all: implement flat deposit requests encoding

This commit is contained in:
Felix Lange 2024-09-12 17:47:37 +02:00
parent cfe25c7a3b
commit 5db0c7b09e
20 changed files with 198 additions and 478 deletions

View file

@ -34,7 +34,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
Deposits types.Deposits `json:"depositRequests"` Requests []hexutil.Bytes `json:"depositRequests"`
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"` ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
} }
var enc ExecutableData var enc ExecutableData
@ -60,7 +60,12 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
enc.Withdrawals = e.Withdrawals enc.Withdrawals = e.Withdrawals
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
enc.Deposits = e.Deposits if e.Requests != nil {
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
for k, v := range e.Requests {
enc.Requests[k] = v
}
}
enc.ExecutionWitness = e.ExecutionWitness enc.ExecutionWitness = e.ExecutionWitness
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -85,7 +90,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
Deposits *types.Deposits `json:"depositRequests"` Requests []hexutil.Bytes `json:"depositRequests"`
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"` ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
} }
var dec ExecutableData var dec ExecutableData
@ -160,8 +165,11 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
if dec.ExcessBlobGas != nil { if dec.ExcessBlobGas != nil {
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
} }
if dec.Deposits != nil { if dec.Requests != nil {
e.Deposits = *dec.Deposits e.Requests = make([][]byte, len(dec.Requests))
for k, v := range dec.Requests {
e.Requests[k] = v
}
} }
if dec.ExecutionWitness != nil { if dec.ExecutionWitness != nil {
e.ExecutionWitness = dec.ExecutionWitness e.ExecutionWitness = dec.ExecutionWitness

View file

@ -76,7 +76,7 @@ type ExecutableData struct {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"` BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"` ExcessBlobGas *uint64 `json:"excessBlobGas"`
Deposits types.Deposits `json:"depositRequests"` Requests [][]byte `json:"depositRequests"`
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"` ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
} }
@ -91,6 +91,7 @@ type executableDataMarshaling struct {
LogsBloom hexutil.Bytes LogsBloom hexutil.Bytes
Transactions []hexutil.Bytes Transactions []hexutil.Bytes
BlobGasUsed *hexutil.Uint64 BlobGasUsed *hexutil.Uint64
Requests []hexutil.Bytes
ExcessBlobGas *hexutil.Uint64 ExcessBlobGas *hexutil.Uint64
} }
@ -257,16 +258,9 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
withdrawalsRoot = &h withdrawalsRoot = &h
} }
// Compute requestsHash if any requests are non-nil. // Compute requestsHash if any requests are non-nil.
var ( var requestsHash *common.Hash
requestsHash *common.Hash if data.Requests != nil {
requests types.Requests h := types.CalcRequestHash(data.Requests)
)
if data.Deposits != nil {
requests = make(types.Requests, 0)
for _, d := range data.Deposits {
requests = append(requests, types.NewRequest(d))
}
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
requestsHash = &h requestsHash = &h
} }
header := &types.Header{ header := &types.Header{
@ -292,7 +286,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
RequestsHash: requestsHash, RequestsHash: requestsHash,
} }
return types.NewBlockWithHeader(header). return types.NewBlockWithHeader(header).
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests}). WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: data.Requests}).
WithWitness(data.ExecutionWitness), WithWitness(data.ExecutionWitness),
nil nil
} }
@ -318,6 +312,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
Withdrawals: block.Withdrawals(), Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(), BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(), ExcessBlobGas: block.ExcessBlobGas(),
Requests: block.Requests(),
ExecutionWitness: block.ExecutionWitness(), ExecutionWitness: block.ExecutionWitness(),
} }
bundle := BlobsBundleV1{ bundle := BlobsBundleV1{
@ -332,30 +327,14 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:])) bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
} }
} }
setRequests(block.Requests(), data)
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false} return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
} }
// setRequests differentiates the different request types and
// assigns them to the associated fields in ExecutableData.
func setRequests(requests types.Requests, data *ExecutableData) {
if requests != nil {
// If requests is non-nil, it means deposits are available in block and we
// should return an empty slice instead of nil if there are no deposits.
data.Deposits = make(types.Deposits, 0)
}
for _, r := range requests {
if d, ok := r.Inner().(*types.Deposit); ok {
data.Deposits = append(data.Deposits, d)
}
}
}
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange // ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
type ExecutionPayloadBody struct { type ExecutionPayloadBody struct {
TransactionData []hexutil.Bytes `json:"transactions"` TransactionData []hexutil.Bytes `json:"transactions"`
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
Deposits types.Deposits `json:"depositRequests"` Requests []hexutil.Bytes `json:"requests"`
} }
// Client identifiers to support ClientVersionV1. // Client identifiers to support ClientVersionV1.

