mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
skip EoA check in validation mode
This commit is contained in:
parent
5db01067d3
commit
4c325ba5b3
6 changed files with 77 additions and 35 deletions
|
|
@ -142,27 +142,30 @@ type Message struct {
|
||||||
BlobGasFeeCap *big.Int
|
BlobGasFeeCap *big.Int
|
||||||
BlobHashes []common.Hash
|
BlobHashes []common.Hash
|
||||||
|
|
||||||
// When SkipAccountChecks is true, the message nonce is not checked against the
|
// When SkipNonceChecks is true, the message nonce is not checked against the
|
||||||
// account nonce in state. It also disables checking that the sender is an EOA.
|
// account nonce in state.
|
||||||
// This field will be set to true for operations like RPC eth_call.
|
// This field will be set to true for operations like RPC eth_call.
|
||||||
SkipAccountChecks bool
|
SkipNonceChecks bool
|
||||||
|
// When SkipFromEoACheck is true, the message sender is not checked to be an EOA.
|
||||||
|
SkipFromEoACheck bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionToMessage converts a transaction into a Message.
|
// TransactionToMessage converts a transaction into a Message.
|
||||||
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
|
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
|
||||||
msg := &Message{
|
msg := &Message{
|
||||||
Nonce: tx.Nonce(),
|
Nonce: tx.Nonce(),
|
||||||
GasLimit: tx.Gas(),
|
GasLimit: tx.Gas(),
|
||||||
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||||
GasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
|
GasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
|
||||||
GasTipCap: new(big.Int).Set(tx.GasTipCap()),
|
GasTipCap: new(big.Int).Set(tx.GasTipCap()),
|
||||||
To: tx.To(),
|
To: tx.To(),
|
||||||
Value: tx.Value(),
|
Value: tx.Value(),
|
||||||
Data: tx.Data(),
|
Data: tx.Data(),
|
||||||
AccessList: tx.AccessList(),
|
AccessList: tx.AccessList(),
|
||||||
SkipAccountChecks: false,
|
SkipNonceChecks: false,
|
||||||
BlobHashes: tx.BlobHashes(),
|
SkipFromEoACheck: false,
|
||||||
BlobGasFeeCap: tx.BlobGasFeeCap(),
|
BlobHashes: tx.BlobHashes(),
|
||||||
|
BlobGasFeeCap: tx.BlobGasFeeCap(),
|
||||||
}
|
}
|
||||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
||||||
if baseFee != nil {
|
if baseFee != nil {
|
||||||
|
|
@ -280,7 +283,7 @@ func (st *StateTransition) buyGas() error {
|
||||||
func (st *StateTransition) preCheck() error {
|
func (st *StateTransition) preCheck() error {
|
||||||
// Only check transactions that are not fake
|
// Only check transactions that are not fake
|
||||||
msg := st.msg
|
msg := st.msg
|
||||||
if !msg.SkipAccountChecks {
|
if !msg.SkipNonceChecks {
|
||||||
// Make sure this transaction's nonce is correct.
|
// Make sure this transaction's nonce is correct.
|
||||||
stNonce := st.state.GetNonce(msg.From)
|
stNonce := st.state.GetNonce(msg.From)
|
||||||
if msgNonce := msg.Nonce; stNonce < msgNonce {
|
if msgNonce := msg.Nonce; stNonce < msgNonce {
|
||||||
|
|
@ -293,6 +296,8 @@ func (st *StateTransition) preCheck() error {
|
||||||
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
|
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
|
||||||
msg.From.Hex(), stNonce)
|
msg.From.Hex(), stNonce)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !msg.SkipFromEoACheck {
|
||||||
// Make sure the sender is an EOA
|
// Make sure the sender is an EOA
|
||||||
codeHash := st.state.GetCodeHash(msg.From)
|
codeHash := st.state.GetCodeHash(msg.From)
|
||||||
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash {
|
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash {
|
||||||
|
|
|
||||||
|
|
@ -951,7 +951,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
msg = args.ToMessage(vmctx.BaseFee, true)
|
msg = args.ToMessage(vmctx.BaseFee, true, true)
|
||||||
tx = args.ToTransaction(args.GasPrice == nil)
|
tx = args.ToTransaction(args.GasPrice == nil)
|
||||||
traceConfig *TraceConfig
|
traceConfig *TraceConfig
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1172,7 +1172,7 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
|
||||||
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
|
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
msg := args.ToMessage(header.BaseFee, skipChecks)
|
msg := args.ToMessage(header.BaseFee, skipChecks, skipChecks)
|
||||||
// Lower the basefee to 0 to avoid breaking EVM
|
// Lower the basefee to 0 to avoid breaking EVM
|
||||||
// invariants (basefee < feecap).
|
// invariants (basefee < feecap).
|
||||||
if msg.GasPrice.Sign() == 0 {
|
if msg.GasPrice.Sign() == 0 {
|
||||||
|
|
@ -1299,7 +1299,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
||||||
if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
|
if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
call := args.ToMessage(header.BaseFee, true)
|
call := args.ToMessage(header.BaseFee, true, true)
|
||||||
|
|
||||||
// Run the gas estimation and wrap any revertals into a custom return
|
// Run the gas estimation and wrap any revertals into a custom return
|
||||||
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
|
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
|
||||||
|
|
@ -1633,7 +1633,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
statedb := db.Copy()
|
statedb := db.Copy()
|
||||||
// Set the accesslist to the last al
|
// Set the accesslist to the last al
|
||||||
args.AccessList = &accessList
|
args.AccessList = &accessList
|
||||||
msg := args.ToMessage(header.BaseFee, true)
|
msg := args.ToMessage(header.BaseFee, true, true)
|
||||||
|
|
||||||
// Apply the transaction with the access list tracer
|
// Apply the transaction with the access list tracer
|
||||||
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
||||||
|
|
|
||||||
|
|
@ -1720,6 +1720,41 @@ func TestSimulateV1(t *testing.T) {
|
||||||
want: nil,
|
want: nil,
|
||||||
expectErr: &invalidTxError{Message: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 4712388)", accounts[2].addr), Code: errCodeNonceTooHigh},
|
expectErr: &invalidTxError{Message: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 4712388)", accounts[2].addr), Code: errCodeNonceTooHigh},
|
||||||
},
|
},
|
||||||
|
// Contract sends tx in validation mode.
|
||||||
|
{
|
||||||
|
name: "validation-checks-from-contract",
|
||||||
|
tag: latest,
|
||||||
|
blocks: []simBlock{{
|
||||||
|
StateOverrides: &StateOverride{
|
||||||
|
randomAccounts[2].addr: OverrideAccount{
|
||||||
|
Balance: newRPCBalance(big.NewInt(2098640803896784)),
|
||||||
|
Code: hex2Bytes("00"),
|
||||||
|
Nonce: newUint64(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Calls: []TransactionArgs{{
|
||||||
|
From: &randomAccounts[2].addr,
|
||||||
|
To: &cac,
|
||||||
|
Nonce: newUint64(1),
|
||||||
|
MaxFeePerGas: newInt(233138868),
|
||||||
|
MaxPriorityFeePerGas: newInt(1),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
validation: &validation,
|
||||||
|
want: []blockRes{{
|
||||||
|
Number: "0xb",
|
||||||
|
GasLimit: "0x47e7c4",
|
||||||
|
GasUsed: "0xd166",
|
||||||
|
Miner: coinbase,
|
||||||
|
BaseFeePerGas: "0xde56ab3",
|
||||||
|
Calls: []callRes{{
|
||||||
|
ReturnValue: "0x",
|
||||||
|
GasUsed: "0xd166",
|
||||||
|
Logs: []log{},
|
||||||
|
Status: "0x1",
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
// Successful validation
|
// Successful validation
|
||||||
{
|
{
|
||||||
name: "validation-checks-success",
|
name: "validation-checks-success",
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
}
|
}
|
||||||
tx := call.ToTransaction(call.GasPrice == nil)
|
tx := call.ToTransaction(call.GasPrice == nil)
|
||||||
txes[i] = tx
|
txes[i] = tx
|
||||||
msg := call.ToMessage(header.BaseFee, !sim.validate)
|
// EoA check is always skipped, even in validation mode.
|
||||||
|
msg := call.ToMessage(header.BaseFee, !sim.validate, true)
|
||||||
tracer.reset(tx.Hash(), uint(i))
|
tracer.reset(tx.Hash(), uint(i))
|
||||||
evm.Reset(core.NewEVMTxContext(msg), sim.state)
|
evm.Reset(core.NewEVMTxContext(msg), sim.state)
|
||||||
result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, gp)
|
result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, gp)
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
|
||||||
// core evm. This method is used in calls and traces that do not require a real
|
// core evm. This method is used in calls and traces that do not require a real
|
||||||
// live transaction.
|
// live transaction.
|
||||||
// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
|
// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
|
||||||
func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipChecks bool) *core.Message {
|
func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message {
|
||||||
var (
|
var (
|
||||||
gasPrice *big.Int
|
gasPrice *big.Int
|
||||||
gasFeeCap *big.Int
|
gasFeeCap *big.Int
|
||||||
|
|
@ -452,19 +452,20 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipChecks bool) *core.
|
||||||
accessList = *args.AccessList
|
accessList = *args.AccessList
|
||||||
}
|
}
|
||||||
return &core.Message{
|
return &core.Message{
|
||||||
From: args.from(),
|
From: args.from(),
|
||||||
To: args.To,
|
To: args.To,
|
||||||
Value: (*big.Int)(args.Value),
|
Value: (*big.Int)(args.Value),
|
||||||
Nonce: uint64(*args.Nonce),
|
Nonce: uint64(*args.Nonce),
|
||||||
GasLimit: uint64(*args.Gas),
|
GasLimit: uint64(*args.Gas),
|
||||||
GasPrice: gasPrice,
|
GasPrice: gasPrice,
|
||||||
GasFeeCap: gasFeeCap,
|
GasFeeCap: gasFeeCap,
|
||||||
GasTipCap: gasTipCap,
|
GasTipCap: gasTipCap,
|
||||||
Data: args.data(),
|
Data: args.data(),
|
||||||
AccessList: accessList,
|
AccessList: accessList,
|
||||||
BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
|
BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
|
||||||
BlobHashes: args.BlobHashes,
|
BlobHashes: args.BlobHashes,
|
||||||
SkipAccountChecks: skipChecks,
|
SkipNonceChecks: skipNonceCheck,
|
||||||
|
SkipFromEoACheck: skipEoACheck,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue