示例#1
0
// 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
}
示例#2
0
// 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
}
示例#3
0
// 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()
	)
	// If there's no code to interact with, respond with an appropriate error
	if contract != nil {
		if code := statedb.GetCode(*contract); len(code) == 0 {
			return nil, bind.ErrNoCode
		}
	}
	// 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, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
	gaspool := new(core.GasPool).AddGas(common.MaxBig)

	_, gas, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
	return gas, err
}
示例#4
0
文件: api.go 项目: karalabe/etherapis
// 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
}
示例#5
0
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
}
示例#6
0
// 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
}
示例#7
0
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)

}