Skip to content

Commit f32d12e

Browse files
authored
feat: EIP-7702 Set Code Transaction support (#42)
* chore: update Go version to 1.21 * feat: implement EIP-7702 set code transaction type Add support for EIP-7702 (SetCodeTx) which allows EOAs to temporarily delegate their code execution to another account. Changes include: - Add SetCodeTx (type 0x04) transaction type and Authorization struct - Add anzeonSigner for EIP-7702 transaction signing - Implement delegation designator resolution in EVM - Add EIP-7702 specific gas calculation for CALL variants - Update EXTCODE* opcodes to handle delegation designators - Add prestate tracer support for authorization list - Update t8n tool and tests for SetCodeTx Based on ethereum/go-ethereum#30078 * fix: complete EIP-7702 authorization marshaling and eth_call support Based on ethereum/go-ethereum#30926 * refactor: improve EIP-7702 API naming - Rename Authorization to SetCodeAuthorization - Rename SignAuth to SignSetCode with key-first parameter order Based on ethereum/go-ethereum#30933 * fix: rename SetCodeAuthorization 'v' to 'yParity' The API spec requires the name yParity. Based on: - ethereum/go-ethereum@73a4ecf - ethereum/go-ethereum#30936 * refactor: rename AuthList to SetCodeAuthorizations Use SetCode prefix consistently in internal APIs for the authorization list, as a follow-up to SetCodeAuthorization type renaming. Based on ethereum/go-ethereum#30935 * refactor: change SetCodeTx.ChainID to uint256 Change ChainID field type from uint64 to uint256.Int in SetCodeTx and SetCodeAuthorization for consistency with other chain ID handling. Also removes unused json/gencodec tags from signature value fields in DynamicFeeTx, BlobTx, SetCodeTx, and FeeDelegateDynamicFeeTx. Based on ethereum/go-ethereum#30982 * fix: correct chainId check for anzeonSigner Use zero value check for SetCodeTx chainId validation. This aligns with cancunSigner and londonSigner as well. Based on ethereum/go-ethereum#31032 * fix: initialize ChainID in SetCodeTx copy method ChainID should be properly initialized and copied in the copy() method to prevent nil pointer issues during transaction processing. Based on ethereum/go-ethereum#31054 * refactor: remove EXTCODE* special handling for EIP-7702 EXTCODE* opcodes no longer need special overrides for EIP-7702 delegation designators. The delegation designator is now returned as-is. Implements EIPs#9248. Based on ethereum/go-ethereum#31089 * feat: add EIP-7702 SetCode transaction pool support Add SetCode transaction handling to legacypool: - SetCodeTxType validation with Anzeon fork check - Empty authorization rejection - Authority tracking and conflict prevention - Account slot limit for delegated accounts and pending authorizations Note: tx replacement is not supported in go-stablenet. Tests are adjusted to expect ErrAccountLimitExceeded instead of successful replacement. Based on ethereum/go-ethereum#31073 * test: add setCodeTx reorg test Based on ethereum/go-ethereum#31206 * refactor: move setcode tx validation into legacyPool Move authorization-related validations from common validation to legacyPool since these checks are specific to SetCode transactions. Based on ethereum/go-ethereum#31209 * fix: fix error logs flood caused by removeAuthorities Fix removeAuthorities to only iterate tx's authorities instead of all authorities in the pool. Based on ethereum/go-ethereum#31249 * refactor: reduce allocs in transaction signing Add sigHash method to TxData interface and move hash computation into each tx type, reducing allocations during signature operations. Based on ethereum/go-ethereum#31258 * fix: reject gapped tx from delegated account Add checkDelegationLimit to reject transactions with gapped nonces from delegated accounts. Only one in-flight executable transaction is allowed for senders with delegation or pending delegation. Based on ethereum/go-ethereum#31430 * fix: exclude 7702 authorities from eth_createAccessList result Exclude valid EIP-7702 authorities from access list generation result. Based on ethereum/go-ethereum#31336 (which resolves ethereum/go-ethereum#31335) * fix: data race in checkDelegationLimit Add delegationTxsCount method with proper lock to fix data race when accessing auths map in checkDelegationLimit. Based on ethereum/go-ethereum#31475 * feat: add EIP-7702 protection to blobpool Add delegation limit checks to blobpool: - Limit senders with delegation/pending auth to one in-flight tx - Check reserver for authority conflicts - Refactor AddressReserver to Reserver struct with Hold/Release/Has Based on ethereum/go-ethereum#31526 * fix: slot limit check and update comments - Skip slot limit validation for tx replacements (same nonce reuses slot) - Clarify cumulative balance validation skip reason: fee delegation compatibility * fix: allow tx and authority regardless of admission order Check reserver for authority conflicts to make authorization validation independent of admission order. Authorities must not conflict with addresses reserved by other subpools. Based on ethereum/go-ethereum#31373 * fix: fix data race of txlookup access in test Reset txlookup fields directly with proper locking instead of assigning a new lookup object to avoid data race. Based on ethereum/go-ethereum#31641 * feat: allow passing AuthorizationList to eth_call and eth_estimateGas Add AuthorizationList field to CallMsg and toCallArg to support SetCodeTx in eth_call and eth_estimateGas APIs. Based on ethereum/go-ethereum#31198 * fix: fix data race of pricedList access Use Reheap() instead of assigning a new pricedList to avoid data race when clearing pool state. Based on ethereum/go-ethereum#31758 * fix: resolve incorrect prestate for EIP-7702 authority accounts Before: Authority accounts' prestate showed post-authorization code/storage and incorrect balance/nonce due to wrong capture timing After: Authority accounts' prestate correctly reflects state before SetCodeAuthorization is applied - Refactor EVMLogger to pass env in CaptureTxStart instead of CaptureStart - Capture authority accounts before delegation code (0xef0100...) is set - Preserve original code/storage while restoring only gas from balance * feat: prestate tracer lookup EIP-7702 delegation account Parse and lookup the delegation account if EIP-7702 is enabled in prestate tracer. Implements ethereum/go-ethereum#32078 Based on ethereum/go-ethereum#32080 * refactor: expose sigHash as SigHash for SetCodeAuthorization Rename the private sigHash() method to public SigHash() method to enable external signing (e.g., MPC signing). Based on ethereum/go-ethereum#32298 (which resolves ethereum/go-ethereum#32297) * fix: resolve test failures in tracer and blobpool - Add tracer lifecycle calls in runtime package - Fix EIP-7702 and blobpool test configs * Revert "chore: update Go version to 1.21" This reverts commit 71e90d7. * fix: support AuthorizationList in simulated backend gas estimation
1 parent bef91ea commit f32d12e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3294
-555
lines changed

accounts/external/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
215215
switch tx.Type() {
216216
case types.LegacyTxType, types.AccessListTxType:
217217
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
218-
case types.DynamicFeeTxType:
218+
case types.DynamicFeeTxType, types.SetCodeTxType:
219219
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
220220
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
221221
default:

cmd/evm/internal/t8ntool/tracewriter.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"math/big"
2323

2424
"github.com/ethereum/go-ethereum/common"
25+
"github.com/ethereum/go-ethereum/core/types"
2526
"github.com/ethereum/go-ethereum/core/vm"
2627
"github.com/ethereum/go-ethereum/eth/tracers"
2728
"github.com/ethereum/go-ethereum/log"
@@ -56,9 +57,11 @@ func (t *traceWriter) CaptureTxEnd(restGas uint64) {
5657
}
5758
}
5859

59-
func (t *traceWriter) CaptureTxStart(gasLimit uint64) { t.inner.CaptureTxStart(gasLimit) }
60-
func (t *traceWriter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
61-
t.inner.CaptureStart(env, from, to, create, input, gas, value)
60+
func (t *traceWriter) CaptureTxStart(env *vm.EVM, gasLimit uint64, authList []types.SetCodeAuthorization) {
61+
t.inner.CaptureTxStart(env, gasLimit, authList)
62+
}
63+
func (t *traceWriter) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
64+
t.inner.CaptureStart(from, to, create, input, gas, value)
6265
}
6366

6467
func (t *traceWriter) CaptureEnd(output []byte, gasUsed uint64, err error) {

cmd/evm/internal/t8ntool/transaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func Transaction(ctx *cli.Context) error {
133133
r.Address = sender
134134
}
135135
// Check intrinsic gas
136-
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
136+
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
137137
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil {
138138
r.Error = err
139139
results = append(results, r)

cmd/evm/t8n_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ func TestT8n(t *testing.T) {
284284
output: t8nOutput{alloc: true, result: true},
285285
expOut: "exp.json",
286286
},
287+
{ // Anzeon test, EIP-7702 transaction
288+
base: "./testdata/33",
289+
input: t8nInput{
290+
"alloc.json", "txs.json", "env.json", "Anzeon", "",
291+
},
292+
output: t8nOutput{alloc: true, result: true},
293+
expOut: "exp.json",
294+
},
287295
} {
288296
args := []string{"t8n"}
289297
args = append(args, tc.output.get()...)

cmd/evm/testdata/33/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This test sets some EIP-7702 delegations and calls them.

cmd/evm/testdata/33/alloc.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"0x8a0a19589531694250d570040a0c4b74576919b8": {
3+
"nonce": "0x00",
4+
"balance": "0x0de0b6b3a7640000",
5+
"code": "0x600060006000600060007310000000000000000000000000000000000000015af1600155600060006000600060007310000000000000000000000000000000000000025af16002553d600060003e600051600355",
6+
"storage": {
7+
"0x01": "0x0100",
8+
"0x02": "0x0100",
9+
"0x03": "0x0100"
10+
}
11+
},
12+
"0x000000000000000000000000000000000000aaaa": {
13+
"nonce": "0x00",
14+
"balance": "0x4563918244f40000",
15+
"code": "0x58808080600173703c4b2bd70c169f5717101caee543299fc946c75af100",
16+
"storage": {}
17+
},
18+
"0x000000000000000000000000000000000000bbbb": {
19+
"nonce": "0x00",
20+
"balance": "0x29a2241af62c0000",
21+
"code": "0x6042805500",
22+
"storage": {}
23+
},
24+
"0x71562b71999873DB5b286dF957af199Ec94617F7": {
25+
"nonce": "0x00",
26+
"balance": "0x6124fee993bc0000",
27+
"code": "0x",
28+
"storage": {}
29+
}
30+
}

cmd/evm/testdata/33/env.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
3+
"currentGasLimit": "71794957647893862",
4+
"currentNumber": "1",
5+
"currentTimestamp": "1000",
6+
"currentRandom": "0",
7+
"currentDifficulty": "0",
8+
"blockHashes": {},
9+
"ommers": [],
10+
"currentBaseFee": "7",
11+
"parentUncleHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
12+
"withdrawals": [],
13+
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000"
14+
}

cmd/evm/testdata/33/exp.json

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"alloc": {
3+
"0x000000000000000000000000000000000000aaaa": {
4+
"code": "0x58808080600173703c4b2bd70c169f5717101caee543299fc946c75af100",
5+
"balance": "0x4563918244f40000"
6+
},
7+
"0x000000000000000000000000000000000000bbbb": {
8+
"code": "0x6042805500",
9+
"balance": "0x29a2241af62c0000"
10+
},
11+
"0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": {
12+
"balance": "0xc0189"
13+
},
14+
"0x703c4b2bd70c169f5717101caee543299fc946c7": {
15+
"code": "0xef0100000000000000000000000000000000000000bbbb",
16+
"storage": {
17+
"0x0000000000000000000000000000000000000000000000000000000000000042": "0x0000000000000000000000000000000000000000000000000000000000000042"
18+
},
19+
"balance": "0x1",
20+
"nonce": "0x1"
21+
},
22+
"0x71562b71999873db5b286df957af199ec94617f7": {
23+
"code": "0xef0100000000000000000000000000000000000000aaaa",
24+
"balance": "0x6124fee993affe76",
25+
"nonce": "0x2"
26+
},
27+
"0x8a0a19589531694250d570040a0c4b74576919b8": {
28+
"code": "0x600060006000600060007310000000000000000000000000000000000000015af1600155600060006000600060007310000000000000000000000000000000000000025af16002553d600060003e600051600355",
29+
"storage": {
30+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000100",
31+
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000100",
32+
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000100"
33+
},
34+
"balance": "0xde0b6b3a7640000"
35+
}
36+
},
37+
"result": {
38+
"stateRoot": "0x1e651689182e93c4ac6ae325b3892016e4dfe61b83e690ea84299a34f0540c12",
39+
"txRoot": "0x5d13a0b074e80388dc754da92b22922313a63417b3e25a10f324935e09697a53",
40+
"receiptsRoot": "0xaeb286ce5a9f77001f07b7f58f3e5e5963c734b3dc8a77828911647cf7f0e8f6",
41+
"logsHash": "0x746a99701f8a36a95ad98bc6cc600161a78944b40c0ea7c39964aefba864de97",
42+
"logsBloom": "0x00000000000000100000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000008000000002000000000000000000000000020000000000020000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000400000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000002000000000000800000000000000000000000000000000100000000000000000000000000000000000000000000000020000000000000000000000000",
43+
"receipts": [
44+
{
45+
"type": "0x4",
46+
"root": "0x",
47+
"status": "0x1",
48+
"cumulativeGasUsed": "0x15581",
49+
"logsBloom": "0x00000000000000100000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000008000000002000000000000000000000000020000000000020000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000400000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000002000000000000800000000000000000000000000000000100000000000000000000000000000000000000000000000020000000000000000000000000",
50+
"logs": [
51+
{
52+
"address": "0x0000000000000000000000000000000000001000",
53+
"topics": [
54+
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
55+
"0x00000000000000000000000071562b71999873db5b286df957af199ec94617f7",
56+
"0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7"
57+
],
58+
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
59+
"blockNumber": "0x1",
60+
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
61+
"transactionIndex": "0x0",
62+
"blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
63+
"logIndex": "0x0",
64+
"removed": false
65+
},
66+
{
67+
"address": "0x0000000000000000000000000000000000001000",
68+
"topics": [
69+
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
70+
"0x00000000000000000000000071562b71999873db5b286df957af199ec94617f7",
71+
"0x0000000000000000000000002adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
72+
],
73+
"data": "0x00000000000000000000000000000000000000000000000000000000000c0189",
74+
"blockNumber": "0x1",
75+
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
76+
"transactionIndex": "0x0",
77+
"blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
78+
"logIndex": "0x1",
79+
"removed": false
80+
}
81+
],
82+
"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
83+
"contractAddress": "0x0000000000000000000000000000000000000000",
84+
"gasUsed": "0x15581",
85+
"effectiveGasPrice": "0x9",
86+
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
87+
"transactionIndex": "0x0"
88+
}
89+
],
90+
"currentDifficulty": "0x0",
91+
"gasUsed": "0x15581",
92+
"currentBaseFee": "0x7",
93+
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
94+
}
95+
}

