diff --git a/common/safeMath.go b/common/safeMath.go new file mode 100644 index 00000000..d5d71f46 --- /dev/null +++ b/common/safeMath.go @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package common + +import "math" + +const ( + MAX_UINT64 = math.MaxUint64 +) + +func SafeSub(x, y uint64) (uint64, bool) { + return x - y, x < y +} + +func SafeAdd(x, y uint64) (uint64, bool) { + return x + y, y > MAX_UINT64-x +} + +func SafeMul(x, y uint64) (uint64, bool) { + if x == 0 || y == 0 { + return 0, false + } + return x * y, y > MAX_UINT64/x +} diff --git a/core/store/ledgerstore/tx_handler.go b/core/store/ledgerstore/tx_handler.go index 2cc992ca..c9502bd3 100644 --- a/core/store/ledgerstore/tx_handler.go +++ b/core/store/ledgerstore/tx_handler.go @@ -54,7 +54,12 @@ func (self *StateStore) HandleDeployTransaction(store store.LedgerStore, stateBa ) if tx.GasPrice != 0 { - if err := isBalanceSufficient(tx, stateBatch); err != nil { + gas, overflow := common.SafeMul(tx.GasLimit, tx.GasPrice) + if overflow { + return fmt.Errorf("gaslimit:%d*gasprice:%d overflow!", tx.GasLimit, tx.GasPrice) + } + + if err := isBalanceSufficient(tx.Payer, stateBatch, gas); err != nil { return err } @@ -67,7 +72,7 @@ func (self *StateStore) HandleDeployTransaction(store store.LedgerStore, stateBa Tx: tx, } - notifies, err = costGas(tx.Payer, tx.GasLimit*tx.GasPrice, config, cache, store) + notifies, err = costGas(tx.Payer, gas, config, cache, store) if err != nil { return err } @@ -94,8 +99,13 @@ func (self *StateStore) HandleInvokeTransaction(store store.LedgerStore, stateBa sysTransFlag := bytes.Compare(code, ninit.COMMIT_DPOS_BYTES) == 0 || block.Header.Height == 0 isCharge := !sysTransFlag && tx.GasPrice != 0 + + gas, overflow := common.SafeMul(tx.GasLimit, tx.GasPrice) + if overflow { + return fmt.Errorf("gaslimit:%d*gasprice:%d overflow!", tx.GasLimit, tx.GasPrice) + } if isCharge { - if err := isBalanceSufficient(tx, stateBatch); err != nil { + if err := isBalanceSufficient(tx.Payer, stateBatch, gas); err != nil { return err } } @@ -133,7 +143,7 @@ func (self *StateStore) HandleInvokeTransaction(store store.LedgerStore, stateBa if totalGas < neovm.TRANSACTION_GAS { totalGas = neovm.TRANSACTION_GAS } - notifies, err = costGas(tx.Payer, totalGas*tx.GasPrice, config, sc.CloneCache, store) + notifies, err = costGas(tx.Payer, gas, config, sc.CloneCache, store) if err != nil { return err } @@ -171,13 +181,13 @@ func genNativeTransferCode(from, to common.Address, value uint64) []byte { } // check whether payer ong balance sufficient -func isBalanceSufficient(tx *types.Transaction, stateBatch *statestore.StateBatch) error { - balance, err := getBalance(stateBatch, tx.Payer, utils.OngContractAddress) +func isBalanceSufficient(payer common.Address, stateBatch *statestore.StateBatch, gas uint64) error { + balance, err := getBalance(stateBatch, payer, utils.OngContractAddress) if err != nil { return err } - if balance < tx.GasLimit*tx.GasPrice { - return fmt.Errorf("payer gas insufficient, need %d , only have %d", tx.GasLimit*tx.GasPrice, balance) + if balance < gas { + return fmt.Errorf("payer gas insufficient, need %d , only have %d", gas, balance) } return nil }