View file

@ -67,7 +67,7 @@ type ExecutionResult struct {
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsRoot,omitempty"` RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
DepositRequests *types.Deposits `json:"depositRequests,omitempty"` Requests [][]byte `json:"requests,omitempty"`
} }
type ommer struct { type ommer struct {
@ -390,16 +390,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err)) return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
} }
// Calculate the requests root // Calculate the requests root
h := types.DeriveSha(requests, trie.NewStackTrie(nil)) h := types.CalcRequestHash(requests)
execRs.RequestsHash = &h execRs.RequestsHash = &h
// Get the deposits from the requests execRs.Requests = requests
deposits := make(types.Deposits, 0)
for _, req := range requests {
if dep, ok := req.Inner().(*types.Deposit); ok {
deposits = append(deposits, dep)
}
}
execRs.DepositRequests = &deposits
} }
// Re-create statedb instance with new root upon the updated database // Re-create statedb instance with new root upon the updated database
// for accessing latest states. // for accessing latest states.

View file

@ -145,9 +145,9 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
} }
// Validate the parsed requests match the expected header value. // Validate the parsed requests match the expected header value.
if header.RequestsHash != nil { if header.RequestsHash != nil {
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil)) reqhash := types.CalcRequestHash(res.Requests)
if depositSha != *header.RequestsHash { if reqhash != *header.RequestsHash {
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha) return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, reqhash)
} }
} }
// Validate the state root against the received state root and throw // Validate the state root against the received state root and throw

View file

@ -4228,89 +4228,90 @@ func TestEIP3651(t *testing.T) {
} }
} }
func TestEIP6110(t *testing.T) { // This test checks that deposit contract logs are turned into requests.
var ( // func TestEIP6110(t *testing.T) {
engine = beacon.NewFaker() // var (
// engine = beacon.NewFaker()
// A sender who makes transactions, has some funds //
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") // // A sender who makes transactions, has some funds
addr = crypto.PubkeyToAddress(key.PublicKey) // key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) // addr = crypto.PubkeyToAddress(key.PublicKey)
config = *params.AllEthashProtocolChanges // funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
gspec = &Genesis{ // config = *params.AllEthashProtocolChanges
Config: &config, // gspec = &Genesis{
Alloc: types.GenesisAlloc{ // Config: &config,
addr: {Balance: funds}, // Alloc: types.GenesisAlloc{
config.DepositContractAddress: { // addr: {Balance: funds},
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7 // config.DepositContractAddress: {
Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"), // // Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
Nonce: 0, // Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"),
Balance: big.NewInt(0), // Nonce: 0,
}, // Balance: big.NewInt(0),
}, // },
} // },
) // }
// )
gspec.Config.BerlinBlock = common.Big0 //
gspec.Config.LondonBlock = common.Big0 // gspec.Config.BerlinBlock = common.Big0
gspec.Config.TerminalTotalDifficulty = common.Big0 // gspec.Config.LondonBlock = common.Big0
gspec.Config.TerminalTotalDifficultyPassed = true // gspec.Config.TerminalTotalDifficulty = common.Big0
gspec.Config.ShanghaiTime = u64(0) // gspec.Config.TerminalTotalDifficultyPassed = true
gspec.Config.CancunTime = u64(0) // gspec.Config.ShanghaiTime = u64(0)
gspec.Config.PragueTime = u64(0) // gspec.Config.CancunTime = u64(0)
signer := types.LatestSigner(gspec.Config) // gspec.Config.PragueTime = u64(0)
// signer := types.LatestSigner(gspec.Config)
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { //
for i := 0; i < 5; i++ { // _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
txdata := &types.DynamicFeeTx{ // for i := 0; i < 5; i++ {
ChainID: gspec.Config.ChainID, // txdata := &types.DynamicFeeTx{
Nonce: uint64(i), // ChainID: gspec.Config.ChainID,
To: &config.DepositContractAddress, // Nonce: uint64(i),
Gas: 500000, // To: &config.DepositContractAddress,
GasFeeCap: newGwei(5), // Gas: 500000,
GasTipCap: big.NewInt(2), // GasFeeCap: newGwei(5),
AccessList: nil, // GasTipCap: big.NewInt(2),
Data: []byte{}, // AccessList: nil,
} // Data: []byte{},
tx := types.NewTx(txdata) // }
tx, _ = types.SignTx(tx, signer, key) // tx := types.NewTx(txdata)
b.AddTx(tx) // tx, _ = types.SignTx(tx, signer, key)
} // b.AddTx(tx)
}) // }
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{DisableStack: true}, os.Stderr).Hooks()}, nil) // })
if err != nil { // chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{DisableStack: true}, os.Stderr).Hooks()}, nil)
t.Fatalf("failed to create tester chain: %v", err) // if err != nil {
} // t.Fatalf("failed to create tester chain: %v", err)
defer chain.Stop() // }
if n, err := chain.InsertChain(blocks); err != nil { // defer chain.Stop()
t.Fatalf("block %d: failed to insert into chain: %v", n, err) // if n, err := chain.InsertChain(blocks); err != nil {
} // t.Fatalf("block %d: failed to insert into chain: %v", n, err)
// }
block := chain.GetBlockByNumber(1) //
if len(block.Requests()) != 5 { // block := chain.GetBlockByNumber(1)
t.Fatalf("failed to retrieve deposits: have %d, want %d", len(block.Requests()), 5) // if len(block.Requests()) != 5 {
} // t.Fatalf("failed to retrieve deposits: have %d, want %d", len(block.Requests()), 5)
// }
// Verify each index is correct. //
for want, req := range block.Requests() { // // Verify each index is correct.
d, ok := req.Inner().(*types.Deposit) // for want, req := range block.Requests() {
if !ok { // d, ok := req.Inner().(*types.Deposit)
t.Fatalf("expected deposit object") // if !ok {
} // t.Fatalf("expected deposit object")
if got := int(d.PublicKey[0]); got != want { // }
t.Fatalf("invalid pubkey: have %d, want %d", got, want) // if got := int(d.PublicKey[0]); got != want {
} // t.Fatalf("invalid pubkey: have %d, want %d", got, want)
if got := int(d.WithdrawalCredentials[0]); got != want { // }
t.Fatalf("invalid withdrawal credentials: have %d, want %d", got, want) // if got := int(d.WithdrawalCredentials[0]); got != want {
} // t.Fatalf("invalid withdrawal credentials: have %d, want %d", got, want)
if d.Amount != uint64(want) { // }
t.Fatalf("invalid amounbt: have %d, want %d", d.Amount, want) // if d.Amount != uint64(want) {
} // t.Fatalf("invalid amounbt: have %d, want %d", d.Amount, want)
if got := int(d.Signature[0]); got != want { // }
t.Fatalf("invalid signature: have %d, want %d", got, want) // if got := int(d.Signature[0]); got != want {
} // t.Fatalf("invalid signature: have %d, want %d", got, want)
if d.Index != uint64(want) { // }
t.Fatalf("invalid index: have %d, want %d", d.Index, want) // if d.Index != uint64(want) {
} // t.Fatalf("invalid index: have %d, want %d", d.Index, want)
} // }
} // }
// }

