forked from cerc-io/plugeth
core, all: split vm.Context into BlockContext and TxContext (#21672)
* all: core: split vm.Config into BlockConfig and TxConfig * core: core/vm: reset EVM between tx in block instead of creating new * core/vm: added docs
This commit is contained in:
parent
6f4cccf8d2
commit
2045a2bba3
@ -542,10 +542,11 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
|||||||
// Execute the call.
|
// Execute the call.
|
||||||
msg := callMsg{call}
|
msg := callMsg{call}
|
||||||
|
|
||||||
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
|
||||||
// Create a new environment which holds all relevant information
|
// Create a new environment which holds all relevant information
|
||||||
// about the transaction and calling mechanisms.
|
// about the transaction and calling mechanisms.
|
||||||
vmEnv := vm.NewEVM(evmContext, stateDB, b.config, vm.Config{})
|
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{})
|
||||||
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
|
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
|
||||||
|
|
||||||
return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
|
return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
|
||||||
|
@ -110,7 +110,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
txIndex = 0
|
txIndex = 0
|
||||||
)
|
)
|
||||||
gaspool.AddGas(pre.Env.GasLimit)
|
gaspool.AddGas(pre.Env.GasLimit)
|
||||||
vmContext := vm.Context{
|
vmContext := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
Coinbase: pre.Env.Coinbase,
|
Coinbase: pre.Env.Coinbase,
|
||||||
@ -119,7 +119,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
Difficulty: pre.Env.Difficulty,
|
Difficulty: pre.Env.Difficulty,
|
||||||
GasLimit: pre.Env.GasLimit,
|
GasLimit: pre.Env.GasLimit,
|
||||||
GetHash: getHash,
|
GetHash: getHash,
|
||||||
// GasPrice and Origin needs to be set per transaction
|
|
||||||
}
|
}
|
||||||
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
||||||
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
||||||
@ -143,10 +142,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
vmConfig.Tracer = tracer
|
vmConfig.Tracer = tracer
|
||||||
vmConfig.Debug = (tracer != nil)
|
vmConfig.Debug = (tracer != nil)
|
||||||
statedb.Prepare(tx.Hash(), blockHash, txIndex)
|
statedb.Prepare(tx.Hash(), blockHash, txIndex)
|
||||||
vmContext.GasPrice = msg.GasPrice()
|
txContext := core.NewEVMTxContext(msg)
|
||||||
vmContext.Origin = msg.From()
|
|
||||||
|
|
||||||
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
|
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
|
||||||
if chainConfig.IsYoloV2(vmContext.BlockNumber) {
|
if chainConfig.IsYoloV2(vmContext.BlockNumber) {
|
||||||
statedb.AddAddressToAccessList(msg.From())
|
statedb.AddAddressToAccessList(msg.From())
|
||||||
if dst := msg.To(); dst != nil {
|
if dst := msg.To(); dst != nil {
|
||||||
@ -185,7 +183,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
receipt.GasUsed = msgResult.UsedGas
|
receipt.GasUsed = msgResult.UsedGas
|
||||||
// if the transaction created a contract, store the creation address in the receipt.
|
// if the transaction created a contract, store the creation address in the receipt.
|
||||||
if msg.To() == nil {
|
if msg.To() == nil {
|
||||||
receipt.ContractAddress = crypto.CreateAddress(evm.Context.Origin, tx.Nonce())
|
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
||||||
}
|
}
|
||||||
// Set the receipt logs and create a bloom for filtering
|
// Set the receipt logs and create a bloom for filtering
|
||||||
receipt.Logs = statedb.GetLogs(tx.Hash())
|
receipt.Logs = statedb.GetLogs(tx.Hash())
|
||||||
|
@ -671,12 +671,13 @@ func (api *RetestethAPI) AccountRange(ctx context.Context,
|
|||||||
}
|
}
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
signer := types.MakeSigner(api.blockchain.Config(), block.Number())
|
signer := types.MakeSigner(api.blockchain.Config(), block.Number())
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), api.blockchain, nil)
|
||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
// Assemble the transaction call message and return if the requested offset
|
// Assemble the transaction call message and return if the requested offset
|
||||||
msg, _ := tx.AsMessage(signer)
|
msg, _ := tx.AsMessage(signer)
|
||||||
context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
// Not yet the searched for transaction, execute on top of the current state
|
// Not yet the searched for transaction, execute on top of the current state
|
||||||
vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
|
vmenv := vm.NewEVM(context, txContext, statedb, api.blockchain.Config(), vm.Config{})
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||||
return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
||||||
}
|
}
|
||||||
@ -781,12 +782,13 @@ func (api *RetestethAPI) StorageRangeAt(ctx context.Context,
|
|||||||
}
|
}
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
signer := types.MakeSigner(api.blockchain.Config(), block.Number())
|
signer := types.MakeSigner(api.blockchain.Config(), block.Number())
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), api.blockchain, nil)
|
||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
// Assemble the transaction call message and return if the requested offset
|
// Assemble the transaction call message and return if the requested offset
|
||||||
msg, _ := tx.AsMessage(signer)
|
msg, _ := tx.AsMessage(signer)
|
||||||
context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
// Not yet the searched for transaction, execute on top of the current state
|
// Not yet the searched for transaction, execute on top of the current state
|
||||||
vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
|
vmenv := vm.NewEVM(context, txContext, statedb, api.blockchain.Config(), vm.Config{})
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||||
return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
||||||
}
|
}
|
||||||
|
16
core/evm.go
16
core/evm.go
@ -35,8 +35,8 @@ type ChainContext interface {
|
|||||||
GetHeader(common.Hash, uint64) *types.Header
|
GetHeader(common.Hash, uint64) *types.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVMContext creates a new context for use in the EVM.
|
// NewEVMBlockContext creates a new context for use in the EVM.
|
||||||
func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) vm.Context {
|
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
|
||||||
// If we don't have an explicit author (i.e. not mining), extract from the header
|
// If we don't have an explicit author (i.e. not mining), extract from the header
|
||||||
var beneficiary common.Address
|
var beneficiary common.Address
|
||||||
if author == nil {
|
if author == nil {
|
||||||
@ -44,17 +44,23 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
|
|||||||
} else {
|
} else {
|
||||||
beneficiary = *author
|
beneficiary = *author
|
||||||
}
|
}
|
||||||
return vm.Context{
|
return vm.BlockContext{
|
||||||
CanTransfer: CanTransfer,
|
CanTransfer: CanTransfer,
|
||||||
Transfer: Transfer,
|
Transfer: Transfer,
|
||||||
GetHash: GetHashFn(header, chain),
|
GetHash: GetHashFn(header, chain),
|
||||||
Origin: msg.From(),
|
|
||||||
Coinbase: beneficiary,
|
Coinbase: beneficiary,
|
||||||
BlockNumber: new(big.Int).Set(header.Number),
|
BlockNumber: new(big.Int).Set(header.Number),
|
||||||
Time: new(big.Int).SetUint64(header.Time),
|
Time: new(big.Int).SetUint64(header.Time),
|
||||||
Difficulty: new(big.Int).Set(header.Difficulty),
|
Difficulty: new(big.Int).Set(header.Difficulty),
|
||||||
GasLimit: header.GasLimit,
|
GasLimit: header.GasLimit,
|
||||||
GasPrice: new(big.Int).Set(msg.GasPrice()),
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEVMTxContext creates a new transaction context for a single transaction.
|
||||||
|
func NewEVMTxContext(msg Message) vm.TxContext {
|
||||||
|
return vm.TxContext{
|
||||||
|
Origin: msg.From(),
|
||||||
|
GasPrice: new(big.Int).Set(msg.GasPrice()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +86,9 @@ func precacheTransaction(config *params.ChainConfig, bc ChainContext, author *co
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Create the EVM and execute the transaction
|
// Create the EVM and execute the transaction
|
||||||
context := NewEVMContext(msg, header, bc, author)
|
context := NewEVMBlockContext(header, bc, author)
|
||||||
vm := vm.NewEVM(context, statedb, config, cfg)
|
txContext := NewEVMTxContext(msg)
|
||||||
|
vm := vm.NewEVM(context, txContext, statedb, config, cfg)
|
||||||
|
|
||||||
_, err = ApplyMessage(vm, msg, gaspool)
|
_, err = ApplyMessage(vm, msg, gaspool)
|
||||||
return err
|
return err
|
||||||
|
@ -65,10 +65,16 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
||||||
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, 0, err
|
||||||
|
}
|
||||||
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
||||||
receipt, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, header, tx, usedGas, vmenv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
@ -81,34 +87,25 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
return receipts, allLogs, *usedGas, nil
|
return receipts, allLogs, *usedGas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTransaction attempts to apply a transaction to the given state database
|
func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||||
// and uses the input parameters for its environment. It returns the receipt
|
|
||||||
// for the transaction, gas used and an error if the transaction failed,
|
|
||||||
// indicating the block was invalid.
|
|
||||||
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
|
|
||||||
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Create a new context to be used in the EVM environment
|
// Create a new context to be used in the EVM environment
|
||||||
context := NewEVMContext(msg, header, bc, author)
|
txContext := NewEVMTxContext(msg)
|
||||||
// Create a new environment which holds all relevant information
|
// Add addresses to access list if applicable
|
||||||
// about the transaction and calling mechanisms.
|
|
||||||
vmenv := vm.NewEVM(context, statedb, config, cfg)
|
|
||||||
|
|
||||||
if config.IsYoloV2(header.Number) {
|
if config.IsYoloV2(header.Number) {
|
||||||
statedb.AddAddressToAccessList(msg.From())
|
statedb.AddAddressToAccessList(msg.From())
|
||||||
if dst := msg.To(); dst != nil {
|
if dst := msg.To(); dst != nil {
|
||||||
statedb.AddAddressToAccessList(*dst)
|
statedb.AddAddressToAccessList(*dst)
|
||||||
// If it's a create-tx, the destination will be added inside evm.create
|
// If it's a create-tx, the destination will be added inside evm.create
|
||||||
}
|
}
|
||||||
for _, addr := range vmenv.ActivePrecompiles() {
|
for _, addr := range evm.ActivePrecompiles() {
|
||||||
statedb.AddAddressToAccessList(addr)
|
statedb.AddAddressToAccessList(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the evm with the new transaction context.
|
||||||
|
evm.Reset(txContext, statedb)
|
||||||
// Apply the transaction to the current state (included in the env)
|
// Apply the transaction to the current state (included in the env)
|
||||||
result, err := ApplyMessage(vmenv, msg, gp)
|
result, err := ApplyMessage(evm, msg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -128,7 +125,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
|||||||
receipt.GasUsed = result.UsedGas
|
receipt.GasUsed = result.UsedGas
|
||||||
// if the transaction created a contract, store the creation address in the receipt.
|
// if the transaction created a contract, store the creation address in the receipt.
|
||||||
if msg.To() == nil {
|
if msg.To() == nil {
|
||||||
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
|
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
||||||
}
|
}
|
||||||
// Set the receipt logs and create a bloom for filtering
|
// Set the receipt logs and create a bloom for filtering
|
||||||
receipt.Logs = statedb.GetLogs(tx.Hash())
|
receipt.Logs = statedb.GetLogs(tx.Hash())
|
||||||
@ -139,3 +136,18 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
|||||||
|
|
||||||
return receipt, err
|
return receipt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyTransaction attempts to apply a transaction to the given state database
|
||||||
|
// and uses the input parameters for its environment. It returns the receipt
|
||||||
|
// for the transaction, gas used and an error if the transaction failed,
|
||||||
|
// indicating the block was invalid.
|
||||||
|
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
|
||||||
|
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Create a new context to be used in the EVM environment
|
||||||
|
blockContext := NewEVMBlockContext(header, bc, author)
|
||||||
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
|
||||||
|
return applyTransaction(msg, config, bc, author, gp, statedb, header, tx, usedGas, vmenv)
|
||||||
|
}
|
||||||
|
@ -230,8 +230,8 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
}
|
}
|
||||||
msg := st.msg
|
msg := st.msg
|
||||||
sender := vm.AccountRef(msg.From())
|
sender := vm.AccountRef(msg.From())
|
||||||
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
|
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
|
||||||
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.BlockNumber)
|
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
|
||||||
contractCreation := msg.To() == nil
|
contractCreation := msg.To() == nil
|
||||||
|
|
||||||
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
||||||
@ -245,7 +245,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
st.gas -= gas
|
st.gas -= gas
|
||||||
|
|
||||||
// Check clause 6
|
// Check clause 6
|
||||||
if msg.Value().Sign() > 0 && !st.evm.CanTransfer(st.state, msg.From(), msg.Value()) {
|
if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) {
|
||||||
return nil, ErrInsufficientFundsForTransfer
|
return nil, ErrInsufficientFundsForTransfer
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
@ -260,7 +260,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
||||||
}
|
}
|
||||||
st.refundGas()
|
st.refundGas()
|
||||||
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
|
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
|
||||||
|
|
||||||
return &ExecutionResult{
|
return &ExecutionResult{
|
||||||
UsedGas: st.gasUsed(),
|
UsedGas: st.gasUsed(),
|
||||||
|
@ -91,9 +91,9 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
|||||||
return nil, errors.New("no compatible interpreter")
|
return nil, errors.New("no compatible interpreter")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context provides the EVM with auxiliary information. Once provided
|
// BlockContext provides the EVM with auxiliary information. Once provided
|
||||||
// it shouldn't be modified.
|
// it shouldn't be modified.
|
||||||
type Context struct {
|
type BlockContext struct {
|
||||||
// CanTransfer returns whether the account contains
|
// CanTransfer returns whether the account contains
|
||||||
// sufficient ether to transfer the value
|
// sufficient ether to transfer the value
|
||||||
CanTransfer CanTransferFunc
|
CanTransfer CanTransferFunc
|
||||||
@ -102,10 +102,6 @@ type Context struct {
|
|||||||
// GetHash returns the hash corresponding to n
|
// GetHash returns the hash corresponding to n
|
||||||
GetHash GetHashFunc
|
GetHash GetHashFunc
|
||||||
|
|
||||||
// Message information
|
|
||||||
Origin common.Address // Provides information for ORIGIN
|
|
||||||
GasPrice *big.Int // Provides information for GASPRICE
|
|
||||||
|
|
||||||
// Block information
|
// Block information
|
||||||
Coinbase common.Address // Provides information for COINBASE
|
Coinbase common.Address // Provides information for COINBASE
|
||||||
GasLimit uint64 // Provides information for GASLIMIT
|
GasLimit uint64 // Provides information for GASLIMIT
|
||||||
@ -114,6 +110,14 @@ type Context struct {
|
|||||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TxContext provides the EVM with information about a transaction.
|
||||||
|
// All fields can change between transactions.
|
||||||
|
type TxContext struct {
|
||||||
|
// Message information
|
||||||
|
Origin common.Address // Provides information for ORIGIN
|
||||||
|
GasPrice *big.Int // Provides information for GASPRICE
|
||||||
|
}
|
||||||
|
|
||||||
// EVM is the Ethereum Virtual Machine base object and provides
|
// EVM is the Ethereum Virtual Machine base object and provides
|
||||||
// the necessary tools to run a contract on the given state with
|
// the necessary tools to run a contract on the given state with
|
||||||
// the provided context. It should be noted that any error
|
// the provided context. It should be noted that any error
|
||||||
@ -125,7 +129,8 @@ type Context struct {
|
|||||||
// The EVM should never be reused and is not thread safe.
|
// The EVM should never be reused and is not thread safe.
|
||||||
type EVM struct {
|
type EVM struct {
|
||||||
// Context provides auxiliary blockchain related information
|
// Context provides auxiliary blockchain related information
|
||||||
Context
|
Context BlockContext
|
||||||
|
TxContext
|
||||||
// StateDB gives access to the underlying state
|
// StateDB gives access to the underlying state
|
||||||
StateDB StateDB
|
StateDB StateDB
|
||||||
// Depth is the current call stack
|
// Depth is the current call stack
|
||||||
@ -153,17 +158,18 @@ type EVM struct {
|
|||||||
|
|
||||||
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
|
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
|
||||||
// only ever be used *once*.
|
// only ever be used *once*.
|
||||||
func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
|
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
|
||||||
evm := &EVM{
|
evm := &EVM{
|
||||||
Context: ctx,
|
Context: blockCtx,
|
||||||
|
TxContext: txCtx,
|
||||||
StateDB: statedb,
|
StateDB: statedb,
|
||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
chainRules: chainConfig.Rules(ctx.BlockNumber),
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
|
||||||
interpreters: make([]Interpreter, 0, 1),
|
interpreters: make([]Interpreter, 0, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
if chainConfig.IsEWASM(ctx.BlockNumber) {
|
if chainConfig.IsEWASM(blockCtx.BlockNumber) {
|
||||||
// to be implemented by EVM-C and Wagon PRs.
|
// to be implemented by EVM-C and Wagon PRs.
|
||||||
// if vmConfig.EWASMInterpreter != "" {
|
// if vmConfig.EWASMInterpreter != "" {
|
||||||
// extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":")
|
// extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":")
|
||||||
@ -187,6 +193,13 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
|
|||||||
return evm
|
return evm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset resets the EVM with a new transaction context.Reset
|
||||||
|
// This is not threadsafe and should only be done very cautiously.
|
||||||
|
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
|
||||||
|
evm.TxContext = txCtx
|
||||||
|
evm.StateDB = statedb
|
||||||
|
}
|
||||||
|
|
||||||
// Cancel cancels any running EVM operation. This may be called concurrently and
|
// Cancel cancels any running EVM operation. This may be called concurrently and
|
||||||
// it's safe to be called multiple times.
|
// it's safe to be called multiple times.
|
||||||
func (evm *EVM) Cancel() {
|
func (evm *EVM) Cancel() {
|
||||||
@ -233,7 +246,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||||||
}
|
}
|
||||||
evm.StateDB.CreateAccount(addr)
|
evm.StateDB.CreateAccount(addr)
|
||||||
}
|
}
|
||||||
evm.Transfer(evm.StateDB, caller.Address(), addr, value)
|
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
|
||||||
|
|
||||||
// Capture the tracer start/end events in debug mode
|
// Capture the tracer start/end events in debug mode
|
||||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||||
@ -426,7 +439,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||||||
if evm.depth > int(params.CallCreateDepth) {
|
if evm.depth > int(params.CallCreateDepth) {
|
||||||
return nil, common.Address{}, gas, ErrDepth
|
return nil, common.Address{}, gas, ErrDepth
|
||||||
}
|
}
|
||||||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||||
return nil, common.Address{}, gas, ErrInsufficientBalance
|
return nil, common.Address{}, gas, ErrInsufficientBalance
|
||||||
}
|
}
|
||||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||||
@ -447,7 +460,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||||||
if evm.chainRules.IsEIP158 {
|
if evm.chainRules.IsEIP158 {
|
||||||
evm.StateDB.SetNonce(address, 1)
|
evm.StateDB.SetNonce(address, 1)
|
||||||
}
|
}
|
||||||
evm.Transfer(evm.StateDB, caller.Address(), address, value)
|
evm.Context.Transfer(evm.StateDB, caller.Address(), address, value)
|
||||||
|
|
||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
|
@ -87,11 +87,11 @@ func TestEIP2200(t *testing.T) {
|
|||||||
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
||||||
statedb.Finalise(true) // Push the state into the "original" slot
|
statedb.Finalise(true) // Push the state into the "original" slot
|
||||||
|
|
||||||
vmctx := Context{
|
vmctx := BlockContext{
|
||||||
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
|
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
|
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
|
||||||
}
|
}
|
||||||
vmenv := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
||||||
|
|
||||||
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
|
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
|
||||||
if err != tt.failure {
|
if err != tt.failure {
|
||||||
|
@ -438,14 +438,14 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
var upper, lower uint64
|
var upper, lower uint64
|
||||||
upper = interpreter.evm.BlockNumber.Uint64()
|
upper = interpreter.evm.Context.BlockNumber.Uint64()
|
||||||
if upper < 257 {
|
if upper < 257 {
|
||||||
lower = 0
|
lower = 0
|
||||||
} else {
|
} else {
|
||||||
lower = upper - 256
|
lower = upper - 256
|
||||||
}
|
}
|
||||||
if num64 >= lower && num64 < upper {
|
if num64 >= lower && num64 < upper {
|
||||||
num.SetBytes(interpreter.evm.GetHash(num64).Bytes())
|
num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes())
|
||||||
} else {
|
} else {
|
||||||
num.Clear()
|
num.Clear()
|
||||||
}
|
}
|
||||||
@ -453,30 +453,30 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||||
callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Coinbase.Bytes()))
|
callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||||
v, _ := uint256.FromBig(interpreter.evm.Time)
|
v, _ := uint256.FromBig(interpreter.evm.Context.Time)
|
||||||
callContext.stack.push(v)
|
callContext.stack.push(v)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opNumber(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
func opNumber(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||||
v, _ := uint256.FromBig(interpreter.evm.BlockNumber)
|
v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
|
||||||
callContext.stack.push(v)
|
callContext.stack.push(v)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||||
v, _ := uint256.FromBig(interpreter.evm.Difficulty)
|
v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
|
||||||
callContext.stack.push(v)
|
callContext.stack.push(v)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||||
callContext.stack.push(new(uint256.Int).SetUint64(interpreter.evm.GasLimit))
|
callContext.stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +842,7 @@ func makeLog(size int) executionFunc {
|
|||||||
Data: d,
|
Data: d,
|
||||||
// This is a non-consensus field, but assigned here because
|
// This is a non-consensus field, but assigned here because
|
||||||
// core/state doesn't know the current block number.
|
// core/state doesn't know the current block number.
|
||||||
BlockNumber: interpreter.evm.BlockNumber.Uint64(),
|
BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -92,7 +92,7 @@ func init() {
|
|||||||
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
|
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
rstack = newReturnStack()
|
rstack = newReturnStack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
@ -192,7 +192,7 @@ func TestSAR(t *testing.T) {
|
|||||||
|
|
||||||
func TestAddMod(t *testing.T) {
|
func TestAddMod(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
@ -231,7 +231,7 @@ func TestAddMod(t *testing.T) {
|
|||||||
// getResult is a convenience function to generate the expected values
|
// getResult is a convenience function to generate the expected values
|
||||||
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
|
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack, rstack = newstack(), newReturnStack()
|
stack, rstack = newstack(), newReturnStack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
interpreter = env.interpreter.(*EVMInterpreter)
|
interpreter = env.interpreter.(*EVMInterpreter)
|
||||||
@ -281,7 +281,7 @@ func TestJsonTestcases(t *testing.T) {
|
|||||||
|
|
||||||
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack, rstack = newstack(), newReturnStack()
|
stack, rstack = newstack(), newReturnStack()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||||
)
|
)
|
||||||
@ -515,7 +515,7 @@ func BenchmarkOpIsZero(b *testing.B) {
|
|||||||
|
|
||||||
func TestOpMstore(t *testing.T) {
|
func TestOpMstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack, rstack = newstack(), newReturnStack()
|
stack, rstack = newstack(), newReturnStack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||||
@ -539,7 +539,7 @@ func TestOpMstore(t *testing.T) {
|
|||||||
|
|
||||||
func BenchmarkOpMstore(bench *testing.B) {
|
func BenchmarkOpMstore(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack, rstack = newstack(), newReturnStack()
|
stack, rstack = newstack(), newReturnStack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||||
@ -560,7 +560,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkOpSHA3(bench *testing.B) {
|
func BenchmarkOpSHA3(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack, rstack = newstack(), newReturnStack()
|
stack, rstack = newstack(), newReturnStack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||||
|
@ -51,7 +51,7 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
|||||||
|
|
||||||
func TestStoreCapture(t *testing.T) {
|
func TestStoreCapture(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, &dummyStatedb{}, params.TestChainConfig, Config{})
|
||||||
logger = NewStructLogger(nil)
|
logger = NewStructLogger(nil)
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
|
@ -22,18 +22,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewEnv(cfg *Config) *vm.EVM {
|
func NewEnv(cfg *Config) *vm.EVM {
|
||||||
context := vm.Context{
|
txContext := vm.TxContext{
|
||||||
|
Origin: cfg.Origin,
|
||||||
|
GasPrice: cfg.GasPrice,
|
||||||
|
}
|
||||||
|
blockContext := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
GetHash: cfg.GetHashFn,
|
GetHash: cfg.GetHashFn,
|
||||||
Origin: cfg.Origin,
|
|
||||||
Coinbase: cfg.Coinbase,
|
Coinbase: cfg.Coinbase,
|
||||||
BlockNumber: cfg.BlockNumber,
|
BlockNumber: cfg.BlockNumber,
|
||||||
Time: cfg.Time,
|
Time: cfg.Time,
|
||||||
Difficulty: cfg.Difficulty,
|
Difficulty: cfg.Difficulty,
|
||||||
GasLimit: cfg.GasLimit,
|
GasLimit: cfg.GasLimit,
|
||||||
GasPrice: cfg.GasPrice,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm.NewEVM(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
|||||||
vmenv = NewEnv(cfg)
|
vmenv = NewEnv(cfg)
|
||||||
sender = vm.AccountRef(cfg.Origin)
|
sender = vm.AccountRef(cfg.Origin)
|
||||||
)
|
)
|
||||||
if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
|
if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
|
||||||
cfg.State.AddAddressToAccessList(cfg.Origin)
|
cfg.State.AddAddressToAccessList(cfg.Origin)
|
||||||
cfg.State.AddAddressToAccessList(address)
|
cfg.State.AddAddressToAccessList(address)
|
||||||
for _, addr := range vmenv.ActivePrecompiles() {
|
for _, addr := range vmenv.ActivePrecompiles() {
|
||||||
@ -150,7 +150,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
|||||||
vmenv = NewEnv(cfg)
|
vmenv = NewEnv(cfg)
|
||||||
sender = vm.AccountRef(cfg.Origin)
|
sender = vm.AccountRef(cfg.Origin)
|
||||||
)
|
)
|
||||||
if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
|
if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
|
||||||
cfg.State.AddAddressToAccessList(cfg.Origin)
|
cfg.State.AddAddressToAccessList(cfg.Origin)
|
||||||
for _, addr := range vmenv.ActivePrecompiles() {
|
for _, addr := range vmenv.ActivePrecompiles() {
|
||||||
cfg.State.AddAddressToAccessList(addr)
|
cfg.State.AddAddressToAccessList(addr)
|
||||||
@ -178,7 +178,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
|
|||||||
vmenv := NewEnv(cfg)
|
vmenv := NewEnv(cfg)
|
||||||
|
|
||||||
sender := cfg.State.GetOrNewStateObject(cfg.Origin)
|
sender := cfg.State.GetOrNewStateObject(cfg.Origin)
|
||||||
if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
|
if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
|
||||||
cfg.State.AddAddressToAccessList(cfg.Origin)
|
cfg.State.AddAddressToAccessList(cfg.Origin)
|
||||||
cfg.State.AddAddressToAccessList(address)
|
cfg.State.AddAddressToAccessList(address)
|
||||||
for _, addr := range vmenv.ActivePrecompiles() {
|
for _, addr := range vmenv.ActivePrecompiles() {
|
||||||
|
@ -194,8 +194,9 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
|||||||
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
||||||
vmError := func() error { return nil }
|
vmError := func() error { return nil }
|
||||||
|
|
||||||
context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
|
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
|
||||||
|
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
||||||
|
@ -203,13 +203,11 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
|
|||||||
// Fetch and execute the next block trace tasks
|
// Fetch and execute the next block trace tasks
|
||||||
for task := range tasks {
|
for task := range tasks {
|
||||||
signer := types.MakeSigner(api.eth.blockchain.Config(), task.block.Number())
|
signer := types.MakeSigner(api.eth.blockchain.Config(), task.block.Number())
|
||||||
|
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.eth.blockchain, nil)
|
||||||
// Trace all the transactions contained within
|
// Trace all the transactions contained within
|
||||||
for i, tx := range task.block.Transactions() {
|
for i, tx := range task.block.Transactions() {
|
||||||
msg, _ := tx.AsMessage(signer)
|
msg, _ := tx.AsMessage(signer)
|
||||||
vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil)
|
res, err := api.traceTx(ctx, msg, blockCtx, task.statedb, config)
|
||||||
|
|
||||||
res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
task.results[i] = &txTraceResult{Error: err.Error()}
|
task.results[i] = &txTraceResult{Error: err.Error()}
|
||||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||||
@ -473,17 +471,15 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
|||||||
if threads > len(txs) {
|
if threads > len(txs) {
|
||||||
threads = len(txs)
|
threads = len(txs)
|
||||||
}
|
}
|
||||||
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
|
||||||
for th := 0; th < threads; th++ {
|
for th := 0; th < threads; th++ {
|
||||||
pend.Add(1)
|
pend.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer pend.Done()
|
defer pend.Done()
|
||||||
|
|
||||||
// Fetch and execute the next transaction trace tasks
|
// Fetch and execute the next transaction trace tasks
|
||||||
for task := range jobs {
|
for task := range jobs {
|
||||||
msg, _ := txs[task.index].AsMessage(signer)
|
msg, _ := txs[task.index].AsMessage(signer)
|
||||||
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
|
res, err := api.traceTx(ctx, msg, blockCtx, task.statedb, config)
|
||||||
|
|
||||||
res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results[task.index] = &txTraceResult{Error: err.Error()}
|
results[task.index] = &txTraceResult{Error: err.Error()}
|
||||||
continue
|
continue
|
||||||
@ -500,9 +496,9 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
|||||||
|
|
||||||
// Generate the next state snapshot fast without tracing
|
// Generate the next state snapshot fast without tracing
|
||||||
msg, _ := tx.AsMessage(signer)
|
msg, _ := tx.AsMessage(signer)
|
||||||
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
|
||||||
vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{})
|
vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.eth.blockchain.Config(), vm.Config{})
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||||
failed = err
|
failed = err
|
||||||
break
|
break
|
||||||
@ -565,6 +561,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
|
|||||||
signer = types.MakeSigner(api.eth.blockchain.Config(), block.Number())
|
signer = types.MakeSigner(api.eth.blockchain.Config(), block.Number())
|
||||||
dumps []string
|
dumps []string
|
||||||
chainConfig = api.eth.blockchain.Config()
|
chainConfig = api.eth.blockchain.Config()
|
||||||
|
vmctx = core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
|
||||||
canon = true
|
canon = true
|
||||||
)
|
)
|
||||||
// Check if there are any overrides: the caller may wish to enable a future
|
// Check if there are any overrides: the caller may wish to enable a future
|
||||||
@ -587,13 +584,12 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
|
|||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// Prepare the trasaction for un-traced execution
|
// Prepare the trasaction for un-traced execution
|
||||||
var (
|
var (
|
||||||
msg, _ = tx.AsMessage(signer)
|
msg, _ = tx.AsMessage(signer)
|
||||||
vmctx = core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
|
txContext = core.NewEVMTxContext(msg)
|
||||||
|
vmConf vm.Config
|
||||||
vmConf vm.Config
|
dump *os.File
|
||||||
dump *os.File
|
writer *bufio.Writer
|
||||||
writer *bufio.Writer
|
err error
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
// If the transaction needs tracing, swap out the configs
|
// If the transaction needs tracing, swap out the configs
|
||||||
if tx.Hash() == txHash || txHash == (common.Hash{}) {
|
if tx.Hash() == txHash || txHash == (common.Hash{}) {
|
||||||
@ -617,7 +613,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
vmenv := vm.NewEVM(vmctx, statedb, chainConfig, vmConf)
|
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
||||||
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
||||||
if writer != nil {
|
if writer != nil {
|
||||||
writer.Flush()
|
writer.Flush()
|
||||||
@ -776,18 +772,19 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.CallArgs,
|
|||||||
|
|
||||||
// Execute the trace
|
// Execute the trace
|
||||||
msg := args.ToMessage(api.eth.APIBackend.RPCGasCap())
|
msg := args.ToMessage(api.eth.APIBackend.RPCGasCap())
|
||||||
vmctx := core.NewEVMContext(msg, header, api.eth.blockchain, nil)
|
vmctx := core.NewEVMBlockContext(header, api.eth.blockchain, nil)
|
||||||
return api.traceTx(ctx, msg, vmctx, statedb, config)
|
return api.traceTx(ctx, msg, vmctx, statedb, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// traceTx configures a new tracer according to the provided configuration, and
|
// traceTx configures a new tracer according to the provided configuration, and
|
||||||
// executes the given message in the provided environment. The return value will
|
// executes the given message in the provided environment. The return value will
|
||||||
// be tracer dependent.
|
// be tracer dependent.
|
||||||
func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||||
// Assemble the structured logger or the JavaScript tracer
|
// Assemble the structured logger or the JavaScript tracer
|
||||||
var (
|
var (
|
||||||
tracer vm.Tracer
|
tracer vm.Tracer
|
||||||
err error
|
err error
|
||||||
|
txContext = core.NewEVMTxContext(message)
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
case config != nil && config.Tracer != nil:
|
case config != nil && config.Tracer != nil:
|
||||||
@ -817,7 +814,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
|
|||||||
tracer = vm.NewStructLogger(config.LogConfig)
|
tracer = vm.NewStructLogger(config.LogConfig)
|
||||||
}
|
}
|
||||||
// Run the transaction with tracing enabled.
|
// Run the transaction with tracing enabled.
|
||||||
vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer})
|
vmenv := vm.NewEVM(vmctx, txContext, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
|
||||||
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -847,19 +844,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
// computeTxEnv returns the execution environment of a certain transaction.
|
// computeTxEnv returns the execution environment of a certain transaction.
|
||||||
func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) {
|
func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
|
||||||
// Create the parent state database
|
// Create the parent state database
|
||||||
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
|
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
return nil, vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash())
|
return nil, vm.BlockContext{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash())
|
||||||
}
|
}
|
||||||
statedb, err := api.computeStateDB(parent, reexec)
|
statedb, err := api.computeStateDB(parent, reexec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, vm.Context{}, nil, err
|
return nil, vm.BlockContext{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if txIndex == 0 && len(block.Transactions()) == 0 {
|
if txIndex == 0 && len(block.Transactions()) == 0 {
|
||||||
return nil, vm.Context{}, statedb, nil
|
return nil, vm.BlockContext{}, statedb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
@ -868,18 +865,19 @@ func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec
|
|||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
// Assemble the transaction call message and return if the requested offset
|
// Assemble the transaction call message and return if the requested offset
|
||||||
msg, _ := tx.AsMessage(signer)
|
msg, _ := tx.AsMessage(signer)
|
||||||
context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
|
||||||
if idx == txIndex {
|
if idx == txIndex {
|
||||||
return msg, context, statedb, nil
|
return msg, context, statedb, nil
|
||||||
}
|
}
|
||||||
// Not yet the searched for transaction, execute on top of the current state
|
// Not yet the searched for transaction, execute on top of the current state
|
||||||
vmenv := vm.NewEVM(context, statedb, api.eth.blockchain.Config(), vm.Config{})
|
vmenv := vm.NewEVM(context, txContext, statedb, api.eth.blockchain.Config(), vm.Config{})
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||||
return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
||||||
}
|
}
|
||||||
// Ensure any modifications are committed to the state
|
// Ensure any modifications are committed to the state
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
||||||
}
|
}
|
||||||
return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
||||||
}
|
}
|
||||||
|
@ -545,7 +545,7 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
|
|||||||
if jst.err == nil {
|
if jst.err == nil {
|
||||||
// Initialize the context if it wasn't done yet
|
// Initialize the context if it wasn't done yet
|
||||||
if !jst.inited {
|
if !jst.inited {
|
||||||
jst.ctx["block"] = env.BlockNumber.Uint64()
|
jst.ctx["block"] = env.Context.BlockNumber.Uint64()
|
||||||
jst.inited = true
|
jst.inited = true
|
||||||
}
|
}
|
||||||
// If tracing was interrupted, set the error and stop
|
// If tracing was interrupted, set the error and stop
|
||||||
|
@ -51,7 +51,7 @@ type dummyStatedb struct {
|
|||||||
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
||||||
|
|
||||||
func runTrace(tracer *Tracer) (json.RawMessage, error) {
|
func runTrace(tracer *Tracer) (json.RawMessage, error) {
|
||||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
|
||||||
contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
|
contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
||||||
@ -166,7 +166,7 @@ func TestHaltBetweenSteps(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||||
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
|
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
|
||||||
|
|
||||||
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, nil, contract, 0, nil)
|
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, nil, contract, 0, nil)
|
||||||
|
@ -143,16 +143,18 @@ func TestPrestateTracerCreate2(t *testing.T) {
|
|||||||
result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
|
result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
|
||||||
*/
|
*/
|
||||||
origin, _ := signer.Sender(tx)
|
origin, _ := signer.Sender(tx)
|
||||||
context := vm.Context{
|
txContext := vm.TxContext{
|
||||||
|
Origin: origin,
|
||||||
|
GasPrice: big.NewInt(1),
|
||||||
|
}
|
||||||
|
context := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
Origin: origin,
|
|
||||||
Coinbase: common.Address{},
|
Coinbase: common.Address{},
|
||||||
BlockNumber: new(big.Int).SetUint64(8000000),
|
BlockNumber: new(big.Int).SetUint64(8000000),
|
||||||
Time: new(big.Int).SetUint64(5),
|
Time: new(big.Int).SetUint64(5),
|
||||||
Difficulty: big.NewInt(0x30000),
|
Difficulty: big.NewInt(0x30000),
|
||||||
GasLimit: uint64(6000000),
|
GasLimit: uint64(6000000),
|
||||||
GasPrice: big.NewInt(1),
|
|
||||||
}
|
}
|
||||||
alloc := core.GenesisAlloc{}
|
alloc := core.GenesisAlloc{}
|
||||||
|
|
||||||
@ -175,7 +177,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
|
||||||
msg, err := tx.AsMessage(signer)
|
msg, err := tx.AsMessage(signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -230,17 +232,18 @@ func TestCallTracer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
|
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
|
||||||
origin, _ := signer.Sender(tx)
|
origin, _ := signer.Sender(tx)
|
||||||
|
txContext := vm.TxContext{
|
||||||
context := vm.Context{
|
Origin: origin,
|
||||||
|
GasPrice: tx.GasPrice(),
|
||||||
|
}
|
||||||
|
context := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
Origin: origin,
|
|
||||||
Coinbase: test.Context.Miner,
|
Coinbase: test.Context.Miner,
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||||
Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
|
Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
|
||||||
Difficulty: (*big.Int)(test.Context.Difficulty),
|
Difficulty: (*big.Int)(test.Context.Difficulty),
|
||||||
GasLimit: uint64(test.Context.GasLimit),
|
GasLimit: uint64(test.Context.GasLimit),
|
||||||
GasPrice: tx.GasPrice(),
|
|
||||||
}
|
}
|
||||||
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
|
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
|
||||||
|
|
||||||
@ -249,7 +252,7 @@ func TestCallTracer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
|
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
|
||||||
msg, err := tx.AsMessage(signer)
|
msg, err := tx.AsMessage(signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -171,8 +171,9 @@ func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
|
||||||
context := core.NewEVMContext(msg, header, b.eth.blockchain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
return vm.NewEVM(context, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
|
context := core.NewEVMBlockContext(header, b.eth.blockchain, nil)
|
||||||
|
return vm.NewEVM(context, txContext, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
||||||
|
@ -130,8 +130,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||||||
|
|
||||||
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
|
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
|
||||||
|
|
||||||
context := core.NewEVMContext(msg, header, bc, nil)
|
context := core.NewEVMBlockContext(header, bc, nil)
|
||||||
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
vmenv := vm.NewEVM(context, txContext, statedb, config, vm.Config{})
|
||||||
|
|
||||||
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
|
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
|
||||||
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
||||||
@ -143,8 +144,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||||||
state := light.NewState(ctx, header, lc.Odr())
|
state := light.NewState(ctx, header, lc.Odr())
|
||||||
state.SetBalance(bankAddr, math.MaxBig256)
|
state.SetBalance(bankAddr, math.MaxBig256)
|
||||||
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
|
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
|
||||||
context := core.NewEVMContext(msg, header, lc, nil)
|
context := core.NewEVMBlockContext(header, lc, nil)
|
||||||
vmenv := vm.NewEVM(context, state, config, vm.Config{})
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{})
|
||||||
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
||||||
result, _ := core.ApplyMessage(vmenv, msg, gp)
|
result, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
if state.Error() == nil {
|
if state.Error() == nil {
|
||||||
|
@ -195,8 +195,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
|
|||||||
// Perform read-only call.
|
// Perform read-only call.
|
||||||
st.SetBalance(testBankAddress, math.MaxBig256)
|
st.SetBalance(testBankAddress, math.MaxBig256)
|
||||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
|
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
|
||||||
context := core.NewEVMContext(msg, header, chain, nil)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
vmenv := vm.NewEVM(context, st, config, vm.Config{})
|
context := core.NewEVMBlockContext(header, chain, nil)
|
||||||
|
vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{})
|
||||||
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
||||||
result, _ := core.ApplyMessage(vmenv, msg, gp)
|
result, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
res = append(res, result.Return()...)
|
res = append(res, result.Return()...)
|
||||||
|
@ -182,9 +182,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, common.Hash{}, err
|
return nil, nil, common.Hash{}, err
|
||||||
}
|
}
|
||||||
context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||||
context.GetHash = vmTestBlockHash
|
context.GetHash = vmTestBlockHash
|
||||||
evm := vm.NewEVM(context, statedb, config, vmconfig)
|
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||||
|
|
||||||
if config.IsYoloV2(context.BlockNumber) {
|
if config.IsYoloV2(context.BlockNumber) {
|
||||||
statedb.AddAddressToAccessList(msg.From())
|
statedb.AddAddressToAccessList(msg.From())
|
||||||
|
@ -138,20 +138,22 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
|
|||||||
return core.CanTransfer(db, address, amount)
|
return core.CanTransfer(db, address, amount)
|
||||||
}
|
}
|
||||||
transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {}
|
transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {}
|
||||||
context := vm.Context{
|
txContext := vm.TxContext{
|
||||||
|
Origin: t.json.Exec.Origin,
|
||||||
|
GasPrice: t.json.Exec.GasPrice,
|
||||||
|
}
|
||||||
|
context := vm.BlockContext{
|
||||||
CanTransfer: canTransfer,
|
CanTransfer: canTransfer,
|
||||||
Transfer: transfer,
|
Transfer: transfer,
|
||||||
GetHash: vmTestBlockHash,
|
GetHash: vmTestBlockHash,
|
||||||
Origin: t.json.Exec.Origin,
|
|
||||||
Coinbase: t.json.Env.Coinbase,
|
Coinbase: t.json.Env.Coinbase,
|
||||||
BlockNumber: new(big.Int).SetUint64(t.json.Env.Number),
|
BlockNumber: new(big.Int).SetUint64(t.json.Env.Number),
|
||||||
Time: new(big.Int).SetUint64(t.json.Env.Timestamp),
|
Time: new(big.Int).SetUint64(t.json.Env.Timestamp),
|
||||||
GasLimit: t.json.Env.GasLimit,
|
GasLimit: t.json.Env.GasLimit,
|
||||||
Difficulty: t.json.Env.Difficulty,
|
Difficulty: t.json.Env.Difficulty,
|
||||||
GasPrice: t.json.Exec.GasPrice,
|
|
||||||
}
|
}
|
||||||
vmconfig.NoRecursion = true
|
vmconfig.NoRecursion = true
|
||||||
return vm.NewEVM(context, statedb, params.MainnetChainConfig, vmconfig)
|
return vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vmconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func vmTestBlockHash(n uint64) common.Hash {
|
func vmTestBlockHash(n uint64) common.Hash {
|
||||||
|
Loading…
Reference in New Issue
Block a user