Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal/ethapi: eth_simulateV1 #27720

Merged
merged 131 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
62d33d5
internal/ethapi: add multicall method
s1na May 26, 2023
80df50d
add test case for logs
s1na Jun 5, 2023
c3f1494
add ecrecover override
s1na Jun 6, 2023
a219206
forgot to commit other files
s1na Jun 6, 2023
0285f81
dont abort on call validation error
s1na Jun 6, 2023
c301ce4
add state buildup test
s1na Jun 6, 2023
922f72c
test block override defaults to base
s1na Jun 6, 2023
80bcb16
check block nums are in order
s1na Jun 6, 2023
4478f20
add method to web3ext
s1na Jun 8, 2023
2ae2fe5
add transfers
s1na Jun 8, 2023
0aaaf34
forgot the tracer
s1na Jun 8, 2023
2db37b9
minor
s1na Jun 8, 2023
04965a3
fix marshaling of empty values
s1na Jun 15, 2023
c78330d
rename to multicallV1
s1na Jun 30, 2023
8fff7fd
return block info except blockhash
s1na Jul 3, 2023
637acc5
Finalise state after call, add selfdestruct test
s1na Jul 13, 2023
d23eb89
Add status field to call result
s1na Jul 13, 2023
a7af5a9
wrap params into an object
s1na Jul 13, 2023
98882fc
blockhash = keccak(blockNum)
s1na Jul 13, 2023
b865824
name tests
s1na Jul 17, 2023
da3102e
persist precompiles in evm
s1na Jul 17, 2023
6a2c96c
add storage clearing test case for eth_call
s1na Jul 18, 2023
b3efbad
implement precompile override and moveTo feature
s1na Jul 18, 2023
9aed710
copy storage over in MoveTo
s1na Jul 18, 2023
2c25ab6
add todo comments
s1na Jul 24, 2023
5d351c9
add testcase moveto precompile
s1na Jul 31, 2023
63f4f6e
rm ecrecover override field
s1na Jul 31, 2023
80506ea
rename blocks to blockStateCalls
s1na Jul 31, 2023
fd786c0
rename to moveToAddress
s1na Aug 1, 2023
6845b5e
add optional validation of txes
s1na Aug 1, 2023
c5e33fa
test coinbase
s1na Aug 2, 2023
d4e332e
fix storage clearing
s1na Aug 3, 2023
b0e7869
Rename block override field names
s1na Sep 4, 2023
56b4402
auto-set and validate block number and timestamp
s1na Sep 4, 2023
7e17e4c
implement transfers as logs
s1na Sep 4, 2023
fe3bb83
add prevrandao to result
s1na Sep 5, 2023
906d93a
clear logs on call fail
s1na Sep 5, 2023
8e02675
add txhash to logs
s1na Sep 7, 2023
a0d2706
moveTo only for precompiles
s1na Sep 11, 2023
ed4cbaf
resolve merge conflicts
s1na Sep 13, 2023
3231291
optional block param
s1na Sep 20, 2023
3df0fec
rename return to returnData
s1na Sep 20, 2023
760f5e5
fix tx gaslimit and type default
s1na Sep 20, 2023
b3996e4
dont set defaults for calls
s1na Sep 20, 2023
100c593
fix crasher
s1na Sep 29, 2023
523e3d2
cover it in test case
s1na Sep 29, 2023
d5c0ff4
add error codes to calls
s1na Oct 4, 2023
45ba37e
compute block hash based on header
s1na Oct 5, 2023
973116c
repair logs
s1na Oct 5, 2023
a5ffd9a
serve blockhash requests
s1na Oct 6, 2023
cc1158a
possibly fix crasher
s1na Oct 10, 2023
2690445
fix block hash cache
s1na Oct 10, 2023
d1ce690
move multicall logic to struct
s1na Oct 10, 2023
e230258
move precompile list to own func
s1na Oct 10, 2023
c02d29d
limit number of blocks
s1na Oct 24, 2023
e4eb56a
add error code for blocks length check
s1na Oct 24, 2023
ed37821
rename types
s1na Oct 24, 2023
f5ac039
fix error codes
s1na Oct 26, 2023
23ef9c6
minor fix
s1na Nov 13, 2023
6da9202
Fix extra delegatecall value log
s1na Dec 14, 2023
12d59b5
update transfer log address
s1na Dec 14, 2023
1616559
resolve merge conflicts
s1na Dec 14, 2023
7fff1c4
Add cancun to precompiled contracts
s1na Dec 14, 2023
bf78094
safer api for getting active precompiles
s1na Dec 14, 2023
c594f74
fix godoc comment
s1na Jan 3, 2024
11133e0
fix precompileMove in eth_call
s1na Jan 3, 2024
ad24d2e
rename block overrides receiver name
s1na Jan 3, 2024
c77da8c
rename validate param
s1na Jan 3, 2024
3d29c1f
copy header prior to applying overrides
s1na Jan 3, 2024
31e2cc9
legacy tx if gasPrice provided
s1na Jan 4, 2024
5ed9958
resolve merge conflict
s1na Jan 4, 2024
2b1cf22
fix graphql test
s1na Jan 4, 2024
fd0f626
fix rpcgascap for ethclient tests
s1na Jan 4, 2024
1e7b497
fix block overrides in gethclient
s1na Jan 4, 2024
589107b
rename to blobGasPrice
s1na Jan 5, 2024
89df0e3
rename method to eth_simulateV1
s1na Jan 11, 2024
1a28a17
move call sanitization to own method
s1na Jan 15, 2024
115117c
move tx type detection check
s1na Jan 15, 2024
df14718
compute receipts
s1na Jan 16, 2024
ae33566
finish renaming to simulate
s1na Jan 17, 2024
12d7dd0
fix empty tx, receipts hash
s1na Jan 17, 2024
214e209
minor rename:
s1na Jan 17, 2024
af155c1
move block processing logic to func
s1na Jan 17, 2024
c73c10a
merge master
s1na Feb 19, 2024
489ef43
fix lint errs
s1na Feb 19, 2024
0c0b13d
rename to blobBaseFee
s1na Feb 19, 2024
86ce924
revert setDefaults changes, skip extra validations:
s1na Feb 21, 2024
4a017ff
rm obsolete test
s1na Feb 21, 2024
49bf257
resolve merge conflict
s1na Feb 21, 2024
9fa1556
fix makeHeaders using unpopulated parent
s1na Mar 5, 2024
7177f22
check gas fee in validation mode
s1na Mar 5, 2024
3daabda
add empty withdrawals obj
s1na Mar 29, 2024
c08ba25
resolve merge conflict
s1na Mar 29, 2024
81e7fe1
fix baseFee, add blobGasUsed and excessBlobGas to result
s1na Apr 5, 2024
8698221
default timestamp bump to 12
s1na May 6, 2024
48ca188
generate empty blocks for gaps
s1na May 7, 2024
81e065c
fix block hashes
s1na May 7, 2024
263cfd7
compute basefee prior to execution
s1na May 22, 2024
e382782
return full header
s1na May 28, 2024
9139685
add fullTx option
s1na May 28, 2024
569a2d7
move out base fee lowering to api code
s1na Jun 6, 2024
d7cd3a0
missed one file
s1na Jun 6, 2024
399812a
set base fee to 0 in non-validating mode
s1na Jun 6, 2024
1c154e9
check base fee in test block results
s1na Jun 6, 2024
638d82b
resolve merge conflict
s1na Jun 7, 2024
ac690f0
fix chainId default
s1na Jun 12, 2024
a9842e5
add td
s1na Jun 12, 2024
a6f80c7
add data on reverts
s1na Jun 12, 2024
5db0106
fix
s1na Jun 12, 2024
4c325ba
skip EoA check in validation mode
s1na Jun 12, 2024
102aa80
resolve merge conflict
s1na Jul 15, 2024
172ed02
refactors
s1na Jul 15, 2024
ddba7dd
rm stale todos
s1na Jul 15, 2024
c0d5dfb
resolve merge conflict
s1na Jul 25, 2024
e3cd999
default timestamp bump 1 sec
s1na Aug 14, 2024
33400fb
review comments, pt. 1
s1na Aug 16, 2024
5f0fafd
fix precompile moveTo
s1na Aug 16, 2024
73ff7e5
move timestamp sanitization
s1na Aug 19, 2024
5d8c058
Clean up sanitizeCall
s1na Aug 19, 2024
edf9e37
Fix lint errors
s1na Aug 19, 2024
e7bac20
add test comments
s1na Aug 19, 2024
9a963dc
add license to simulate_test
s1na Sep 4, 2024
7198fc1
update test to use fixed address
s1na Sep 4, 2024
6ec5083
Merge branch 'master' into multicall
s1na Sep 4, 2024
791719a
core/vm: use maps.Clone
holiman Sep 4, 2024
c216ef5
internal: refactored ToTransaction of transaction args
holiman Sep 4, 2024
2415110
Merge branch 'master' into multicall
s1na Sep 4, 2024
6205806
internal/ethapi: simplify
holiman Sep 5, 2024
098a448
internal/ethapi: abort when context is cancelled
holiman Sep 5, 2024
9da10f9
Merge branch 'master' into multicall
holiman Sep 6, 2024
f25fcd3
internal/ethapi: fix merge-conflicts
holiman Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
skip EoA check in validation mode
  • Loading branch information