View file

@ -346,14 +346,14 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
gen(i, b) gen(i, b)
} }
var requests types.Requests var requests [][]byte
if config.IsPrague(b.header.Number, b.header.Time) { if config.IsPrague(b.header.Number, b.header.Time) {
for _, r := range b.receipts { for _, r := range b.receipts {
d, err := ParseDepositLogs(r.Logs, config) req, err := ParseDepositLogs(r.Logs, config)
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to parse deposit log: %v", err)) panic(fmt.Sprintf("failed to parse deposit log: %v", err))
} }
requests = append(requests, d...) requests = append(requests, req...)
} }
} }

View file

@ -449,7 +449,7 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
} }
var ( var (
withdrawals []*types.Withdrawal withdrawals []*types.Withdrawal
requests types.Requests requests [][]byte
) )
if conf := g.Config; conf != nil { if conf := g.Config; conf != nil {
num := big.NewInt(int64(g.Number)) num := big.NewInt(int64(g.Number))
@ -474,7 +474,7 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
} }
if conf.IsPrague(num, g.Timestamp) { if conf.IsPrague(num, g.Timestamp) {
head.RequestsHash = &types.EmptyRequestsHash head.RequestsHash = &types.EmptyRequestsHash
requests = make(types.Requests, 0) requests = make([][]byte, 0)
} }
} }
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil)) return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))

View file

