Skip to content

Commit e631d4c

Browse files
committed
all: implement 6110
1 parent 67fe7af commit e631d4c

File tree

26 files changed

+556
-73
lines changed

26 files changed

+556
-73
lines changed

beacon/engine/gen_ed.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon/engine/types.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ type ExecutableData struct {
7676
Withdrawals []*types.Withdrawal `json:"withdrawals"`
7777
BlobGasUsed *uint64 `json:"blobGasUsed"`
7878
ExcessBlobGas *uint64 `json:"excessBlobGas"`
79-
Deposits []*types.Deposit `json:"depositReceipts"`
79+
Deposits types.Deposits `json:"depositRequests"`
8080
}
8181

8282
// JSON type overrides for executableData.
@@ -231,10 +231,16 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash,
231231
h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil))
232232
withdrawalsRoot = &h
233233
}
234-
var depositsRoot *common.Hash
234+
235+
var (
236+
requestsHash *common.Hash
237+
requests types.Requests
238+
)
235239
if params.Deposits != nil {
236-
h := types.DeriveSha(types.Deposits(params.Deposits), trie.NewStackTrie(nil))
237-
depositsRoot = &h
240+
requests = make(types.Requests, 0)
241+
requests = append(requests, params.Deposits.Requests()...)
242+
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
243+
requestsHash = &h
238244
}
239245
header := &types.Header{
240246
ParentHash: params.ParentHash,
@@ -256,9 +262,9 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash,
256262
ExcessBlobGas: params.ExcessBlobGas,
257263
BlobGasUsed: params.BlobGasUsed,
258264
ParentBeaconRoot: beaconRoot,
259-
DepositsHash: depositsRoot,
265+
RequestsHash: requestsHash,
260266
}
261-
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: params.Withdrawals, Deposits: params.Deposits})
267+
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: params.Withdrawals, Requests: requests})
262268
if block.Hash() != params.BlockHash {
263269
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash())
264270
}

cmd/evm/internal/t8ntool/execution.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ type ExecutionResult struct {
6666
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
6767
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
6868
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
69+
RequestsRoot *common.Hash `json:"requestsRoot,omitempty"`
70+
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
6971
}
7072

7173
type ommer struct {
@@ -368,6 +370,23 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
368370
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
369371
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
370372
}
373+
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
374+
// Parse the requests from the logs
375+
var allLogs []*types.Log
376+
for _, receipt := range receipts {
377+
allLogs = append(allLogs, receipt.Logs...)
378+
}
379+
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
380+
if err != nil {
381+
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
382+
}
383+
// Calculate the requests root
384+
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
385+
execRs.RequestsRoot = &h
386+
// Get the deposits from the requests
387+
deposits := requests.Deposits()
388+
execRs.DepositRequests = &deposits
389+
}
371390
// Re-create statedb instance with new root upon the updated database
372391
// for accessing latest states.
373392
statedb, err = state.New(root, statedb.Database(), nil)

core/block_validator.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,32 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
121121

122122
// ValidateState validates the various changes that happen after a state transition,
123123
// such as amount of used gas, the receipt roots and the state root itself.
124-
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
124+
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult) error {
125+
if res == nil {
126+
return fmt.Errorf("nil ProcessResult value")
127+
}
125128
header := block.Header()
126-
if block.GasUsed() != usedGas {
127-
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
129+
if block.GasUsed() != res.GasUsed {
130+
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), res.GasUsed)
128131
}
129132
// Validate the received block's bloom with the one derived from the generated receipts.
130133
// For valid blocks this should always validate to true.
131-
rbloom := types.CreateBloom(receipts)
134+
rbloom := types.CreateBloom(res.Receipts)
132135
if rbloom != header.Bloom {
133136
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
134137
}
135138
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
136-
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
139+
receiptSha := types.DeriveSha(res.Receipts, trie.NewStackTrie(nil))
137140
if receiptSha != header.ReceiptHash {
138141
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
139142
}
143+
// Validate the parsed requests match the expected header value.
144+
if header.RequestsHash != nil {
145+
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
146+
if depositSha != *header.RequestsHash {
147+
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
148+
}
149+
}
140150
// Validate the state root against the received state root and throw
141151
// an error if they don't match.
142152
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {

core/blockchain.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
16141614
return 0, errChainStopped
16151615
}
16161616
defer bc.chainmu.Unlock()
1617+
16171618
return bc.insertChain(chain, true)
16181619
}
16191620

