From 4ce98c44a2b7260572412143f3c2639914393f70 Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Wed, 6 Aug 2025 13:02:29 +0800 Subject: [PATCH] core/types: remove message #25977 --- accounts/abi/bind/backends/simulated.go | 44 ++- core/evm.go | 6 +- core/state_prefetcher.go | 4 +- core/state_processor.go | 10 +- core/state_transition.go | 309 ++++++++++-------- core/token_validator.go | 44 ++- core/types/transaction.go | 101 ------ eth/api_backend.go | 6 +- eth/state_accessor.go | 4 +- eth/tracers/api.go | 20 +- eth/tracers/api_test.go | 4 +- .../internal/tracetest/calltrace_test.go | 8 +- .../internal/tracetest/flat_calltrace_test.go | 2 +- .../internal/tracetest/prestate_test.go | 2 +- eth/tracers/tracers_test.go | 2 +- internal/ethapi/api.go | 9 +- internal/ethapi/backend.go | 2 +- internal/ethapi/transaction_args.go | 19 +- internal/ethapi/transaction_args_test.go | 2 +- tests/state_test_util.go | 16 +- 20 files changed, 275 insertions(+), 339 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 907510a9bf4b..b8b2d7467d81 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -30,8 +30,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/XDCx" "github.com/XinFinOrg/XDPoSChain/XDCxlending" "github.com/XinFinOrg/XDPoSChain/accounts" - "github.com/XinFinOrg/XDPoSChain/node" - "github.com/XinFinOrg/XDPoSChain/accounts/abi" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/accounts/keystore" @@ -52,6 +50,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/event" "github.com/XinFinOrg/XDPoSChain/log" + "github.com/XinFinOrg/XDPoSChain/node" "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rpc" ) @@ -735,18 +734,33 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM if call.Value == nil { call.Value = new(big.Int) } + // Set infinite balance to the fake caller account. from := stateDB.GetOrNewStateObject(call.From) from.SetBalance(math.MaxBig256) + // Execute the call. - msg := callMsg{call} + msg := &core.Message{ + From: call.From, + To: call.To, + Value: call.Value, + GasLimit: call.Gas, + GasPrice: call.GasPrice, + GasFeeCap: call.GasFeeCap, + GasTipCap: call.GasTipCap, + Data: call.Data, + AccessList: call.AccessList, + SkipAccountChecks: true, + } feeCapacity := state.GetTRC21FeeCapacityFromState(stateDB) - if msg.To() != nil { - if value, ok := feeCapacity[*msg.To()]; ok { - msg.CallMsg.BalanceTokenFee = value + if msg.To != nil { + if value, ok := feeCapacity[*msg.To]; ok { + msg.BalanceTokenFee = value } } + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. txContext := core.NewEVMTxContext(msg) evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil) // Create a new environment which holds all relevant information @@ -920,24 +934,6 @@ func (b *SimulatedBackend) BlockChain() *core.BlockChain { return b.blockchain } -// callMsg implements core.Message to allow passing it as a transaction simulator. -type callMsg struct { - ethereum.CallMsg -} - -func (m callMsg) From() common.Address { return m.CallMsg.From } -func (m callMsg) Nonce() uint64 { return 0 } -func (m callMsg) IsFake() bool { return true } -func (m callMsg) To() *common.Address { return m.CallMsg.To } -func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } -func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap } -func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap } -func (m callMsg) Gas() uint64 { return m.CallMsg.Gas } -func (m callMsg) Value() *big.Int { return m.CallMsg.Value } -func (m callMsg) Data() []byte { return m.CallMsg.Data } -func (m callMsg) BalanceTokenFee() *big.Int { return m.CallMsg.BalanceTokenFee } -func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList } - // filterBackend implements filters.Backend to support filtering for logs without // taking bloom-bits acceleration structures into account. type filterBackend struct { diff --git a/core/evm.go b/core/evm.go index 258459b67569..6e250fd08727 100644 --- a/core/evm.go +++ b/core/evm.go @@ -69,10 +69,10 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common } // NewEVMTxContext creates a new transaction context for a single transaction. -func NewEVMTxContext(msg Message) vm.TxContext { +func NewEVMTxContext(msg *Message) vm.TxContext { return vm.TxContext{ - Origin: msg.From(), - GasPrice: new(big.Int).Set(msg.GasPrice()), + Origin: msg.From, + GasPrice: new(big.Int).Set(msg.GasPrice), } } diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 62910989d538..1d79eca6e93d 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -64,7 +64,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c return } // Convert the transaction into an executable message and pre-cache its sender - msg, err := tx.AsMessage(signer, nil, nil, header.BaseFee) + msg, err := TransactionToMessage(tx, signer, nil, nil, header.BaseFee) if err != nil { return // Also invalid block, bail out } @@ -86,7 +86,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c // precacheTransaction attempts to apply a transaction to the given state database // and uses the input parameters for its environment. The goal is not to execute // the transaction successfully, rather to warm up touched data slots. -func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { +func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { // Update the evm with the new transaction context. evm.Reset(NewEVMTxContext(msg), statedb) // Add addresses to access list if applicable diff --git a/core/state_processor.go b/core/state_processor.go index c4812d39cd45..53e41f398d93 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -246,8 +246,7 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* balanceFee = value } } - // msg, err := tx.AsMessage(types.MakeSigner(config, blockNumber), balanceFee, blockNumber) - msg, err := tx.AsMessage(types.MakeSigner(config, blockNumber), balanceFee, blockNumber, baseFee) + msg, err := TransactionToMessage(tx, types.MakeSigner(config, blockNumber), balanceFee, blockNumber, baseFee) if err != nil { return nil, 0, err, false } @@ -386,7 +385,7 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* blockMap[9147453] = "0x3538a544021c07869c16b764424c5987409cba48" blockMap[9147459] = "0xe187cf86c2274b1f16e8225a7da9a75aba4f1f5f" - addrFrom := msg.From().Hex() + addrFrom := msg.From.Hex() currentBlockNumber := blockNumber.Int64() if addr, ok := blockMap[currentBlockNumber]; ok { @@ -430,7 +429,7 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* receipt.GasUsed = result.UsedGas // 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.TxContext.Origin, tx.Nonce()) } @@ -441,7 +440,7 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) if balanceFee != nil && result.Failed() { - state.PayFeeWithTRC21TxFail(statedb, msg.From(), *to) + state.PayFeeWithTRC21TxFail(statedb, msg.From, *to) } return receipt, result.UsedGas, err, balanceFee != nil } @@ -466,7 +465,6 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* blockContext := NewEVMBlockContext(header, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, XDCxState, config, cfg) coinbaseOwner := getCoinbaseOwner(bc, statedb, header, author) - // return applyTransaction(config, tokensFee, gp, statedb, coinbaseOwner, header.Number, header.BaseFee, header.Hash(), tx, usedGas, vmenv) return applyTransaction(config, tokensFee, gp, statedb, coinbaseOwner, header.Number, header.BaseFee, header.Hash(), tx, usedGas, vmenv) } diff --git a/core/state_transition.go b/core/state_transition.go index 6d9aa2b75f56..9c8008acc8e3 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -24,64 +24,10 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/vm" - "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/params" "github.com/holiman/uint256" ) -var emptyCodeHash = crypto.Keccak256Hash(nil) - -/* -The State Transitioning Model - -A state transition is a change made when a transaction is applied to the current world state -The state transitioning model does all all the necessary work to work out a valid new state root. - -1) Nonce handling -2) Pre pay gas -3) Create a new state object if the recipient is \0*32 -4) Value transfer -== If contract creation == - - 4a) Attempt to run transaction data - 4b) If valid, use result as code for the new state object - -== end == -5) Run Script section -6) Derive new state root -*/ -type StateTransition struct { - gp *GasPool - msg Message - gas uint64 - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int - initialGas uint64 - value *big.Int - data []byte - state vm.StateDB - evm *vm.EVM -} - -// Message represents a message sent to a contract. -type Message interface { - From() common.Address - To() *common.Address - - GasPrice() *big.Int - GasFeeCap() *big.Int - GasTipCap() *big.Int - Gas() uint64 - Value() *big.Int - - Nonce() uint64 - IsFake() bool - Data() []byte - BalanceTokenFee() *big.Int - AccessList() types.AccessList -} - // ExecutionResult includes all output after executing given evm // message no matter the execution itself is successful or not. type ExecutionResult struct { @@ -166,19 +112,64 @@ func toWordSize(size uint64) uint64 { return (size + 31) / 32 } -// NewStateTransition initialises and returns a new state transition object. -func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition { - return &StateTransition{ - gp: gp, - evm: evm, - msg: msg, - gasPrice: msg.GasPrice(), - gasFeeCap: msg.GasFeeCap(), - gasTipCap: msg.GasTipCap(), - value: msg.Value(), - data: msg.Data(), - state: evm.StateDB, +// A Message contains the data derived from a single transaction that is relevant to state +// processing. +type Message struct { + To *common.Address + From common.Address + Nonce uint64 + Value *big.Int + GasLimit uint64 + GasPrice *big.Int + GasFeeCap *big.Int + GasTipCap *big.Int + BalanceTokenFee *big.Int + Data []byte + AccessList types.AccessList + + // When SkipAccountCheckss is true, the message nonce is not checked against the + // account nonce in state. It also disables checking that the sender is an EOA. + // This field will be set to true for operations like RPC eth_call. + SkipAccountChecks bool +} + +// TransactionToMessage converts a transaction into a Message. +func TransactionToMessage(tx *types.Transaction, s types.Signer, balanceFee, blockNumber, baseFee *big.Int) (*Message, error) { + msg := &Message{ + Nonce: tx.Nonce(), + GasLimit: tx.Gas(), + GasPrice: new(big.Int).Set(tx.GasPrice()), + GasFeeCap: new(big.Int).Set(tx.GasFeeCap()), + GasTipCap: new(big.Int).Set(tx.GasTipCap()), + To: tx.To(), + Value: tx.Value(), + Data: tx.Data(), + AccessList: tx.AccessList(), + SkipAccountChecks: false, + BalanceTokenFee: balanceFee, + } + + if balanceFee != nil { + if blockNumber != nil { + if blockNumber.Cmp(common.BlockNumberGas50x) >= 0 { + msg.GasPrice = new(big.Int).Set(common.GasPrice50x) + } else if blockNumber.Cmp(common.TIPTRC21Fee) > 0 { + msg.GasPrice = new(big.Int).Set(common.TRC21GasPrice) + } else { + msg.GasPrice = new(big.Int).Set(common.TRC21GasPriceBefore) + } + } + } else if baseFee != nil { + // If baseFee provided, set gasPrice to effectiveGasPrice. + msg.GasPrice = msg.GasPrice.Add(msg.GasTipCap, baseFee) + if msg.GasPrice.Cmp(msg.GasFeeCap) > 0 { + msg.GasPrice = msg.GasFeeCap + } } + + var err error + msg.From, err = types.Sender(s, tx) + return msg, err } // ApplyMessage computes the new state by applying the given message @@ -188,63 +179,97 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition // the gas used (which includes gas refunds) and an error if it failed. An error always // indicates a core error meaning that the message would always fail for that particular // state and would never be accepted within a block. -func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool, owner common.Address) (*ExecutionResult, error) { +func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool, owner common.Address) (*ExecutionResult, error) { return NewStateTransition(evm, msg, gp).TransitionDb(owner) } -func (st *StateTransition) from() vm.AccountRef { - f := st.msg.From() - if !st.state.Exist(f) { - st.state.CreateAccount(f) +// StateTransition represents a state transition. +// +// == The State Transitioning Model +// +// A state transition is a change made when a transaction is applied to the current world +// state. The state transitioning model does all the necessary work to work out a valid new +// state root. +// +// 1. Nonce handling +// 2. Pre pay gas +// 3. Create a new state object if the recipient is nil +// 4. Value transfer +// +// == If contract creation == +// +// 4a. Attempt to run transaction data +// 4b. If valid, use result as code for the new state object +// +// == end == +// +// 5. Run Script section +// 6. Derive new state root +type StateTransition struct { + gp *GasPool + msg *Message + gasRemaining uint64 + initialGas uint64 + state vm.StateDB + evm *vm.EVM +} + +// NewStateTransition initialises and returns a new state transition object. +func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition { + return &StateTransition{ + gp: gp, + evm: evm, + msg: msg, + state: evm.StateDB, } - return vm.AccountRef(f) } -func (st *StateTransition) balanceTokenFee() *big.Int { - return st.msg.BalanceTokenFee() +func (st *StateTransition) from() common.Address { + f := st.msg.From + if !st.state.Exist(f) { + st.state.CreateAccount(f) + } + return f } -func (st *StateTransition) to() vm.AccountRef { +func (st *StateTransition) to() common.Address { if st.msg == nil { - return vm.AccountRef{} + return common.Address{} } - to := st.msg.To() + to := st.msg.To if to == nil { - return vm.AccountRef{} // contract creation + return common.Address{} // contract creation } - - reference := vm.AccountRef(*to) if !st.state.Exist(*to) { st.state.CreateAccount(*to) } - return reference + return *to } func (st *StateTransition) buyGas() error { - mgval := new(big.Int).SetUint64(st.msg.Gas()) - mgval = mgval.Mul(mgval, st.gasPrice) - balanceTokenFee := st.balanceTokenFee() - if balanceTokenFee == nil { + mgval := new(big.Int).SetUint64(st.msg.GasLimit) + mgval = mgval.Mul(mgval, st.msg.GasPrice) + if st.msg.BalanceTokenFee == nil { balanceCheck := mgval - if st.gasFeeCap != nil { - balanceCheck = new(big.Int).SetUint64(st.msg.Gas()) - balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap) - balanceCheck.Add(balanceCheck, st.value) + if st.msg.GasFeeCap != nil { + balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit) + balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) + balanceCheck.Add(balanceCheck, st.msg.Value) } - if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 { - return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want) + if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { + return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) } - } else if balanceTokenFee.Cmp(mgval) < 0 { + } else if st.msg.BalanceTokenFee.Cmp(mgval) < 0 { return ErrInsufficientFunds } - if err := st.gp.SubGas(st.msg.Gas()); err != nil { + if err := st.gp.SubGas(st.msg.GasLimit); err != nil { return err } - st.gas += st.msg.Gas() + st.gasRemaining += st.msg.GasLimit - st.initialGas = st.msg.Gas() - if balanceTokenFee == nil { - st.state.SubBalance(st.msg.From(), mgval) + st.initialGas = st.msg.GasLimit + if st.msg.BalanceTokenFee == nil { + st.state.SubBalance(st.msg.From, mgval) } return nil } @@ -252,48 +277,48 @@ func (st *StateTransition) buyGas() error { func (st *StateTransition) preCheck() error { // Only check transactions that are not fake msg := st.msg - if !msg.IsFake() { + if !msg.SkipAccountChecks { // Make sure this transaction's nonce is correct. - stNonce := st.state.GetNonce(msg.From()) - if msgNonce := msg.Nonce(); stNonce < msgNonce { + stNonce := st.state.GetNonce(msg.From) + if msgNonce := msg.Nonce; stNonce < msgNonce { return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, - msg.From().Hex(), msgNonce, stNonce) + msg.From.Hex(), msgNonce, stNonce) } else if stNonce > msgNonce { return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, - msg.From().Hex(), msgNonce, stNonce) + msg.From.Hex(), msgNonce, stNonce) } else if stNonce+1 < stNonce { return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax, - msg.From().Hex(), stNonce) + msg.From.Hex(), stNonce) } // Make sure the sender is an EOA - if codeHash := st.state.GetCodeHash(msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) { + if codeHash := st.state.GetCodeHash(msg.From); codeHash != types.EmptyCodeHash && codeHash != (common.Hash{}) { return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, - msg.From().Hex(), codeHash) + msg.From.Hex(), codeHash) } } // Make sure that transaction gasFeeCap is greater than the baseFee (post london) if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) { // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) - skipCheck := st.evm.Config.NoBaseFee && st.gasFeeCap.BitLen() == 0 && st.gasTipCap.BitLen() == 0 + skipCheck := st.evm.Config.NoBaseFee && msg.GasFeeCap.BitLen() == 0 && msg.GasTipCap.BitLen() == 0 if !skipCheck { - if l := st.gasFeeCap.BitLen(); l > 256 { + if l := msg.GasFeeCap.BitLen(); l > 256 { return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, - msg.From().Hex(), l) + msg.From.Hex(), l) } - if l := st.gasTipCap.BitLen(); l > 256 { + if l := msg.GasTipCap.BitLen(); l > 256 { return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, - msg.From().Hex(), l) + msg.From.Hex(), l) } - if st.gasFeeCap.Cmp(st.gasTipCap) < 0 { + if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, - msg.From().Hex(), st.gasTipCap, st.gasFeeCap) + msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap) } // This will panic if baseFee is nil, but basefee presence is verified // as part of header validation. - if !types.IsSpecialTx(msg.To()) && st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + if !types.IsSpecialTx(msg.To) && msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, - msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee) + msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) } } } @@ -332,44 +357,44 @@ func (st *StateTransition) TransitionDb(owner common.Address) (*ExecutionResult, if tracer := st.evm.Config.Tracer; tracer != nil { st.evm.Config.Tracer.CaptureTxStart(st.initialGas) defer func() { - st.evm.Config.Tracer.CaptureTxEnd(st.gas) + st.evm.Config.Tracer.CaptureTxEnd(st.gasRemaining) }() } var ( msg = st.msg - sender = st.from() // err checked in preCheck + sender = vm.AccountRef(st.from()) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber) - contractCreation = msg.To() == nil + contractCreation = msg.To == nil ) // Check clauses 4-5, subtract intrinsic gas if everything is correct - gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, rules.IsHomestead, rules.IsEIP1559) + gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsEIP1559) if err != nil { return nil, err } - if st.gas < gas { - return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas) + if st.gasRemaining < gas { + return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas) } - st.gas -= gas + st.gasRemaining -= gas // Check whether the init code size has been exceeded. - if rules.IsEIP1559 && contractCreation && len(st.data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(st.data), params.MaxInitCodeSize) + if rules.IsEIP1559 && contractCreation && len(msg.Data) > params.MaxInitCodeSize { + return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) } // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) // - reset transient storage(eip 1153) - st.state.Prepare(rules, msg.From(), st.evm.Context.Coinbase, msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) + st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) // Check clause 6 - value, overflow := uint256.FromBig(msg.Value()) + value, overflow := uint256.FromBig(msg.Value) if overflow { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) + return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) } - if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From(), value.ToBig()) { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) + if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From, value.ToBig()) { + return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) } var ( @@ -377,11 +402,11 @@ func (st *StateTransition) TransitionDb(owner common.Address) (*ExecutionResult, vmerr error // vm errors do not effect consensus and are therefore not assigned to err ) if contractCreation { - ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value) + ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, msg.Value) } else { // Increment the nonce for the next transaction st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1) - ret, st.gas, vmerr = st.evm.Call(sender, st.to().Address(), st.data, st.gas, st.value) + ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value) } if !rules.IsEIP1559 { // Before EIP-3529: refunds were capped to gasUsed / 2 @@ -393,14 +418,14 @@ func (st *StateTransition) TransitionDb(owner common.Address) (*ExecutionResult, if st.evm.Context.BlockNumber.Cmp(common.TIPTRC21Fee) > 0 { if (owner != common.Address{}) { - st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)) + st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), msg.GasPrice)) } } else { - effectiveTip := st.gasPrice + effectiveTip := msg.GasPrice if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) { - effectiveTip = new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee) - if effectiveTip.Cmp(st.gasTipCap) > 0 { - effectiveTip = st.gasTipCap + effectiveTip = new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee) + if effectiveTip.Cmp(msg.GasTipCap) > 0 { + effectiveTip = msg.GasTipCap } } st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) @@ -419,21 +444,19 @@ func (st *StateTransition) refundGas(refundQuotient uint64) { if refund > st.state.GetRefund() { refund = st.state.GetRefund() } - st.gas += refund + st.gasRemaining += refund - balanceTokenFee := st.balanceTokenFee() - if balanceTokenFee == nil { - from := st.from() + if st.msg.BalanceTokenFee == nil { // Return ETH for remaining gas, exchanged at the original rate. - remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) - st.state.AddBalance(from.Address(), remaining) + remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice) + st.state.AddBalance(st.from(), remaining) } // Also return remaining gas to the block gas counter so it is // available for the next transaction. - st.gp.AddGas(st.gas) + st.gp.AddGas(st.gasRemaining) } // gasUsed returns the amount of gas used up by the state transition. func (st *StateTransition) gasUsed() uint64 { - return st.initialGas - st.gas + return st.initialGas - st.gasRemaining } diff --git a/core/token_validator.go b/core/token_validator.go index 86d2b9ddc568..21045a19211f 100644 --- a/core/token_validator.go +++ b/core/token_validator.go @@ -27,7 +27,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract" "github.com/XinFinOrg/XDPoSChain/core/state" - "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/log" ) @@ -38,24 +37,6 @@ const ( getDecimalFunction = "decimals" ) -// callMsg implements core.Message to allow passing it as a transaction simulator. -type callMsg struct { - ethereum.CallMsg -} - -func (m callMsg) From() common.Address { return m.CallMsg.From } -func (m callMsg) Nonce() uint64 { return 0 } -func (m callMsg) IsFake() bool { return true } -func (m callMsg) To() *common.Address { return m.CallMsg.To } -func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } -func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap } -func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap } -func (m callMsg) Gas() uint64 { return m.CallMsg.Gas } -func (m callMsg) Value() *big.Int { return m.CallMsg.Value } -func (m callMsg) Data() []byte { return m.CallMsg.Data } -func (m callMsg) BalanceTokenFee() *big.Int { return m.CallMsg.BalanceTokenFee } -func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList } - type SimulatedBackend interface { CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext, statedb *state.StateDB) ([]byte, error) } @@ -102,18 +83,31 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext, if call.Value == nil { call.Value = new(big.Int) } + // Execute the call. - msg := callMsg{call} + msg := &Message{ + From: call.From, + To: call.To, + Value: call.Value, + GasLimit: call.Gas, + GasPrice: call.GasPrice, + GasFeeCap: call.GasFeeCap, + GasTipCap: call.GasTipCap, + Data: call.Data, + AccessList: call.AccessList, + SkipAccountChecks: true, + } feeCapacity := state.GetTRC21FeeCapacityFromState(statedb) - if msg.To() != nil { - if value, ok := feeCapacity[*msg.To()]; ok { - msg.CallMsg.BalanceTokenFee = value + if msg.To != nil { + if value, ok := feeCapacity[*msg.To]; ok { + msg.BalanceTokenFee = value } } - txContext := NewEVMTxContext(msg) - evmContext := NewEVMBlockContext(chain.CurrentHeader(), chain, nil) + // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. + txContext := NewEVMTxContext(msg) + evmContext := NewEVMBlockContext(chain.CurrentHeader(), chain, nil) vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, chain.Config(), vm.Config{}) gaspool := new(GasPool).AddGas(1000000) owner := common.Address{} diff --git a/core/types/transaction.go b/core/types/transaction.go index 0a6daf07fab3..25e5edaef96e 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -424,45 +424,6 @@ func (tx *Transaction) EffectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.In return tx.inner.effectiveGasPrice(dst, baseFee) } -// AsMessage returns the transaction as a core.Message. -func (tx *Transaction) AsMessage(s Signer, balanceFee, blockNumber, baseFee *big.Int) (Message, error) { - msg := Message{ - nonce: tx.Nonce(), - gasLimit: tx.Gas(), - gasPrice: new(big.Int).Set(tx.GasPrice()), - gasFeeCap: new(big.Int).Set(tx.GasFeeCap()), - gasTipCap: new(big.Int).Set(tx.GasTipCap()), - to: tx.To(), - amount: tx.Value(), - data: tx.Data(), - accessList: tx.AccessList(), - isFake: false, - balanceTokenFee: balanceFee, - } - - if balanceFee != nil { - if blockNumber != nil { - if blockNumber.Cmp(common.BlockNumberGas50x) >= 0 { - msg.gasPrice = common.GasPrice50x - } else if blockNumber.Cmp(common.TIPTRC21Fee) > 0 { - msg.gasPrice = common.TRC21GasPrice - } else { - msg.gasPrice = common.TRC21GasPriceBefore - } - } - } else if baseFee != nil { - // If baseFee provided, set gasPrice to effectiveGasPrice. - msg.gasPrice = msg.gasPrice.Add(msg.gasTipCap, baseFee) - if msg.gasPrice.Cmp(msg.gasFeeCap) > 0 { - msg.gasPrice.Set(msg.gasFeeCap) - } - } - - var err error - msg.from, err = Sender(s, tx) - return msg, err -} - // WithSignature returns a new transaction with the given signature. // This signature needs to be in the [R || S || V] format where V is 0 or 1. func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) { @@ -818,68 +779,6 @@ func (t *TransactionsByPriceAndNonce) Pop() { heap.Pop(&t.heads) } -// Message is a fully derived transaction and implements core.Message -// -// NOTE: In a future PR this will be removed. -type Message struct { - to *common.Address - from common.Address - nonce uint64 - amount *big.Int - gasLimit uint64 - gasPrice *big.Int - gasFeeCap *big.Int - gasTipCap *big.Int - data []byte - accessList AccessList - isFake bool - balanceTokenFee *big.Int -} - -func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, isFake bool, balanceTokenFee *big.Int, number *big.Int) Message { - if balanceTokenFee != nil { - gasPrice = common.GetGasPrice(number) - } - return Message{ - from: from, - to: to, - nonce: nonce, - amount: amount, - gasLimit: gasLimit, - gasPrice: gasPrice, - gasFeeCap: gasFeeCap, - gasTipCap: gasTipCap, - data: data, - accessList: accessList, - isFake: isFake, - balanceTokenFee: balanceTokenFee, - } -} - -func (m Message) From() common.Address { return m.from } -func (m Message) BalanceTokenFee() *big.Int { return m.balanceTokenFee } -func (m Message) To() *common.Address { return m.to } -func (m Message) GasPrice() *big.Int { return m.gasPrice } -func (m Message) GasFeeCap() *big.Int { return m.gasFeeCap } -func (m Message) GasTipCap() *big.Int { return m.gasTipCap } -func (m Message) Value() *big.Int { return m.amount } -func (m Message) Gas() uint64 { return m.gasLimit } -func (m Message) Nonce() uint64 { return m.nonce } -func (m Message) Data() []byte { return m.data } -func (m Message) IsFake() bool { return m.isFake } -func (m Message) AccessList() AccessList { return m.accessList } - -func (m *Message) SetNonce(nonce uint64) { m.nonce = nonce } - -func (m *Message) SetBalanceTokenFeeForCall() { - m.balanceTokenFee = new(big.Int).SetUint64(m.gasLimit) - m.balanceTokenFee.Mul(m.balanceTokenFee, m.gasPrice) -} - -func (m *Message) SetBalanceTokenFee(balanceTokenFee *big.Int) { - m.balanceTokenFee = balanceTokenFee -} - // copyAddressPtr copies an address. func copyAddressPtr(a *common.Address) *common.Address { if a == nil { diff --git a/eth/api_backend.go b/eth/api_backend.go index 999dcbfe355b..d0dafc9ac0ba 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -257,12 +257,12 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return b.eth.blockchain.GetTdByHash(hash) } -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { vmError := func() error { return nil } if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() } - state.SetBalance(msg.From(), math.MaxBig256) + state.SetBalance(msg.From, math.MaxBig256) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) return vm.NewEVM(context, txContext, state, XDCxState, b.eth.chainConfig, *vmConfig), vmError, nil @@ -418,7 +418,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re return b.eth.StateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) } -func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/eth/state_accessor.go b/eth/state_accessor.go index a5fe1872f8a6..a90a570dd304 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -190,7 +190,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe } // stateAtTransaction returns the execution environment of a certain transaction. -func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") @@ -220,7 +220,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, } } // Assemble the transaction call message and return if the requested offset - msg, _ := tx.AsMessage(signer, balance, block.Number(), block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee()) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) if idx == txIndex { diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 72f82cd840e4..6a1fedaccfd9 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -88,7 +88,7 @@ type Backend interface { Engine() consensus.Engine ChainDb() ethdb.Database StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) - StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) + StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) } // API is the collection of tracing APIs exposed over the private debugging endpoint. @@ -295,7 +295,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed } } header := task.block.Header() - msg, _ := tx.AsMessage(signer, balance, header.Number, header.BaseFee) + msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee) txctx := &Context{ BlockHash: task.block.Hash(), BlockNumber: task.block.Number(), @@ -541,13 +541,13 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config } } var ( - msg, _ = tx.AsMessage(signer, balance, block.Number(), block.BaseFee()) + msg, _ = core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee()) txContext = core.NewEVMTxContext(msg) vmenv = vm.NewEVM(vmctx, txContext, statedb, nil, chainConfig, vm.Config{}) ) statedb.SetTxContext(tx.Hash(), i) owner := common.Address{} - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), owner); err != nil { log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) // We intentionally don't return the error here: if we do, then the RPC server will not // return the roots. Most likely, the caller already knows that a certain transaction fails to @@ -619,7 +619,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac } } // Generate the next state snapshot fast without tracing - msg, _ := tx.AsMessage(signer, balance, block.Number(), block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee()) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -670,7 +670,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat } } header := block.Header() - msg, _ := txs[task.index].AsMessage(signer, balance, header.Number, header.BaseFee) + msg, _ := core.TransactionToMessage(txs[task.index], signer, balance, header.Number, header.BaseFee) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -713,11 +713,11 @@ txloop: } // Generate the next state snapshot fast without tracing header := block.Header() - msg, _ := tx.AsMessage(signer, balance, header.Number, header.BaseFee) + msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, nil, api.backend.ChainConfig(), vm.Config{}) owner := common.Address{} - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil { + if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), owner); err != nil { failed = err break txloop } @@ -837,7 +837,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { var ( tracer Tracer err error @@ -876,7 +876,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex // Call SetTxContext to clear out the statedb access list statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - if _, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), common.Address{}); err != nil { + if _, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit), common.Address{}); err != nil { return nil, fmt.Errorf("tracing failed: %w", err) } return tracer.GetResult() diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 71820085531a..44bc9f70d3ec 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -160,7 +160,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex return statedb, release, nil } -func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { +func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { return nil, vm.BlockContext{}, nil, nil, errBlockNotFound @@ -175,7 +175,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block // Recompute transactions up to the target index. signer := types.MakeSigner(b.chainConfig, block.Number()) for idx, tx := range block.Transactions() { - msg, _ := tx.AsMessage(signer, nil, block.Number(), block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, nil, block.Number(), block.BaseFee()) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), b.chain, nil) if idx == txIndex { diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index aebbb4acb37f..7bdd377965a8 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -145,7 +145,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, nil, nil) + msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -219,7 +219,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { b.Fatalf("failed to parse testcase input: %v", err) } signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) - msg, err := tx.AsMessage(signer, nil, nil, nil) + msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -313,7 +313,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, nil, nil) + msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -389,7 +389,7 @@ func testContractTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, nil, nil) + msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index d7bebb6dea9b..184cfb2dde8f 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -109,7 +109,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string } evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, context.BlockNumber, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee) if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 9047cda0d5ae..26346a999a89 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -115,7 +115,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, context.BlockNumber, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index c6f6feb143e3..274711c69186 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -88,7 +88,7 @@ func BenchmarkTransactionTrace(b *testing.B) { //EnableReturnData: false, }) evm := vm.NewEVM(context, txContext, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer}) - msg, err := tx.AsMessage(signer, nil, nil, nil) + msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 242f7f024d9d..feefdc0a3305 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1127,7 +1127,8 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash if err != nil { return nil, err } - msg.SetBalanceTokenFeeForCall() + msg.BalanceTokenFee = new(big.Int).SetUint64(msg.GasLimit) + msg.BalanceTokenFee.Mul(msg.BalanceTokenFee, msg.GasPrice) // Get a new instance of the EVM. evm, vmError, err := b.GetEVM(ctx, msg, statedb, XDCxState, header, &vm.Config{NoBaseFee: true}) @@ -1154,7 +1155,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) } if err != nil { - return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) + return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.GasLimit) } return result, err } @@ -1776,7 +1777,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH if value, ok := feeCapacity[to]; ok { balanceTokenFee = value } - msg.SetBalanceTokenFee(balanceTokenFee) + msg.BalanceTokenFee = balanceTokenFee // Apply the transaction with the access list tracer tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles) @@ -1786,7 +1787,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH return nil, 0, nil, err } // TODO: determine the value of owner - res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner) + res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), owner) if err != nil { return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err) } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index c463368c13f8..f3ed5ae65c75 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -73,7 +73,7 @@ type Backend interface { PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, blockHash common.Hash) *big.Int - GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) + GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 627f57b68716..c74d617080ce 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -27,6 +27,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/hexutil" + "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/rpc" @@ -228,10 +229,10 @@ type AccountBackend interface { // ToMessage converts the transaction arguments to the Message type used by the // core evm. This method is used in calls and traces that do not require a real // live transaction. -func (args *TransactionArgs) ToMessage(b AccountBackend, number *big.Int, globalGasCap uint64, baseFee *big.Int) (types.Message, error) { +func (args *TransactionArgs) ToMessage(b AccountBackend, number *big.Int, globalGasCap uint64, baseFee *big.Int) (*core.Message, error) { // Reject invalid combinations of pre- and post-1559 fee styles if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { - return types.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } // Set sender address or use zero address if none specified. @@ -308,7 +309,19 @@ func (args *TransactionArgs) ToMessage(b AccountBackend, number *big.Int, global accessList = *args.AccessList } - msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true, nil, number) + msg := &core.Message{ + From: addr, + To: args.To, + Nonce: 0, + Value: value, + GasLimit: gas, + GasPrice: gasPrice, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: data, + AccessList: accessList, + SkipAccountChecks: true, + } return msg, nil } diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index e34d3a293416..15ac410d1a4d 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -349,7 +349,7 @@ func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *backendMock) GetEVM(context.Context, core.Message, *state.StateDB, *tradingstate.TradingStateDB, *types.Header, *vm.Config) (*vm.EVM, func() error, error) { +func (b *backendMock) GetEVM(context.Context, *core.Message, *state.StateDB, *tradingstate.TradingStateDB, *types.Header, *vm.Config) (*vm.EVM, func() error, error) { return nil, nil, nil } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 7c7b2501d790..c409df0ab954 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -214,7 +214,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis { } } -func (tx *stTransaction) toMessage(ps stPostState, number *big.Int, baseFee *big.Int) (core.Message, error) { +func (tx *stTransaction) toMessage(ps stPostState, number *big.Int, baseFee *big.Int) (*core.Message, error) { // Derive sender from private key if present. var from common.Address if len(tx.PrivateKey) > 0 { @@ -284,7 +284,19 @@ func (tx *stTransaction) toMessage(ps stPostState, number *big.Int, baseFee *big return nil, errors.New("no gas price provided") } - msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, false, nil, number) + msg := &core.Message{ + From: from, + To: to, + Nonce: tx.Nonce, + Value: value, + GasLimit: gasLimit, + GasPrice: tx.GasPrice, + GasFeeCap: tx.MaxFeePerGas, + GasTipCap: tx.MaxPriorityFeePerGas, + Data: data, + AccessList: accessList, + SkipAccountChecks: false, + } return msg, nil }