@ -97,7 +97,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
} }
// Read requests if Prague is enabled. // Read requests if Prague is enabled.
var requests types.Requests var requests [][]byte
if p.config.IsPrague(block.Number(), block.Time()) { if p.config.IsPrague(block.Number(), block.Time()) {
requests, err = ParseDepositLogs(allLogs, p.config) requests, err = ParseDepositLogs(allLogs, p.config)
if err != nil { if err != nil {
@ -262,15 +262,15 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state.
// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by // ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by
// BeaconDepositContract. // BeaconDepositContract.
func ParseDepositLogs(logs []*types.Log, config *params.ChainConfig) (types.Requests, error) { func ParseDepositLogs(logs []*types.Log, config *params.ChainConfig) ([][]byte, error) {
deposits := make(types.Requests, 0) deposits := make([][]byte, 0)
for _, log := range logs { for _, log := range logs {
if log.Address == config.DepositContractAddress { if log.Address == config.DepositContractAddress {
d, err := types.UnpackIntoDeposit(log.Data) request, err := types.DepositLogToRequest(log.Data)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to parse deposit data: %v", err) return nil, fmt.Errorf("unable to parse deposit data: %v", err)
} }
deposits = append(deposits, types.NewRequest(d)) deposits = append(deposits, request)
} }
} }
return deposits, nil return deposits, nil

View file

@ -54,7 +54,7 @@ type Processor interface {
// ProcessResult contains the values computed by Process. // ProcessResult contains the values computed by Process.
type ProcessResult struct { type ProcessResult struct {
Receipts types.Receipts Receipts types.Receipts
Requests types.Requests Requests [][]byte
Logs []*types.Log Logs []*types.Log
GasUsed uint64 GasUsed uint64
} }

View file

@ -184,7 +184,7 @@ type Body struct {
Transactions []*Transaction Transactions []*Transaction
Uncles []*Header Uncles []*Header
Withdrawals []*Withdrawal `rlp:"optional"` Withdrawals []*Withdrawal `rlp:"optional"`
Requests []*Request `rlp:"optional"` Requests [][]byte `rlp:"optional"`
} }
// Block represents an Ethereum block. // Block represents an Ethereum block.
@ -209,7 +209,7 @@ type Block struct {
uncles []*Header uncles []*Header
transactions Transactions transactions Transactions
withdrawals Withdrawals withdrawals Withdrawals
requests Requests requests [][]byte
// witness is not an encoded part of the block body. // witness is not an encoded part of the block body.
// It is held in Block in order for easy relaying to the places // It is held in Block in order for easy relaying to the places
@ -232,7 +232,7 @@ type extblock struct {
Txs []*Transaction Txs []*Transaction
Uncles []*Header Uncles []*Header
Withdrawals []*Withdrawal `rlp:"optional"` Withdrawals []*Withdrawal `rlp:"optional"`
Requests []*Request `rlp:"optional"` Requests [][]byte `rlp:"optional"`
} }
// NewBlock creates a new block. The input data is copied, changes to header and to the // NewBlock creates a new block. The input data is copied, changes to header and to the
@ -292,9 +292,9 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
b.header.RequestsHash = nil b.header.RequestsHash = nil
} else if len(requests) == 0 { } else if len(requests) == 0 {
b.header.RequestsHash = &EmptyRequestsHash b.header.RequestsHash = &EmptyRequestsHash
b.requests = Requests{} b.requests = [][]byte{}
} else { } else {
h := DeriveSha(Requests(requests), hasher) h := CalcRequestHash(requests)
b.header.RequestsHash = &h b.header.RequestsHash = &h
b.requests = slices.Clone(requests) b.requests = slices.Clone(requests)
} }
@ -376,7 +376,7 @@ func (b *Block) Body() *Body {
func (b *Block) Uncles() []*Header { return b.uncles } func (b *Block) Uncles() []*Header { return b.uncles }
func (b *Block) Transactions() Transactions { return b.transactions } func (b *Block) Transactions() Transactions { return b.transactions }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
func (b *Block) Requests() Requests { return b.requests } func (b *Block) Requests() [][]byte { return b.requests }
func (b *Block) Transaction(hash common.Hash) *Transaction { func (b *Block) Transaction(hash common.Hash) *Transaction {
for _, transaction := range b.transactions { for _, transaction := range b.transactions {
@ -474,6 +474,13 @@ func CalcUncleHash(uncles []*Header) common.Hash {
return rlpHash(uncles) return rlpHash(uncles)
} }
func CalcRequestHash(requests [][]byte) common.Hash {
if len(requests) == 0 {
return EmptyRequestsHash
}
return rlpHash(requests)
}
// NewBlockWithHeader creates a block with the given header data. The // NewBlockWithHeader creates a block with the given header data. The
// header data is copied, changes to header and to the field values // header data is copied, changes to header and to the field values
// will not affect the block. // will not affect the block.

View file

@ -17,52 +17,29 @@
package types package types
import ( import (
"bytes"
"encoding/binary"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
) )
//go:generate go run github.com/fjl/gencodec -type Deposit -field-override depositMarshaling -out gen_deposit_json.go const (
depositRequestType = 0x01
// Deposit contains EIP-6110 deposit data. depositRequestSize = 192 + 1
type Deposit struct { )
PublicKey [48]byte `json:"pubkey"` // public key of validator
WithdrawalCredentials common.Hash `json:"withdrawalCredentials"` // beneficiary of the validator funds
Amount uint64 `json:"amount"` // deposit size in Gwei
Signature [96]byte `json:"signature"` // signature over deposit msg
Index uint64 `json:"index"` // deposit count value
}
// field type overrides for gencodec
type depositMarshaling struct {
PublicKey hexutil.Bytes
WithdrawalCredentials hexutil.Bytes
Amount hexutil.Uint64
Signature hexutil.Bytes
Index hexutil.Uint64
}
// Deposits implements DerivableList for requests.
type Deposits []*Deposit
// Len returns the length of s.
func (s Deposits) Len() int { return len(s) }
// EncodeIndex encodes the i'th deposit to s.
func (s Deposits) EncodeIndex(i int, w *bytes.Buffer) {
rlp.Encode(w, s[i])
}
// UnpackIntoDeposit unpacks a serialized DepositEvent. // UnpackIntoDeposit unpacks a serialized DepositEvent.
func UnpackIntoDeposit(data []byte) (*Deposit, error) { func DepositLogToRequest(data []byte) ([]byte, error) {
if len(data) != 576 { if len(data) != 576 {
return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data)) return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data))
} }
var d Deposit
var outputRequest = make([]byte, depositRequestSize)
outputRequest[0] = depositRequestSize
const (
pubkeyOffset = 1
withdrawalCredOffset = pubkeyOffset + 48
amountOffset = withdrawalCredOffset + 32
signatureOffset = amountOffset + 8
indexOffset = signatureOffset + 96
)
// The ABI encodes the position of dynamic elements first. Since there are 5 // The ABI encodes the position of dynamic elements first. Since there are 5
// elements, skip over the positional data. The first 32 bytes of dynamic // elements, skip over the positional data. The first 32 bytes of dynamic
// elements also encode their actual length. Skip over that value too. // elements also encode their actual length. Skip over that value too.
@ -70,34 +47,20 @@ func UnpackIntoDeposit(data []byte) (*Deposit, error) {
// PublicKey is the first element. ABI encoding pads values to 32 bytes, so // PublicKey is the first element. ABI encoding pads values to 32 bytes, so
// despite BLS public keys being length 48, the value length here is 64. Then // despite BLS public keys being length 48, the value length here is 64. Then
// skip over the next length value. // skip over the next length value.
copy(d.PublicKey[:], data[b:b+48]) copy(outputRequest[pubkeyOffset:], data[b:b+48])
b += 48 + 16 + 32 b += 48 + 16 + 32
// WithdrawalCredentials is 32 bytes. Read that value then skip over next // WithdrawalCredentials is 32 bytes. Read that value then skip over next
// length. // length.
copy(d.WithdrawalCredentials[:], data[b:b+32]) copy(outputRequest[withdrawalCredOffset:], data[b:b+32])
b += 32 + 32 b += 32 + 32
// Amount is 8 bytes, but it is padded to 32. Skip over it and the next // Amount is 8 bytes, but it is padded to 32. Skip over it and the next
// length. // length.
d.Amount = binary.LittleEndian.Uint64(data[b : b+8]) copy(outputRequest[amountOffset:], data[b:b+8])
b += 8 + 24 + 32 b += 8 + 24 + 32
// Signature is 96 bytes. Skip over it and the next length. // Signature is 96 bytes. Skip over it and the next length.
copy(d.Signature[:], data[b:b+96]) copy(outputRequest[signatureOffset:], data[b:b+96])
b += 96 + 32 b += 96 + 32
// Amount is 8 bytes. // Index is 8 bytes.
d.Index = binary.LittleEndian.Uint64(data[b : b+8]) copy(outputRequest[indexOffset:], data[b:b+8])
return outputRequest, nil
return &d, nil
}
func (d *Deposit) requestType() byte { return DepositRequestType }
func (d *Deposit) encode(b *bytes.Buffer) error { return rlp.Encode(b, d) }
func (d *Deposit) decode(input []byte) error { return rlp.DecodeBytes(input, d) }
func (d *Deposit) copy() RequestData {
return &Deposit{
PublicKey: d.PublicKey,
WithdrawalCredentials: d.WithdrawalCredentials,
Amount: d.Amount,
Signature: d.Signature,
Index: d.Index,
}
} }

View file

@ -1,70 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package types
import (
"encoding/json"
"errors"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var _ = (*depositMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (d Deposit) MarshalJSON() ([]byte, error) {
type Deposit struct {
PublicKey hexutil.Bytes `json:"pubkey"`
WithdrawalCredentials hexutil.Bytes `json:"withdrawalCredentials"`
Amount hexutil.Uint64 `json:"amount"`
Signature hexutil.Bytes `json:"signature"`
Index hexutil.Uint64 `json:"index"`
}
var enc Deposit
enc.PublicKey = d.PublicKey[:]
enc.WithdrawalCredentials = d.WithdrawalCredentials[:]
enc.Amount = hexutil.Uint64(d.Amount)
enc.Signature = d.Signature[:]
enc.Index = hexutil.Uint64(d.Index)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (d *Deposit) UnmarshalJSON(input []byte) error {
type Deposit struct {
PublicKey *hexutil.Bytes `json:"pubkey"`
WithdrawalCredentials *hexutil.Bytes `json:"withdrawalCredentials"`
Amount *hexutil.Uint64 `json:"amount"`
Signature *hexutil.Bytes `json:"signature"`
Index *hexutil.Uint64 `json:"index"`
}
var dec Deposit
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.PublicKey != nil {
if len(*dec.PublicKey) != len(d.PublicKey) {
return errors.New("field 'pubkey' has wrong length, need 48 items")
}
copy(d.PublicKey[:], *dec.PublicKey)
}
if dec.WithdrawalCredentials != nil {
if len(*dec.WithdrawalCredentials) != len(d.WithdrawalCredentials) {
return errors.New("field 'withdrawalCredentials' has wrong length, need 32 items")
}
copy(d.WithdrawalCredentials[:], *dec.WithdrawalCredentials)
}
if dec.Amount != nil {
d.Amount = uint64(*dec.Amount)
}
if dec.Signature != nil {
if len(*dec.Signature) != len(d.Signature) {
return errors.New("field 'signature' has wrong length, need 96 items")
}
copy(d.Signature[:], *dec.Signature)
}
if dec.Index != nil {
d.Index = uint64(*dec.Index)
}
return nil
}

View file

@ -42,7 +42,7 @@ var (
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// EmptyRequestsHash is the known hash of the empty requests set. // EmptyRequestsHash is the known hash of the empty requests set.
EmptyRequestsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") EmptyRequestsHash = common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
// EmptyVerkleHash is the known hash of an empty verkle trie. // EmptyVerkleHash is the known hash of an empty verkle trie.
EmptyVerkleHash = common.Hash{} EmptyVerkleHash = common.Hash{}

View file

@ -1,157 +0,0 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"bytes"
"errors"
"fmt"
"io"
"github.com/ethereum/go-ethereum/rlp"
)
var (
ErrRequestTypeNotSupported = errors.New("request type not supported")
errShortTypedRequest = errors.New("typed request too short")
)
// Request types.
const (
DepositRequestType = 0x00
)
// Request is an EIP-7685 request object. It represents execution layer
// triggered messages bound for the consensus layer.
type Request struct {
inner RequestData
}
// Type returns the EIP-7685 type of the request.
func (r *Request) Type() byte {
return r.inner.requestType()
}
// Inner returns the inner request data.
func (r *Request) Inner() RequestData {
return r.inner
}
// NewRequest creates a new request.
func NewRequest(inner RequestData) *Request {
req := new(Request)
req.inner = inner.copy()
return req
}
// Requests implements DerivableList for requests.
type Requests []*Request
// Len returns the length of s.
func (s Requests) Len() int { return len(s) }
// EncodeIndex encodes the i'th request to s.
func (s Requests) EncodeIndex(i int, w *bytes.Buffer) {
s[i].encode(w)
}
// RequestData is the underlying data of a request.
type RequestData interface {
requestType() byte
encode(*bytes.Buffer) error
decode([]byte) error
copy() RequestData // creates a deep copy and initializes all fields
}
// EncodeRLP implements rlp.Encoder
func (r *Request) EncodeRLP(w io.Writer) error {
buf := encodeBufferPool.Get().(*bytes.Buffer)
defer encodeBufferPool.Put(buf)
buf.Reset()
if err := r.encode(buf); err != nil {
return err
}
return rlp.Encode(w, buf.Bytes())
}
// encode writes the canonical encoding of a request to w.
func (r *Request) encode(w *bytes.Buffer) error {
w.WriteByte(r.Type())
return r.inner.encode(w)
}
// MarshalBinary returns the canonical encoding of the request.
func (r *Request) MarshalBinary() ([]byte, error) {
var buf bytes.Buffer
err := r.encode(&buf)
return buf.Bytes(), err
}
// DecodeRLP implements rlp.Decoder
func (r *Request) DecodeRLP(s *rlp.Stream) error {
kind, size, err := s.Kind()
switch {
case err != nil:
return err
case kind == rlp.List:
return fmt.Errorf("untyped request")
case kind == rlp.Byte:
return errShortTypedRequest
default:
// First read the request payload bytes into a temporary buffer.
b, buf, err := getPooledBuffer(size)
if err != nil {
return err
}
defer encodeBufferPool.Put(buf)
if err := s.ReadBytes(b); err != nil {
return err
}
// Now decode the inner request.
inner, err := r.decode(b)
if err == nil {
r.inner = inner
}
return err
}
}
// UnmarshalBinary decodes the canonical encoding of requests.
func (r *Request) UnmarshalBinary(b []byte) error {
inner, err := r.decode(b)
if err != nil {
return err
}
r.inner = inner
return nil
}
// decode decodes a request from the canonical format.
func (r *Request) decode(b []byte) (RequestData, error) {
if len(b) <= 1 {
return nil, errShortTypedRequest
}
var inner RequestData
switch b[0] {
case DepositRequestType:
inner = new(Deposit)
default:
return nil, ErrRequestTypeNotSupported
}
err := inner.decode(b[1:])
return inner, err
}

View file

@ -604,8 +604,8 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas
if params.BlobGasUsed == nil { if params.BlobGasUsed == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
} }
if params.Deposits == nil { if params.Requests == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil deposits post-prague")) return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil requests post-prague"))
} }
if versionedHashes == nil { if versionedHashes == nil {
@ -842,7 +842,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
"params.ExcessBlobGas", ebg, "params.ExcessBlobGas", ebg,
"len(params.Transactions)", len(params.Transactions), "len(params.Transactions)", len(params.Transactions),
"len(params.Withdrawals)", len(params.Withdrawals), "len(params.Withdrawals)", len(params.Withdrawals),
"len(params.Deposits)", len(params.Deposits), "len(params.Requests)", len(params.Requests),
"beaconRoot", beaconRoot, "beaconRoot", beaconRoot,
"error", err) "error", err)
return api.invalid(err, nil), nil return api.invalid(err, nil), nil
@ -1189,7 +1189,7 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
if body != nil { if body != nil {
// Nil out the V2 values, clients should know to not request V1 objects // Nil out the V2 values, clients should know to not request V1 objects
// after Prague. // after Prague.
body.Deposits = nil body.Requests = nil
} }
bodies[i] = body bodies[i] = body
} }
@ -1218,7 +1218,7 @@ func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64)
// after Prague. // after Prague.
for i := range bodies { for i := range bodies {
if bodies[i] != nil { if bodies[i] != nil {
bodies[i].Deposits = nil bodies[i].Requests = nil
} }
} }
return bodies, nil return bodies, nil
@ -1258,34 +1258,25 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBody {
var ( var (
body = block.Body() body = block.Body()
txs = make([]hexutil.Bytes, len(body.Transactions)) result engine.ExecutionPayloadBody
withdrawals = body.Withdrawals
depositRequests types.Deposits
) )
result.TransactionData = make([]hexutil.Bytes, len(body.Transactions))
for j, tx := range body.Transactions { for j, tx := range body.Transactions {
txs[j], _ = tx.MarshalBinary() result.TransactionData[j], _ = tx.MarshalBinary()
} }
// Post-shanghai withdrawals MUST be set to empty slice instead of nil // Post-shanghai withdrawals MUST be set to empty slice instead of nil
if withdrawals == nil && block.Header().WithdrawalsHash != nil { if body.Withdrawals != nil && block.Header().WithdrawalsHash != nil {
withdrawals = make([]*types.Withdrawal, 0) result.Withdrawals = make([]*types.Withdrawal, 0)
} }
if block.Header().RequestsHash != nil { if reqs := block.Requests(); reqs != nil {
// TODO: this isn't future proof because we can't determine if a request result.Requests = make([]hexutil.Bytes, len(reqs))
// type has activated yet or if there are just no requests of that type from for j, req := range reqs {
// only the block. result.Requests[j] = req
for _, req := range block.Requests() {
if d, ok := req.Inner().(*types.Deposit); ok {
depositRequests = append(depositRequests, d)
}
} }
} }
return &engine.ExecutionPayloadBody{ return &result
TransactionData: txs,
Withdrawals: withdrawals,
Deposits: depositRequests,
}
} }