@@ -1916,16 +1917,16 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
19161917

19171918
// Process block using the parent state as reference point
19181919
pstart := time.Now()
1919-
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
1920+
res, err := bc.processor.Process(block, statedb, bc.vmConfig)
19201921
if err != nil {
1921-
bc.reportBlock(block, receipts, err)
1922+
bc.reportBlock(block, nil, err)
19221923
return nil, err
19231924
}
19241925
ptime := time.Since(pstart)
19251926

19261927
vstart := time.Now()
1927-
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
1928-
bc.reportBlock(block, receipts, err)
1928+
if err := bc.validator.ValidateState(block, statedb, res); err != nil {
1929+
bc.reportBlock(block, res.Receipts, err)
19291930
return nil, err
19301931
}
19311932
vtime := time.Since(vstart)
@@ -1953,9 +1954,9 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
19531954
)
19541955
if !setHead {
19551956
// Don't set the head, only insert the block
1956-
err = bc.writeBlockWithState(block, receipts, statedb)
1957+
err = bc.writeBlockWithState(block, res.Receipts, statedb)
19571958
} else {
1958-
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
1959+
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, false)
19591960
}
19601961
if err != nil {
19611962
return nil, err
@@ -1969,7 +1970,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
19691970
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
19701971
blockInsertTimer.UpdateSince(start)
19711972

1972-
return &blockProcessingResult{usedGas: usedGas, procTime: proctime, status: status}, nil
1973+
return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil
19731974
}
19741975

19751976
// insertSideChain is called when an import batch hits upon a pruned ancestor

core/blockchain_test.go

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,14 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
163163
if err != nil {
164164
return err
165165
}
166-
receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{})
166+
res, err := blockchain.processor.Process(block, statedb, vm.Config{})
167167
if err != nil {
168-
blockchain.reportBlock(block, receipts, err)
168+
blockchain.reportBlock(block, res.Receipts, err)
169169
return err
170170
}
171-
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
171+
err = blockchain.validator.ValidateState(block, statedb, res)
172172
if err != nil {
173-
blockchain.reportBlock(block, receipts, err)
173+
blockchain.reportBlock(block, res.Receipts, err)
174174
return err
175175
}
176176

