func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"]))) data = common.FromHex(tx["data"]) gas = common.Big(tx["gasLimit"]) price = common.Big(tx["gasPrice"]) value = common.Big(tx["value"]) nonce = common.Big(tx["nonce"]).Uint64() caddr = common.HexToAddress(env["currentCoinbase"]) ) var to *common.Address if len(tx["to"]) > 2 { t := common.HexToAddress(tx["to"]) to = &t } // Set pre compiled contracts vm.Precompiled = vm.PrecompiledContracts() snapshot := statedb.Copy() coinbase := statedb.GetOrNewStateObject(caddr) coinbase.SetGasLimit(common.Big(env["currentGasLimit"])) message := NewMessage(common.BytesToAddress(keyPair.Address()), to, data, value, gas, price, nonce) vmenv := NewEnvFromMap(statedb, env, tx) vmenv.origin = common.BytesToAddress(keyPair.Address()) ret, _, err := core.ApplyMessage(vmenv, message, coinbase) if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) { statedb.Set(snapshot) } statedb.Update() return ret, vmenv.state.Logs(), vmenv.Gas, err }
func RunState(ruleSet RuleSet, statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) { var ( data = common.FromHex(tx["data"]) gas = common.Big(tx["gasLimit"]) price = common.Big(tx["gasPrice"]) value = common.Big(tx["value"]) nonce = common.Big(tx["nonce"]).Uint64() ) var to *common.Address if len(tx["to"]) > 2 { t := common.HexToAddress(tx["to"]) to = &t } // Set pre compiled contracts vm.Precompiled = vm.PrecompiledContracts() snapshot := statedb.Copy() gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) key, _ := hex.DecodeString(tx["secretKey"]) addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey) message := NewMessage(addr, to, data, value, gas, price, nonce) vmenv := NewEnvFromMap(ruleSet, statedb, env, tx) vmenv.origin = addr ret, _, err := core.ApplyMessage(vmenv, message, gaspool) if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) { statedb.Set(snapshot) } statedb.Commit() return ret, vmenv.state.Logs(), vmenv.Gas, err }
// ContractCall implements ContractCaller.ContractCall, executing the specified // contract with the given input data. func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) { // Create a copy of the current state db to screw around with var ( block *types.Block statedb *state.StateDB ) if pending { block, statedb = b.pendingBlock, b.pendingState.Copy() } else { block = b.blockchain.CurrentBlock() statedb, _ = b.blockchain.State() } // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(common.Address{}) from.SetBalance(common.MaxBig) // Assemble the call invocation to measure the gas usage msg := callmsg{ from: from, to: &contract, gasPrice: new(big.Int), gasLimit: common.MaxBig, value: new(big.Int), data: data, } // Execute the call and return vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) out, _, err := core.ApplyMessage(vmenv, msg, gaspool) return out, err }
// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the // requested code against the currently pending block/state and returning the used // gas. func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { // Create a copy of the currently pending state db to screw around with var ( block = b.pendingBlock statedb = b.pendingState.Copy() ) // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(sender) from.SetBalance(common.MaxBig) // Assemble the call invocation to measure the gas usage msg := callmsg{ from: from, to: contract, gasPrice: new(big.Int), gasLimit: common.MaxBig, value: value, data: data, } // Execute the call and return vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) _, gas, err := core.ApplyMessage(vmenv, msg, gaspool) return gas, err }
func (app *EthereumApplication) AppendTx(txBytes []byte) (retCode types.RetCode, result []byte, log string) { // decode and run tx tx := new(ethtypes.Transaction) rlpStream := rlp.NewStream(bytes.NewBuffer(txBytes), 0) if err := tx.DecodeRLP(rlpStream); err != nil { return types.RetCodeEncodingError, result, log } gpi := big.NewInt(1000000000) // a billion ... TODO: configurable gp := core.GasPool(*gpi) // XXX: this feels so wrong!? ret, gas, err := core.ApplyMessage(NewEnv(app.stateDB, tx), tx, &gp) if err != nil { if err == ethtypes.ErrInvalidSig || err == ethtypes.ErrInvalidPubKey { return types.RetCodeUnauthorized, result, err.Error() } else if core.IsNonceErr(err) { return types.RetCodeBadNonce, result, err.Error() } else if core.IsInvalidTxErr(err) { return types.RetCodeInsufficientFees, result, err.Error() // bad gas or value transfer } else { return types.RetCodeUnauthorized, result, err.Error() // bad pubkey recovery } } _, _ = ret, gas return types.RetCodeOK, result, log }
// Call forms a transaction from the given arguments and tries to execute it on // a private VM with a copy of the state. Any changes are therefore only temporary // and not part of the actual state. This allows for local execution/queries. func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { block := be.bc.CurrentBlock() statedb, err := state.New(block.Root(), be.chainDb) if err != nil { return "", "", err } var from *state.StateObject if len(fromStr) == 0 { accounts, err := be.am.Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := be.bc.CurrentBlock().Header() vmenv := core.NewEnv(statedb, be.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) return common.ToHex(res), gas.String(), err }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { statedb := self.State().State().Copy() var from *state.StateObject if len(fromStr) == 0 { accounts, err := self.backend.AccountManager().Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) from.SetGasLimit(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = self.DefaultGasPrice() } header := self.CurrentBlock().Header() vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header) res, gas, err := core.ApplyMessage(vmenv, msg, from) return common.ToHex(res), gas.String(), err }
// applies queued transactions originating from address onto the latest state // and creates a block // only used in tests // - could be removed in favour of mining on testdag (natspec e2e + networking) // + filters func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) { block := self.backend.ChainManager().NewBlock(address) coinbase := statedb.GetStateObject(address) coinbase.SetGasPool(big.NewInt(10000000)) txs := self.backend.TxPool().GetQueuedTransactions() for i := 0; i < len(txs); i++ { for _, tx := range txs { if tx.Nonce() == txc { _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, block), tx, coinbase) if err != nil { panic(err) } txc++ } } } xeth := self.WithState(statedb) return txc, xeth }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { statedb := self.State().State() //self.eth.ChainManager().TransState() var from *state.StateObject if len(fromStr) == 0 { accounts, err := self.backend.AccountManager().Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(common.BytesToAddress(accounts[0].Address)) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetGasPool(self.backend.ChainManager().GasLimit()) msg := callmsg{ from: from, to: common.HexToAddress(toStr), gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = DefaultGas() } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = DefaultGasPrice() } block := self.CurrentBlock() vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, block) res, gas, err := core.ApplyMessage(vmenv, msg, from) return common.ToHex(res), gas.String(), err }
func (self *testFrontend) applyTxs() { cb := common.HexToAddress(self.coinbase) block := self.ethereum.ChainManager().NewBlock(cb) coinbase := self.stateDb.GetStateObject(cb) coinbase.SetGasPool(big.NewInt(10000000)) txs := self.ethereum.TxPool().GetQueuedTransactions() for i := 0; i < len(txs); i++ { for _, tx := range txs { //self.t.Logf("%v %v %v", i, tx.Nonce(), self.txc) if tx.Nonce() == self.txc { _, gas, err := core.ApplyMessage(core.NewEnv(self.stateDb, self.ethereum.ChainManager(), tx, block), tx, coinbase) //self.ethereum.TxPool().RemoveSet([]*types.Transaction{tx}) self.t.Logf("ApplyMessage: gas %v err %v", gas, err) self.txc++ } } } //self.ethereum.TxPool().RemoveSet(txs) self.xeth = self.xeth.WithState(self.stateDb) }