diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 16d9b2ce364e..3e0bbc50a6ab 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -462,7 +462,18 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.Cal 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 { @@ -470,14 +481,14 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.Cal } } - txContext := core.NewEVMTxContext(msg) - evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil) // 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) vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, b.config, vm.Config{NoBaseFee: true}) gaspool := new(core.GasPool).AddGas(math.MaxUint64) owner := common.Address{} - return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner) + return core.ApplyMessage(vmenv, msg, gaspool, owner) } // SendTransaction updates the pending block to include the given transaction. @@ -604,24 +615,6 @@ func (b *SimulatedBackend) GetBlockChain() *core.BlockChain { return b.blockchain } -// callMsg implements core.Message to allow passing it as a transaction simulator. -type callMsg struct { - XDPoSChain.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 9847a8d790b1..3367e821e4aa 100644 --- a/core/evm.go +++ b/core/evm.go @@ -59,10 +59,10 @@ func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, auth } // 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_processor.go b/core/state_processor.go index 2f7980db6326..d002f662cc42 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -247,7 +247,7 @@ func applyTransaction(config *params.ChainConfig, tokensFee map[common.Address]* } } // 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 } @@ -430,7 +430,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()) } diff --git a/core/state_transition.go b/core/state_transition.go index 4c9ee3fca09d..374321120b70 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -26,68 +26,14 @@ import ( cmath "github.com/XinFinOrg/XDPoSChain/common/math" "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) - var ( errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas") ) -/* -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 { @@ -172,19 +118,47 @@ 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 + 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, 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, + } + // If baseFee provided, set gasPrice to effectiveGasPrice. + if baseFee != nil { + msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), 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 @@ -194,12 +168,53 @@ 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) } +// 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, + } +} + func (st *StateTransition) from() vm.AccountRef { - f := st.msg.From() + f := st.msg.From if !st.state.Exist(f) { st.state.CreateAccount(f) } @@ -214,7 +229,7 @@ func (st *StateTransition) to() vm.AccountRef { if st.msg == nil { return vm.AccountRef{} } - to := st.msg.To() + to := st.msg.To if to == nil { return vm.AccountRef{} // contract creation } @@ -227,30 +242,30 @@ func (st *StateTransition) to() vm.AccountRef { } func (st *StateTransition) buyGas() error { - mgval := new(big.Int).SetUint64(st.msg.Gas()) - mgval = mgval.Mul(mgval, st.gasPrice) + mgval := new(big.Int).SetUint64(st.msg.GasLimit) + mgval = mgval.Mul(mgval, st.msg.GasPrice) balanceTokenFee := st.balanceTokenFee() if 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 { 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() + st.initialGas = st.msg.GasLimit if balanceTokenFee == nil { - st.state.SubBalance(st.msg.From(), mgval) + st.state.SubBalance(st.msg.From, mgval) } return nil } @@ -258,46 +273,47 @@ 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{}) { + codeHash := st.state.GetCodeHash(msg.From) + if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash { 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) - if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 { - if l := st.gasFeeCap.BitLen(); l > 256 { + if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 { + 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 (msg.To() == nil || *msg.To() != common.RandomizeSMCBinary) && st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + if (msg.To == nil || *msg.To != common.RandomizeSMCBinary) && 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(), st.msg.GasFeeCap, st.evm.Context.BaseFee) } } } @@ -339,36 +355,36 @@ func (st *StateTransition) TransitionDb(owner common.Address) (*ExecutionResult, rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber) homestead = rules.IsHomestead eip3529 = rules.IsEIP1559 - 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, homestead, rules.IsEIP1559) + gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, homestead, 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(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) + st.state.Prepare(rules, msg.From, 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(), msg.Value()) { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) + if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From, msg.Value) { + return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) } var ( @@ -376,11 +392,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, st.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().Address(), msg.Data, st.gasRemaining, st.msg.Value) } if !eip3529 { // Before EIP-3529: refunds were capped to gasUsed / 2 @@ -392,12 +408,12 @@ 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()), st.msg.GasPrice)) } } else { - effectiveTip := st.gasPrice + effectiveTip := st.msg.GasPrice if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) { - effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) + effectiveTip = cmath.BigMin(msg.GasFeeCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) } st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) } @@ -415,21 +431,21 @@ 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() // Return ETH for remaining gas, exchanged at the original rate. - remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) + remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice) st.state.AddBalance(from.Address(), 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/types/transaction.go b/core/types/transaction.go index f0afdca06092..ac466ddc4668 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -807,59 +807,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) diff --git a/eth/api_backend.go b/eth/api_backend.go index 183a0f1f4485..2f5e1ada0308 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -248,12 +248,12 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int { return b.eth.blockchain.GetTdByHash(blockHash) } -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 diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 18c0fc010945..a87c2ea03d4e 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -242,7 +242,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl } } header := task.block.Header() - msg, _ := tx.AsMessage(signer, balance, header.Number, header.BaseFee) + msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee) txctx := &tracers.Context{ BlockHash: task.block.Hash(), TxIndex: i, @@ -520,7 +520,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, } // 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) txContext := core.NewEVMTxContext(msg) statedb.SetTxContext(tx.Hash(), i) diff --git a/eth/tracers/testing/calltrace_test.go b/eth/tracers/testing/calltrace_test.go index 102e6f7416cc..5001a6b0ade0 100644 --- a/eth/tracers/testing/calltrace_test.go +++ b/eth/tracers/testing/calltrace_test.go @@ -115,7 +115,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{Debug: true, 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) } @@ -201,7 +201,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) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index af01acda6741..42c10bebb9f9 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -153,7 +153,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{Debug: true, 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) } @@ -239,7 +239,7 @@ func TestPrestateTracerCreate2(t *testing.T) { } evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, 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) } @@ -336,7 +336,7 @@ func BenchmarkTransactionTrace(b *testing.B) { //EnableReturnData: false, }) evm := vm.NewEVM(context, txContext, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Debug: true, 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/backend.go b/internal/ethapi/backend.go index b9be939a6a42..91de54a3fb78 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -72,7 +72,7 @@ type Backend interface { PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetTd(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 2202fe580e78..71017c50fc5c 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -26,6 +26,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/common/math" + "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/rpc" @@ -223,10 +224,10 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ // 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 Backend, number *big.Int, globalGasCap uint64, baseFee *big.Int) (types.Message, error) { +func (args *TransactionArgs) ToMessage(b Backend, 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. @@ -300,7 +301,18 @@ func (args *TransactionArgs) ToMessage(b Backend, number *big.Int, globalGasCap 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, + Value: value, + GasLimit: gas, + GasPrice: gasPrice, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: data, + AccessList: accessList, + SkipAccountChecks: true, + } return msg, nil } diff --git a/les/api_backend.go b/les/api_backend.go index fe8371c5a25d..17d62adaabbe 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -184,7 +184,7 @@ func (b *LesApiBackend) GetTd(blockHash common.Hash) *big.Int { return b.eth.blockchain.GetTdByHash(blockHash) } -func (b *LesApiBackend) 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 *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = new(vm.Config) } diff --git a/les/odr_test.go b/les/odr_test.go index 706853d504b2..bebd422b20c1 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -109,10 +109,6 @@ func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainCon // //func TestOdrContractCallLes2(t *testing.T) { testOdr(t, 2, 2, odrContractCall) } -type callmsg struct { - types.Message -} - func (callmsg) CheckNonce() bool { return false } func odrContractCall(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { @@ -133,8 +129,18 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai if value, ok := feeCapacity[testContractAddr]; ok { balanceTokenFee = value } - msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} - + msg := &core.Message{ + From: from.Address(), + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 100000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + // msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} + } context := core.NewEVMBlockContext(header, bc, nil) txContext := core.NewEVMTxContext(msg) vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{NoBaseFee: true}) @@ -154,7 +160,18 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai if value, ok := feeCapacity[testContractAddr]; ok { balanceTokenFee = value } - msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} + // msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} + msg := &core.Message{ + From: testBankAddress, + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 1000000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + } context := core.NewEVMBlockContext(header, lc, nil) txContext := core.NewEVMTxContext(msg) vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{NoBaseFee: true}) diff --git a/light/odr_test.go b/light/odr_test.go index 79d3241c2048..588731caddad 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -148,10 +148,6 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc func TestOdrContractCallLes1(t *testing.T) { testChainOdr(t, 1, odrContractCall) } -type callmsg struct { - types.Message -} - func (callmsg) CheckNonce() bool { return false } func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc *LightChain, bhash common.Hash) ([]byte, error) { @@ -185,7 +181,18 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain if value, ok := feeCapacity[testContractAddr]; ok { balanceTokenFee = value } - msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} + // msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true, balanceTokenFee, header.Number)} + msg := &core.Message{ + From: testBankAddress, + To: &testContractAddr, + Value: new(big.Int), + GasLimit: 1000000, + GasPrice: big.NewInt(params.InitialBaseFee), + GasFeeCap: big.NewInt(params.InitialBaseFee), + GasTipCap: new(big.Int), + Data: data, + SkipAccountChecks: true, + } txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(header, chain, nil) vmenv := vm.NewEVM(context, txContext, st, nil, config, vm.Config{NoBaseFee: true}) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index e95e45155589..1791ce506ae5 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 { @@ -282,7 +282,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 := 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: gasPrice, + GasFeeCap: tx.MaxFeePerGas, + GasTipCap: tx.MaxPriorityFeePerGas, + Data: data, + AccessList: accessList, + } return msg, nil }