@@ -4221,3 +4221,86 @@ func TestEIP3651(t *testing.T) {
42214221
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
42224222
}
42234223
}
4224+
4225+
func TestEIP6110(t *testing.T) {
4226+
var (
4227+
engine = beacon.NewFaker()
4228+
4229+
// A sender who makes transactions, has some funds
4230+
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
4231+
addr = crypto.PubkeyToAddress(key.PublicKey)
4232+
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
4233+
config = *params.AllEthashProtocolChanges
4234+
gspec = &Genesis{
4235+
Config: &config,
4236+
Alloc: types.GenesisAlloc{
4237+
addr: {Balance: funds},
4238+
config.DepositContractAddress: {
4239+
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
4240+
Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"),
4241+
Nonce: 0,
4242+
Balance: big.NewInt(0),
4243+
},
4244+
},
4245+
}
4246+
)
4247+
4248+
gspec.Config.BerlinBlock = common.Big0
4249+
gspec.Config.LondonBlock = common.Big0
4250+
gspec.Config.TerminalTotalDifficulty = common.Big0
4251+
gspec.Config.TerminalTotalDifficultyPassed = true
4252+
gspec.Config.ShanghaiTime = u64(0)
4253+
gspec.Config.CancunTime = u64(0)
4254+
gspec.Config.PragueTime = u64(0)
4255+
signer := types.LatestSigner(gspec.Config)
4256+
4257+
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
4258+
for i := 0; i < 5; i++ {
4259+
txdata := &types.DynamicFeeTx{
4260+
ChainID: gspec.Config.ChainID,
4261+
Nonce: uint64(i),
4262+
To: &config.DepositContractAddress,
4263+
Gas: 500000,
4264+
GasFeeCap: newGwei(5),
4265+
GasTipCap: big.NewInt(2),
4266+
AccessList: nil,
4267+
Data: []byte{},
4268+
}
4269+
tx := types.NewTx(txdata)
4270+
tx, _ = types.SignTx(tx, signer, key)
4271+
b.AddTx(tx)
4272+
}
4273+
})
4274+
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{DisableStack: true}, os.Stderr).Hooks()}, nil, nil)
4275+
if err != nil {
4276+
t.Fatalf("failed to create tester chain: %v", err)
4277+
}
4278+
defer chain.Stop()
4279+
if n, err := chain.InsertChain(blocks); err != nil {
4280+
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
4281+
}
4282+
4283+
block := chain.GetBlockByNumber(1)
4284+
if len(block.Deposits()) != 5 {
4285+
t.Fatalf("failed to retreive deposits: have %d, want %d", len(block.Deposits()), 5)
4286+
}
4287+
4288+
// Verify each index is correct.
4289+
for want, d := range block.Deposits() {
4290+
if got := int(d.PublicKey[0]); got != want {
4291+
t.Fatalf("invalid pubkey: have %d, want %d", got, want)
4292+
}
4293+
if got := int(d.WithdrawalCredentials[0]); got != want {
4294+
t.Fatalf("invalid withdrawal credentials: have %d, want %d", got, want)
4295+
}
4296+
if d.Amount != uint64(want) {
4297+
t.Fatalf("invalid amounbt: have %d, want %d", d.Amount, want)
4298+
}
4299+
if got := int(d.Signature[0]); got != want {
4300+
t.Fatalf("invalid signature: have %d, want %d", got, want)
4301+
}
4302+
if d.Index != uint64(want) {
4303+
t.Fatalf("invalid index: have %d, want %d", d.Index, want)
4304+
}
4305+
}
4306+
}

core/chain_makers.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,18 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
346346
gen(i, b)
347347
}
348348

349-
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
349+
var requests types.Requests
350+
if config.IsPrague(b.header.Number, b.header.Time) {
351+
for _, r := range b.receipts {
352+
d, err := ParseDepositLogs(r.Logs, config)
353+
if err != nil {
354+
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
355+
}
356+
requests = append(requests, d...)
357+
}
358+
}
359+
360+
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
350361
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
351362
if err != nil {
352363
panic(err)

core/genesis.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,10 @@ func (g *Genesis) ToBlock() *types.Block {
453453
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
454454
}
455455
}
456-
var withdrawals []*types.Withdrawal
456+
var (
457+
withdrawals []*types.Withdrawal
458+
requests types.Requests
459+
)
457460
if conf := g.Config; conf != nil {
458461
num := big.NewInt(int64(g.Number))
459462
if conf.IsShanghai(num, g.Timestamp) {
@@ -475,8 +478,12 @@ func (g *Genesis) ToBlock() *types.Block {
475478
head.BlobGasUsed = new(uint64)
476479
}
477480
}
481+
if conf.IsPrague(num, g.Timestamp) {
482+
head.RequestsHash = &types.EmptyRequestsHash
483+
requests = make(types.Requests, 0)
484+
}
478485
}
479-
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
486+
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
480487
}
481488

482489
// Commit writes the block and state of a genesis specification to the database.

0 commit comments

Comments
 (0)