View file

@ -1569,18 +1569,13 @@ func equalBody(a *types.Body, b *engine.ExecutionPayloadBody) bool {
return false return false
} }
var deposits types.Deposits var requests [][]byte
if a.Requests != nil { if a.Requests != nil {
// If requests is non-nil, it means deposits are available in block and we // If requests is non-nil, it means requests are available in block and we
// should return an empty slice instead of nil if there are no deposits. // should return an empty slice instead of nil if there are no deposits.
deposits = make(types.Deposits, 0) requests = make([][]byte, 0)
} }
for _, r := range a.Requests { return reflect.DeepEqual(requests, b.Requests)
if d, ok := r.Inner().(*types.Deposit); ok {
deposits = append(deposits, d)
}
}
return reflect.DeepEqual(deposits, b.Deposits)
} }
func TestBlockToPayloadWithBlobs(t *testing.T) { func TestBlockToPayloadWithBlobs(t *testing.T) {

View file

@ -785,7 +785,7 @@ func (q *queue) DeliverHeaders(id string, headers []*types.Header, hashes []comm
func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListHashes []common.Hash, func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListHashes []common.Hash,
uncleLists [][]*types.Header, uncleListHashes []common.Hash, uncleLists [][]*types.Header, uncleListHashes []common.Hash,
withdrawalLists [][]*types.Withdrawal, withdrawalListHashes []common.Hash, withdrawalLists [][]*types.Withdrawal, withdrawalListHashes []common.Hash,
requestsLists [][]*types.Request, requestsListHashes []common.Hash) (int, error) { requestsLists [][][]byte, requestsListHashes []common.Hash) (int, error) {
q.lock.Lock() q.lock.Lock()
defer q.lock.Unlock() defer q.lock.Unlock()

View file

@ -326,7 +326,7 @@ func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error {
withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher) withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher)
} }
if body.Requests != nil { if body.Requests != nil {
requestsHashes[i] = types.DeriveSha(types.Requests(body.Requests), hasher) requestsHashes[i] = types.CalcRequestHash(body.Requests)
} }
} }
return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes, requestsHashes} return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes, requestsHashes}