cmd/evm/testdata/33/txs.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[
2+
{
3+
"type": "0x4",
4+
"chainId": "0x1",
5+
"nonce": "0x0",
6+
"to": "0x71562b71999873db5b286df957af199ec94617f7",
7+
"gas": "0x7a120",
8+
"gasPrice": null,
9+
"maxPriorityFeePerGas": "0x2",
10+
"maxFeePerGas": "0x12a05f200",
11+
"value": "0x0",
12+
"input": "0x",
13+
"accessList": [],
14+
"authorizationList": [
15+
{
16+
"chainId": "0x1",
17+
"address": "0x000000000000000000000000000000000000aaaa",
18+
"nonce": "0x1",
19+
"yParity": "0x1",
20+
"r": "0xf7e3e597fc097e71ed6c26b14b25e5395bc8510d58b9136af439e12715f2d721",
21+
"s": "0x6cf7c3d7939bfdb784373effc0ebb0bd7549691a513f395e3cdabf8602724987"
22+
},
23+
{
24+
"chainId": "0x0",
25+
"address": "0x000000000000000000000000000000000000bbbb",
26+
"nonce": "0x0",
27+
"yParity": "0x1",
28+
"r": "0x5011890f198f0356a887b0779bde5afa1ed04e6acb1e3f37f8f18c7b6f521b98",
29+
"s": "0x56c3fa3456b103f3ef4a0acb4b647b9cab9ec4bc68fbcdf1e10b49fb2bcbcf61"
30+
}
31+
],
32+
"secretKey": "0xb71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291",
33+
"v": "0x0",
34+
"r": "0x0",
35+
"s": "0x0"
36+
}
37+
]

core/bench_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
8383
return func(i int, gen *BlockGen) {
8484
toaddr := common.Address{}
8585
data := make([]byte, nbytes)
86-
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
86+
gas, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
8787
signer := gen.Signer()
8888
gasPrice := big.NewInt(0)
8989
if gen.header.BaseFee != nil {

0 commit comments

Comments
 (0)