Skip to content

Commit c93656f

Browse files
fjllightclientislishude
authored andcommitted
all: implement flat deposit requests encoding (#30425)
This implements recent changes to EIP-7685, EIP-6110, and execution-apis. --------- Co-authored-by: lightclient <[email protected]> Co-authored-by: Shude Li <[email protected]>
1 parent 677bc2a commit c93656f

27 files changed

+222
-627
lines changed

beacon/engine/gen_ed.go

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

beacon/engine/gen_epe.go

Lines changed: 14 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: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ type ExecutableData struct {
7676
Withdrawals []*types.Withdrawal `json:"withdrawals"`
7777
BlobGasUsed *uint64 `json:"blobGasUsed"`
7878
ExcessBlobGas *uint64 `json:"excessBlobGas"`
79-
Deposits types.Deposits `json:"depositRequests"`
8079
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
8180
}
8281

@@ -108,6 +107,7 @@ type ExecutionPayloadEnvelope struct {
108107
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
109108
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
110109
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
110+
Requests [][]byte `json:"executionRequests"`
111111
Override bool `json:"shouldOverrideBuilder"`
112112
Witness *hexutil.Bytes `json:"witness"`
113113
}
@@ -121,6 +121,7 @@ type BlobsBundleV1 struct {
121121
// JSON type overrides for ExecutionPayloadEnvelope.
122122
type executionPayloadEnvelopeMarshaling struct {
123123
BlockValue *hexutil.Big
124+
Requests []hexutil.Bytes
124125
}
125126

126127
type PayloadStatusV1 struct {
@@ -207,8 +208,8 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
207208
// and that the blockhash of the constructed block matches the parameters. Nil
208209
// Withdrawals value will propagate through the returned block. Empty
209210
// Withdrawals value must be passed via non-nil, length 0 value in data.
210-
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
211-
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot)
211+
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
212+
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests)
212213
if err != nil {
213214
return nil, err
214215
}
@@ -221,7 +222,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
221222
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
222223
// for stateless execution, so it skips checking if the executable data hashes to
223224
// the requested hash (stateless has to *compute* the root hash, it's not given).
224-
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
225+
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
225226
txs, err := decodeTransactions(data.Transactions)
226227
if err != nil {
227228
return nil, err
@@ -256,19 +257,13 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
256257
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
257258
withdrawalsRoot = &h
258259
}
259-
// Compute requestsHash if any requests are non-nil.
260-
var (
261-
requestsHash *common.Hash
262-
requests types.Requests
263-
)
264-
if data.Deposits != nil {
265-
requests = make(types.Requests, 0)
266-
for _, d := range data.Deposits {
267-
requests = append(requests, types.NewRequest(d))
268-
}
269-
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
260+
261+
var requestsHash *common.Hash
262+
if requests != nil {
263+
h := types.CalcRequestsHash(requests)
270264
requestsHash = &h
271265
}
266+
272267
header := &types.Header{
273268
ParentHash: data.ParentHash,
274269
UncleHash: types.EmptyUncleHash,
@@ -292,7 +287,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
292287
RequestsHash: requestsHash,
293288
}
294289
return types.NewBlockWithHeader(header).
295-
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests}).
290+
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
296291
WithWitness(data.ExecutionWitness),
297292
nil
298293
}
@@ -332,30 +327,13 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
332327
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
333328
}
334329
}
335-
setRequests(block.Requests(), data)
336330
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
337331
}
338332

339-
// setRequests differentiates the different request types and
340-
// assigns them to the associated fields in ExecutableData.
341-
func setRequests(requests types.Requests, data *ExecutableData) {
342-
if requests != nil {
343-
// If requests is non-nil, it means deposits are available in block and we
344-
// should return an empty slice instead of nil if there are no deposits.
345-
data.Deposits = make(types.Deposits, 0)
346-
}
347-
for _, r := range requests {
348-
if d, ok := r.Inner().(*types.Deposit); ok {
349-
data.Deposits = append(data.Deposits, d)
350-
}
351-
}
352-
}
353-
354333
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
355334
type ExecutionPayloadBody struct {
356335
TransactionData []hexutil.Bytes `json:"transactions"`
357336
Withdrawals []*types.Withdrawal `json:"withdrawals"`
358-
Deposits types.Deposits `json:"depositRequests"`
359337
}
360338

361339
// Client identifiers to support ClientVersionV1.

cmd/evm/internal/t8ntool/execution.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ type ExecutionResult struct {
6767
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
6868
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
6969
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
70-
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
70+
Requests [][]byte `json:"requests,omitempty"`
7171
}
7272

7373
type ommer struct {
@@ -385,21 +385,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
385385
for _, receipt := range receipts {
386386
allLogs = append(allLogs, receipt.Logs...)
387387
}
388-
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
388+
depositRequests, err := core.ParseDepositLogs(allLogs, chainConfig)
389389
if err != nil {
390390
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
391391
}
392+
requests := [][]byte{depositRequests}
392393
// Calculate the requests root
393-
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
394+
h := types.CalcRequestsHash(requests)
394395
execRs.RequestsHash = &h
395-
// Get the deposits from the requests
396-
deposits := make(types.Deposits, 0)
397-
for _, req := range requests {
398-
if dep, ok := req.Inner().(*types.Deposit); ok {
399-
deposits = append(deposits, dep)
400-
}
401-
}
402-
execRs.DepositRequests = &deposits
396+
execRs.Requests = requests
403397
}
404398
// Re-create statedb instance with new root upon the updated database
405399
// for accessing latest states.

core/block_validator.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,12 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
145145
}
146146
// Validate the parsed requests match the expected header value.
147147
if header.RequestsHash != nil {
148-
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
149-
if depositSha != *header.RequestsHash {
150-
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
148+
reqhash := types.CalcRequestsHash(res.Requests)
149+
if reqhash != *header.RequestsHash {
150+
return fmt.Errorf("invalid requests hash (remote: %x local: %x)", *header.RequestsHash, reqhash)
151151
}
152+
} else if res.Requests != nil {
153+
return fmt.Errorf("block has requests before prague fork")
152154
}
153155
// Validate the state root against the received state root and throw
154156
// an error if they don't match.

core/blockchain_test.go

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

core/chain_makers.go

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

349-
var requests types.Requests
349+
var requests [][]byte
350350
if config.IsPrague(b.header.Number, b.header.Time) {
351+
var blockLogs []*types.Log
351352
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...)
353+
blockLogs = append(blockLogs, r.Logs...)
354+
}
355+
depositRequests, err := ParseDepositLogs(blockLogs, config)
356+
if err != nil {
357+
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
357358
}
359+
requests = append(requests, depositRequests)
360+
}
361+
if requests != nil {
362+
reqHash := types.CalcRequestsHash(requests)
363+
b.header.RequestsHash = &reqHash
358364
}
359365

360-
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
366+
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
361367
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
362368
if err != nil {
363369
panic(err)

core/genesis.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,6 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
449449
}
450450
var (
451451
withdrawals []*types.Withdrawal
452-
requests types.Requests
453452
)
454453
if conf := g.Config; conf != nil {
455454
num := big.NewInt(int64(g.Number))
@@ -473,11 +472,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
473472
}
474473
}
475474
if conf.IsPrague(num, g.Timestamp) {
476-
head.RequestsHash = &types.EmptyRequestsHash
477-
requests = make(types.Requests, 0)
475+
emptyRequests := [][]byte{{0}}
476+
rhash := types.CalcRequestsHash(emptyRequests)
477+
head.RequestsHash = &rhash
478478
}
479479
}
480-
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
480+
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
481481
}
482482

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

0 commit comments

Comments
 (0)