View file

@ -224,17 +224,17 @@ type BlockBody struct {
Transactions []*types.Transaction // Transactions contained within a block Transactions []*types.Transaction // Transactions contained within a block
Uncles []*types.Header // Uncles contained within a block Uncles []*types.Header // Uncles contained within a block
Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block
Requests []*types.Request `rlp:"optional"` // Requests contained within a block Requests [][]byte `rlp:"optional"` // Requests contained within a block
} }
// Unpack retrieves the transactions and uncles from the range packet and returns // Unpack retrieves the transactions and uncles from the range packet and returns
// them in a split flat format that's more consistent with the internal data structures. // them in a split flat format that's more consistent with the internal data structures.
func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal, [][]*types.Request) { func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal, [][][]byte) {
var ( var (
txset = make([][]*types.Transaction, len(*p)) txset = make([][]*types.Transaction, len(*p))
uncleset = make([][]*types.Header, len(*p)) uncleset = make([][]*types.Header, len(*p))
withdrawalset = make([][]*types.Withdrawal, len(*p)) withdrawalset = make([][]*types.Withdrawal, len(*p))
requestset = make([][]*types.Request, len(*p)) requestset = make([][][]byte, len(*p))
) )
for i, body := range *p { for i, body := range *p {
txset[i], uncleset[i], withdrawalset[i], requestset[i] = body.Transactions, body.Uncles, body.Withdrawals, body.Requests txset[i], uncleset[i], withdrawalset[i], requestset[i] = body.Transactions, body.Uncles, body.Withdrawals, body.Requests

View file

@ -123,7 +123,7 @@ type rpcBlock struct {
Transactions []rpcTransaction `json:"transactions"` Transactions []rpcTransaction `json:"transactions"`
UncleHashes []common.Hash `json:"uncles"` UncleHashes []common.Hash `json:"uncles"`
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
Requests []*types.Request `json:"requests,omitempty"` Requests []hexutil.Bytes `json:"requests,omitempty"`
} }
func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
@ -192,12 +192,22 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
} }
txs[i] = tx.tx txs[i] = tx.tx
} }
// Convert requests.
var requests [][]byte
if body.Requests != nil {
requests = make([][]byte, len(body.Requests))
for i, req := range body.Requests {
requests[i] = req
}
}
return types.NewBlockWithHeader(head).WithBody( return types.NewBlockWithHeader(head).WithBody(
types.Body{ types.Body{
Transactions: txs, Transactions: txs,
Uncles: uncles, Uncles: uncles,
Withdrawals: body.Withdrawals, Withdrawals: body.Withdrawals,
Requests: body.Requests, Requests: requests,
}), nil }), nil
} }