s1na committed Jun 12, 2024
commit 4c325ba5b365e44f1c33cfe7b3236bcb685ec2de
37 changes: 21 additions & 16 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,27 +142,30 @@ type Message struct {
BlobGasFeeCap *big.Int
BlobHashes []common.Hash

// When SkipAccountChecks is true, the message nonce is not checked against the
// account nonce in state. It also disables checking that the sender is an EOA.
// When SkipNonceChecks is true, the message nonce is not checked against the
// account nonce in state.
// This field will be set to true for operations like RPC eth_call.
SkipAccountChecks bool
SkipNonceChecks bool
s1na marked this conversation as resolved.
Show resolved Hide resolved
// When SkipFromEoACheck is true, the message sender is not checked to be an EOA.
SkipFromEoACheck bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick, please rename it to SkipFromEOACheck

btw, do you know in which scenario this field/feature will be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right should be EOA definitely 👍

This is used when simulating in validation mode. In validation mode we want everything to be checked but only relax the requirement of the sender to be an EOA, e.g. to still allow calling from a multisig contract.

}

// 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,
BlobHashes: tx.BlobHashes(),
BlobGasFeeCap: tx.BlobGasFeeCap(),
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(),
SkipNonceChecks: false,
SkipFromEoACheck: false,
BlobHashes: tx.BlobHashes(),
BlobGasFeeCap: tx.BlobGasFeeCap(),
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
if baseFee != nil {
Expand Down Expand Up @@ -280,7 +283,7 @@ func (st *StateTransition) buyGas() error {
func (st *StateTransition) preCheck() error {
// Only check transactions that are not fake
msg := st.msg
if !msg.SkipAccountChecks {
if !msg.SkipNonceChecks {
// Make sure this transaction's nonce is correct.
stNonce := st.state.GetNonce(msg.From)
if msgNonce := msg.Nonce; stNonce < msgNonce {
Expand All @@ -293,6 +296,8 @@ func (st *StateTransition) preCheck() error {
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
msg.From.Hex(), stNonce)
}
}
if !msg.SkipFromEoACheck {
// Make sure the sender is an EOA
codeHash := st.state.GetCodeHash(msg.From)
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash {
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
return nil, err
}
var (
msg = args.ToMessage(vmctx.BaseFee, true)
msg = args.ToMessage(vmctx.BaseFee, true, true)
tx = args.ToTransaction(args.GasPrice == nil)
traceConfig *TraceConfig
)
Expand Down
6 changes: 3 additions & 3 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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
// invariants (basefee < feecap).
if msg.GasPrice.Sign() == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps i miss something, originally these basefee and blobbasefee setting are done in NewEVM function. Now you relocate them before each invocation, any reason for it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is weird that EVM is overwriting the block context values. I think it's more correct to do this kind of sanitisation in the API layer.

See how this caused a footgun: #29800 (comment)

Expand Down Expand Up @@ -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 {
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
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
Expand Down Expand Up @@ -1633,7 +1633,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
statedb := db.Copy()
// Set the accesslist to the last al
args.AccessList = &accessList
msg := args.ToMessage(header.BaseFee, true)
msg := args.ToMessage(header.BaseFee, true, true)

// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
Expand Down
35 changes: 35 additions & 0 deletions internal/ethapi/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,41 @@ func TestSimulateV1(t *testing.T) {
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},
},
// 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
{
name: "validation-checks-success",
Expand Down
3 changes: 2 additions & 1 deletion internal/ethapi/simulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
}
tx := call.ToTransaction(call.GasPrice == nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate why it's necessary to pass this additional parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We default to a type-2 transaction in eth_simulate. Other methods default to legacy as is. I'm open to changing that but didn't want to have that scope creep in this PR.

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))
evm.Reset(core.NewEVMTxContext(msg), sim.state)
result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, gp)
Expand Down
29 changes: 15 additions & 14 deletions internal/ethapi/transaction_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
// live transaction.
// 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 (
gasPrice *big.Int
gasFeeCap *big.Int
Expand Down Expand Up @@ -452,19 +452,20 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipChecks bool) *core.
accessList = *args.AccessList
}
return &core.Message{
From: args.from(),
To: args.To,
Value: (*big.Int)(args.Value),
Nonce: uint64(*args.Nonce),
GasLimit: uint64(*args.Gas),
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Data: args.data(),
AccessList: accessList,
BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
BlobHashes: args.BlobHashes,
SkipAccountChecks: skipChecks,
From: args.from(),
To: args.To,
Value: (*big.Int)(args.Value),
Nonce: uint64(*args.Nonce),
GasLimit: uint64(*args.Gas),
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Data: args.data(),
AccessList: accessList,
BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
BlobHashes: args.BlobHashes,
SkipNonceChecks: skipNonceCheck,
SkipFromEoACheck: skipEoACheck,
}
}

Expand Down