From 0a1beaa39e8ff5e85ca61a07796c55344de07f00 Mon Sep 17 00:00:00 2001 From: racytech Date: Wed, 1 May 2024 22:58:52 +0500 Subject: [PATCH 1/7] rlp: request and deposit --- core/types/block.go | 40 +++++++++++++++++++ core/types/deposit.go | 49 +++++++++++++++++++++++ core/types/encdec_test.go | 60 +++++++++++++++++++++++----- core/types/request.go | 84 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 11 deletions(-) create mode 100644 core/types/deposit.go create mode 100644 core/types/request.go diff --git a/core/types/block.go b/core/types/block.go index f35ef67901f..15c2f5e9c9e 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -105,6 +105,8 @@ type Header struct { ParentBeaconBlockRoot *libcommon.Hash `json:"parentBeaconBlockRoot"` // EIP-4788 + RequestsRoot *libcommon.Hash `json:"requestsRoot"` // EIP-7685 + // The verkle proof is ignored in legacy headers Verkle bool VerkleProof []byte @@ -161,6 +163,10 @@ func (h *Header) EncodingSize() int { encodingSize += 33 } + if h.RequestsRoot != nil { + encodingSize += 33 + } + if h.Verkle { // Encoding of Verkle Proof encodingSize += rlp2.StringLen(h.VerkleProof) @@ -310,6 +316,16 @@ func (h *Header) EncodeRLP(w io.Writer) error { } } + if h.RequestsRoot != nil { + b[0] = 128 + 32 + if _, err := w.Write(b[:1]); err != nil { + return err + } + if _, err := w.Write(h.RequestsRoot.Bytes()); err != nil { + return err + } + } + if h.Verkle { if err := rlp.EncodeString(h.VerkleProof, w, b[:]); err != nil { return err @@ -498,6 +514,23 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error { h.ParentBeaconBlockRoot = new(libcommon.Hash) h.ParentBeaconBlockRoot.SetBytes(b) + // RequestsRoot + if b, err = s.Bytes(); err != nil { + if errors.Is(err, rlp.EOL) { + h.RequestsRoot = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no RequestsRoot): %w", err) + } + return nil + } + return fmt.Errorf("read RequestsRoot: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for RequestsRoot: %d", len(b)) + } + h.RequestsRoot = new(libcommon.Hash) + h.RequestsRoot.SetBytes(b) + if h.Verkle { if h.VerkleProof, err = s.Bytes(); err != nil { return fmt.Errorf("read VerkleProof: %w", err) @@ -557,6 +590,9 @@ func (h *Header) Size() common.StorageSize { if h.ParentBeaconBlockRoot != nil { s += common.StorageSize(32) } + if h.RequestsRoot != nil { + s += common.StorageSize(32) + } return s } @@ -591,6 +627,7 @@ type Body struct { Transactions []Transaction Uncles []*Header Withdrawals []*Withdrawal + Requests []*Request } // RawBody is semi-parsed variant of Body, where transactions are still unparsed RLP strings @@ -600,6 +637,7 @@ type RawBody struct { Transactions [][]byte Uncles []*Header Withdrawals []*Withdrawal + Requests []*Request } type BodyForStorage struct { @@ -607,6 +645,7 @@ type BodyForStorage struct { TxAmount uint32 Uncles []*Header Withdrawals []*Withdrawal + Requests []*Request } // Alternative representation of the Block. @@ -638,6 +677,7 @@ type Block struct { uncles []*Header transactions Transactions withdrawals []*Withdrawal + requests []*Request // caches hash atomic.Value diff --git a/core/types/deposit.go b/core/types/deposit.go new file mode 100644 index 00000000000..d2ea14b75c0 --- /dev/null +++ b/core/types/deposit.go @@ -0,0 +1,49 @@ +package types + +import ( + "bytes" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/accounts/abi" + "github.com/ledgerwatch/erigon/rlp" +) + +const ( + pLen = 48 // pubkey size + wLen = 32 // withdrawalCredentials size + sLen = 96 // signature size +) + +var ( + // DepositABI is an ABI instance of beacon chain deposit events. + DepositABI = abi.ABI{Events: map[string]abi.Event{"DepositEvent": depositEvent}} + bytesT, _ = abi.NewType("bytes", "", nil) + depositEvent = abi.NewEvent("DepositEvent", "DepositEvent", false, abi.Arguments{ + {Name: "pubkey", Type: bytesT, Indexed: false}, + {Name: "withdrawal_credentials", Type: bytesT, Indexed: false}, + {Name: "amount", Type: bytesT, Indexed: false}, + {Name: "signature", Type: bytesT, Indexed: false}, + {Name: "index", Type: bytesT, Indexed: false}}, + ) +) + +type Deposit struct { + Pubkey [pLen]byte + WithdrawalCredentials libcommon.Hash + Amount uint64 + Signature [sLen]byte + Index uint64 +} + +func (d *Deposit) requestType() byte { return DepositRequestType } +func (d *Deposit) encodeRLP(w *bytes.Buffer) error { return rlp.Encode(w, d) } +func (d *Deposit) decodeRLP(data []byte) error { return rlp.DecodeBytes(data, d) } +func (d *Deposit) copy() RequestData { + return &Deposit{ + Pubkey: d.Pubkey, + WithdrawalCredentials: d.WithdrawalCredentials, + Amount: d.Amount, + Signature: d.Signature, + Index: d.Index, + } +} diff --git a/core/types/encdec_test.go b/core/types/encdec_test.go index 97951782588..a79ce41ca32 100644 --- a/core/types/encdec_test.go +++ b/core/types/encdec_test.go @@ -15,7 +15,7 @@ import ( "github.com/ledgerwatch/erigon/rlp" ) -const RUNS = 100 // for local tests increase this number +const RUNS = 1000000 // for local tests increase this number type TRand struct { rnd *rand.Rand @@ -69,6 +69,23 @@ func (tr *TRand) RandWithdrawal() *Withdrawal { } } +func (tr *TRand) RandDeposit() *Deposit { + return &Deposit{ + Pubkey: [48]byte(tr.RandBytes(48)), + WithdrawalCredentials: tr.RandHash(), + Amount: *tr.RandUint64(), + Signature: [96]byte(tr.RandBytes(96)), + Index: *tr.RandUint64(), + } +} + +func (tr *TRand) RandRequest() *Request { + d := tr.RandDeposit() + var r Request + r.inner = d.copy() + return &r +} + func (tr *TRand) RandHeader() *Header { wHash := tr.RandHash() pHash := tr.RandHash() @@ -210,6 +227,7 @@ func (tr *TRand) RandWithdrawals(size int) []*Withdrawal { } return withdrawals } + func (tr *TRand) RandRawBody() *RawBody { return &RawBody{ Transactions: tr.RandRawTransactions(tr.RandIntInRange(1, 6)), @@ -254,9 +272,9 @@ func isEqualBytes(a, b []byte) bool { return true } -func check(t *testing.T, f string, got, want interface{}) { - if !reflect.DeepEqual(got, want) { - t.Errorf("%s mismatch: got %v, want %v", f, got, want) +func check(t *testing.T, f string, want, got interface{}) { + if !reflect.DeepEqual(want, got) { + t.Errorf("%s mismatch: want %v, got %v", f, want, got) } } @@ -311,13 +329,13 @@ func compareTransactions(t *testing.T, a, b Transaction) { check(t, "Tx.S", s1, s2) } -// func compareDeposits(t *testing.T, a, b *Deposit) { -// check(t, "Deposit.Pubkey", a.Index, b.Index) -// check(t, "Deposit.WithdrawalCredentials", a.WithdrawalCredentials, b.WithdrawalCredentials) -// check(t, "Deposit.Amount", a.Amount, b.Amount) -// check(t, "Deposit.Signature", a.Signature, b.Signature) -// check(t, "Deposit.Index", a.Index, b.Index) -// } +func compareDeposits(t *testing.T, a, b *Deposit) { + check(t, "Deposit.Pubkey", a.Index, b.Index) + check(t, "Deposit.WithdrawalCredentials", a.WithdrawalCredentials, b.WithdrawalCredentials) + check(t, "Deposit.Amount", a.Amount, b.Amount) + check(t, "Deposit.Signature", a.Signature, b.Signature) + check(t, "Deposit.Index", a.Index, b.Index) +} func compareRawBodies(t *testing.T, a, b *RawBody) error { @@ -440,3 +458,23 @@ func TestBodyEncodeDecodeRLP(t *testing.T) { } } } + +func TestDepositEncodeDecode(t *testing.T) { + tr := NewTRand() + var buf bytes.Buffer + for i := 0; i < RUNS; i++ { + enc := tr.RandRequest() + buf.Reset() + if err := enc.EncodeRLP(&buf); err != nil { + t.Errorf("error: deposit.EncodeRLP(): %v", err) + } + s := rlp.NewStream(bytes.NewReader(buf.Bytes()), 0) + dec := &Request{} + if err := dec.DecodeRLP(s); err != nil { + t.Errorf("error: Deposit.DecodeRLP(): %v", err) + } + a := enc.inner.(*Deposit) + b := dec.inner.(*Deposit) + compareDeposits(t, a, b) + } +} diff --git a/core/types/request.go b/core/types/request.go new file mode 100644 index 00000000000..67cd6503264 --- /dev/null +++ b/core/types/request.go @@ -0,0 +1,84 @@ +package types + +import ( + "bytes" + "fmt" + "io" + + "github.com/ledgerwatch/erigon/rlp" +) + +const ( + DepositRequestType byte = 0x00 +) + +type Request struct { + inner RequestData +} + +func (r *Request) Type() byte { + return r.inner.requestType() +} + +func (r *Request) EncodeRLP(w io.Writer) error { + var buf bytes.Buffer // TODO(racytech): find a solution to reuse the same buffer instead of recreating it + buf.WriteByte(r.Type()) // first write type of request then encode inner data + r.inner.encodeRLP(&buf) + return rlp.Encode(w, buf.Bytes()) +} + +func (r *Request) DecodeRLP(s *rlp.Stream) error { + kind, _, err := s.Kind() + switch { + case err != nil: + return err + case kind == rlp.List: + return fmt.Errorf("error: untyped request (unexpected lit)") + case kind == rlp.Byte: + return fmt.Errorf("error: too short request") + default: + var buf []byte + if buf, err = s.Bytes(); err != nil { + return err + } + + return r.decode(buf) + } +} + +func (r *Request) decode(data []byte) error { + if len(data) <= 1 { + return fmt.Errorf("error: too short type request") + } + var inner RequestData + switch data[0] { + case DepositRequestType: + inner = new(Deposit) + default: + return fmt.Errorf("unknown request type - %d", data[0]) + } + + if err := inner.decodeRLP(data[1:]); err != nil { + return err + } + r.inner = inner + return nil +} + +type Requests []*Request + +func (r Requests) Len() int { return len(r) } + +// EncodeIndex encodes the i'th request to w. Note that this does not check for errors +// because we assume that *request will only ever contain valid requests that were either +// constructed by decoding or via public API in this package. +func (r Requests) EncodeIndex(i int, w *bytes.Buffer) { + rlp.Encode(w, r[i]) +} + +type RequestData interface { + encodeRLP(*bytes.Buffer) error + decodeRLP([]byte) error + requestType() byte + copy() RequestData +} From ba7f147e899c40d3b2c7a0711786b4e3300a042f Mon Sep 17 00:00:00 2001 From: racytech Date: Wed, 1 May 2024 23:50:59 +0500 Subject: [PATCH 2/7] add deposit_requests into exectuion payload --- core/types/deposit.go | 9 +++++++ core/types/encdec_test.go | 2 +- core/types/request.go | 6 +++++ turbo/engineapi/engine_server.go | 10 +++++++ turbo/engineapi/engine_types/jsonrpc.go | 35 +++++++++++++------------ 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/core/types/deposit.go b/core/types/deposit.go index d2ea14b75c0..3521cf6daf0 100644 --- a/core/types/deposit.go +++ b/core/types/deposit.go @@ -47,3 +47,12 @@ func (d *Deposit) copy() RequestData { Index: d.Index, } } + +type Deposits []*Deposit + +func (ds Deposits) ToRequests() (reqs Requests) { + for _, d := range ds { + reqs = append(reqs, NewRequest(d)) + } + return +} diff --git a/core/types/encdec_test.go b/core/types/encdec_test.go index a79ce41ca32..1fa59917a06 100644 --- a/core/types/encdec_test.go +++ b/core/types/encdec_test.go @@ -15,7 +15,7 @@ import ( "github.com/ledgerwatch/erigon/rlp" ) -const RUNS = 1000000 // for local tests increase this number +const RUNS = 10 // for local tests increase this number type TRand struct { rnd *rand.Rand diff --git a/core/types/request.go b/core/types/request.go index 67cd6503264..0e10c8c644d 100644 --- a/core/types/request.go +++ b/core/types/request.go @@ -20,6 +20,12 @@ func (r *Request) Type() byte { return r.inner.requestType() } +func NewRequest(inner RequestData) *Request { + req := new(Request) + req.inner = inner.copy() + return req +} + func (r *Request) EncodeRLP(w io.Writer) error { var buf bytes.Buffer // TODO(racytech): find a solution to reuse the same buffer instead of recreating it buf.WriteByte(r.Type()) // first write type of request then encode inner data diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go index 838fb7842b0..529a3bd302d 100644 --- a/turbo/engineapi/engine_server.go +++ b/turbo/engineapi/engine_server.go @@ -160,6 +160,16 @@ func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.Executi header.WithdrawalsHash = &wh } + var requests types.Requests + if version >= clparams.CapellaVersion && req.DepositRequests != nil { + requests = req.DepositRequests.ToRequests() + } + + if requests != nil { + rh := types.DeriveSha(requests) + header.RequestsRoot = &rh + } + if err := s.checkWithdrawalsPresence(header.Time, withdrawals); err != nil { return nil, err } diff --git a/turbo/engineapi/engine_types/jsonrpc.go b/turbo/engineapi/engine_types/jsonrpc.go index 3e3bbde23e8..009f7ec0923 100644 --- a/turbo/engineapi/engine_types/jsonrpc.go +++ b/turbo/engineapi/engine_types/jsonrpc.go @@ -17,23 +17,24 @@ import ( // ExecutionPayload represents an execution payload (aka block) type ExecutionPayload struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom hexutility.Bytes `json:"logsBloom" gencodec:"required"` - PrevRandao common.Hash `json:"prevRandao" gencodec:"required"` - BlockNumber hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData hexutility.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutility.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom hexutility.Bytes `json:"logsBloom" gencodec:"required"` + PrevRandao common.Hash `json:"prevRandao" gencodec:"required"` + BlockNumber hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData hexutility.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutility.Bytes `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + DepositRequests types.Deposits `json:"depositRequests"` // do not forget to add it into erigon-lib/gointerfaces/types if needed } // PayloadAttributes represent the attributes required to start assembling a payload From 9de63ddd2ac22b6b2a51d24cd1e3f7eec7136763 Mon Sep 17 00:00:00 2001 From: racytech Date: Thu, 2 May 2024 01:11:17 +0500 Subject: [PATCH 3/7] add parse deposits from logs --- core/blockchain.go | 14 ++++++++++++++ core/types/deposit.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/core/blockchain.go b/core/blockchain.go index 8dcc0c2f966..924cc9bc7d6 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -105,6 +105,7 @@ func ExecuteBlockEphemerally( includedTxs := make(types.Transactions, 0, block.Transactions().Len()) receipts := make(types.Receipts, 0, block.Transactions().Len()) noop := state.NewNoopWriter() + var allLogs types.Logs for i, tx := range block.Transactions() { ibs.SetTxContext(tx.Hash(), block.Hash(), i) writeTrace := false @@ -135,6 +136,7 @@ func ExecuteBlockEphemerally( receipts = append(receipts, receipt) } } + allLogs = append(allLogs, receipt.Logs...) } receiptSha := types.DeriveSha(receipts) @@ -201,6 +203,18 @@ func ExecuteBlockEphemerally( execRs.StateSyncReceipt = stateSyncReceipt } + if chainConfig.IsPrague(block.Time()) { + requests, err := types.ParseDepositLogs(allLogs, chainConfig.DepositContract) + if err != nil { + return nil, fmt.Errorf("error: could not parse requests logs: %v", err) + } + + rh := types.DeriveSha(requests) + if *block.Header().RequestsRoot != rh { + // TODO(racytech): do we have to check it here? + } + } + return execRs, nil } diff --git a/core/types/deposit.go b/core/types/deposit.go index 3521cf6daf0..3cd8f86e883 100644 --- a/core/types/deposit.go +++ b/core/types/deposit.go @@ -2,6 +2,8 @@ package types import ( "bytes" + "encoding/binary" + "fmt" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/accounts/abi" @@ -48,6 +50,47 @@ func (d *Deposit) copy() RequestData { } } +// field type overrides for abi upacking +type depositUnpacking struct { + Pubkey []byte + WithdrawalCredentials []byte + Amount []byte + Signature []byte + Index []byte +} + +// unpackIntoDeposit unpacks a serialized DepositEvent. +func unpackIntoDeposit(data []byte) (*Deposit, error) { + var du depositUnpacking + if err := DepositABI.UnpackIntoInterface(&du, "DepositEvent", data); err != nil { + return nil, err + } + var d Deposit + copy(d.Pubkey[:], du.Pubkey) + copy(d.WithdrawalCredentials[:], du.WithdrawalCredentials) + d.Amount = binary.LittleEndian.Uint64(du.Amount) + copy(d.Signature[:], du.Signature) + d.Index = binary.LittleEndian.Uint64(du.Index) + + return &d, nil +} + +// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by +// BeaconDepositContract. +func ParseDepositLogs(logs []*Log, depositContractAddress *libcommon.Address) (Requests, error) { + var deposits Requests + for _, log := range logs { + if log.Address == *depositContractAddress { + d, err := unpackIntoDeposit(log.Data) + if err != nil { + return nil, fmt.Errorf("unable to parse deposit data: %v", err) + } + deposits = append(deposits, NewRequest(d)) + } + } + return deposits, nil +} + type Deposits []*Deposit func (ds Deposits) ToRequests() (reqs Requests) { From e4a854620232f024dfcc7440634e77502c5f6685 Mon Sep 17 00:00:00 2001 From: racytech Date: Fri, 3 May 2024 00:58:11 +0500 Subject: [PATCH 4/7] add requests to body --- core/types/block.go | 117 ++++++++++++++++++++++++++++++++------ core/types/deposit.go | 20 +++++-- core/types/encdec_test.go | 108 +++++++++++++++++++++-------------- core/types/request.go | 26 ++++++--- 4 files changed, 201 insertions(+), 70 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 15c2f5e9c9e..71f47a4474c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -706,11 +706,11 @@ func (b *Body) SendersFromTxs() []libcommon.Address { } func (rb RawBody) EncodingSize() int { - payloadSize, _, _, _ := rb.payloadSize() + payloadSize, _, _, _, _ := rb.payloadSize() return payloadSize } -func (rb RawBody) payloadSize() (payloadSize, txsLen, unclesLen, withdrawalsLen int) { +func (rb RawBody) payloadSize() (payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen int) { // size of Transactions for _, tx := range rb.Transactions { txsLen += len(tx) @@ -727,11 +727,17 @@ func (rb RawBody) payloadSize() (payloadSize, txsLen, unclesLen, withdrawalsLen payloadSize += rlp2.ListPrefixLen(withdrawalsLen) + withdrawalsLen } - return payloadSize, txsLen, unclesLen, withdrawalsLen + // size of requests + if rb.Requests != nil { + requestsLen += encodingSizeGeneric(rb.Requests) + payloadSize += rlp2.ListPrefixLen(requestsLen) + requestsLen + } + + return payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen } func (rb RawBody) EncodeRLP(w io.Writer) error { - payloadSize, txsLen, unclesLen, withdrawalsLen := rb.payloadSize() + payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen := rb.payloadSize() var b [33]byte // prefix if err := EncodeStructSizePrefix(payloadSize, w, b[:]); err != nil { @@ -756,6 +762,12 @@ func (rb RawBody) EncodeRLP(w io.Writer) error { return err } } + // encode Requests + if rb.Requests != nil { + if err := encodeRLPGeneric(rb.Requests, requestsLen, w, b[:]); err != nil { + return err + } + } return nil } @@ -791,11 +803,16 @@ func (rb *RawBody) DecodeRLP(s *rlp.Stream) error { if err := decodeWithdrawals(&rb.Withdrawals, s); err != nil { return err } + // decode Requests + rb.Requests = []*Request{} + if err := decodeRequests(&rb.Requests, s); err != nil { + return err + } return s.ListEnd() } -func (bfs BodyForStorage) payloadSize() (payloadSize, unclesLen, withdrawalsLen int) { +func (bfs BodyForStorage) payloadSize() (payloadSize, unclesLen, withdrawalsLen, requestsLen int) { baseTxIdLen := 1 + rlp.IntLenExcludingHead(bfs.BaseTxId) txAmountLen := 1 + rlp.IntLenExcludingHead(uint64(bfs.TxAmount)) @@ -812,11 +829,17 @@ func (bfs BodyForStorage) payloadSize() (payloadSize, unclesLen, withdrawalsLen payloadSize += rlp2.ListPrefixLen(withdrawalsLen) + withdrawalsLen } - return payloadSize, unclesLen, withdrawalsLen + // size of Requests + if bfs.Requests != nil { + requestsLen += encodingSizeGeneric(bfs.Requests) + payloadSize += rlp2.ListPrefixLen(requestsLen) + requestsLen + } + + return payloadSize, unclesLen, withdrawalsLen, requestsLen } func (bfs BodyForStorage) EncodeRLP(w io.Writer) error { - payloadSize, unclesLen, withdrawalsLen := bfs.payloadSize() + payloadSize, unclesLen, withdrawalsLen, requestsLen := bfs.payloadSize() var b [33]byte // prefix @@ -845,6 +868,12 @@ func (bfs BodyForStorage) EncodeRLP(w io.Writer) error { return err } } + // encode Requests + if bfs.Requests != nil { + if err := encodeRLPGeneric(bfs.Requests, requestsLen, w, b[:]); err != nil { + return err + } + } return nil } @@ -871,16 +900,20 @@ func (bfs *BodyForStorage) DecodeRLP(s *rlp.Stream) error { if err := decodeWithdrawals(&bfs.Withdrawals, s); err != nil { return err } - + // decode Requests + bfs.Requests = []*Request{} + if err := decodeRequests(&bfs.Requests, s); err != nil { + return err + } return s.ListEnd() } func (bb Body) EncodingSize() int { - payloadSize, _, _, _ := bb.payloadSize() + payloadSize, _, _, _, _ := bb.payloadSize() return payloadSize } -func (bb Body) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLen int) { +func (bb Body) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLen, requestsLen int) { // size of Transactions txsLen += encodingSizeGeneric(bb.Transactions) payloadSize += rlp2.ListPrefixLen(txsLen) + txsLen @@ -895,11 +928,17 @@ func (bb Body) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLen payloadSize += rlp2.ListPrefixLen(withdrawalsLen) + withdrawalsLen } - return payloadSize, txsLen, unclesLen, withdrawalsLen + // size of Requests + if bb.Requests != nil { + requestsLen += encodingSizeGeneric(bb.Requests) + payloadSize += rlp2.ListPrefixLen(requestsLen) + requestsLen + } + + return payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen } func (bb Body) EncodeRLP(w io.Writer) error { - payloadSize, txsLen, unclesLen, withdrawalsLen := bb.payloadSize() + payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen := bb.payloadSize() var b [33]byte // prefix if err := EncodeStructSizePrefix(payloadSize, w, b[:]); err != nil { @@ -919,6 +958,12 @@ func (bb Body) EncodeRLP(w io.Writer) error { return err } } + // encode Requests + if bb.Requests != nil { + if err := encodeRLPGeneric(bb.Requests, requestsLen, w, b[:]); err != nil { + return err + } + } return nil } @@ -940,6 +985,10 @@ func (bb *Body) DecodeRLP(s *rlp.Stream) error { if err := decodeWithdrawals(&bb.Withdrawals, s); err != nil { return err } + // decode Requests + if err := decodeRequests(&bb.Requests, s); err != nil { + return err + } return s.ListEnd() } @@ -1095,11 +1144,16 @@ func (bb *Block) DecodeRLP(s *rlp.Stream) error { if err := decodeWithdrawals(&bb.withdrawals, s); err != nil { return err } + // decode Requests + bb.requests = []*Request{} + if err := decodeRequests(&bb.requests, s); err != nil { + return err + } return s.ListEnd() } -func (bb Block) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLen int) { +func (bb Block) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLen, requestsLen int) { // size of Header headerLen := bb.header.EncodingSize() payloadSize += rlp2.ListPrefixLen(headerLen) + headerLen @@ -1118,17 +1172,23 @@ func (bb Block) payloadSize() (payloadSize int, txsLen, unclesLen, withdrawalsLe payloadSize += rlp2.ListPrefixLen(withdrawalsLen) + withdrawalsLen } - return payloadSize, txsLen, unclesLen, withdrawalsLen + // size of Requests + if bb.requests != nil { + requestsLen += encodingSizeGeneric(bb.requests) + payloadSize += rlp2.ListPrefixLen(requestsLen) + requestsLen + } + + return payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen } func (bb Block) EncodingSize() int { - payloadSize, _, _, _ := bb.payloadSize() + payloadSize, _, _, _, _ := bb.payloadSize() return payloadSize } // EncodeRLP serializes b into the Ethereum RLP block format. func (bb Block) EncodeRLP(w io.Writer) error { - payloadSize, txsLen, unclesLen, withdrawalsLen := bb.payloadSize() + payloadSize, txsLen, unclesLen, withdrawalsLen, requestsLen := bb.payloadSize() var b [33]byte // prefix if err := EncodeStructSizePrefix(payloadSize, w, b[:]); err != nil { @@ -1152,6 +1212,12 @@ func (bb Block) EncodeRLP(w io.Writer) error { return err } } + // encode Requests + if bb.requests != nil { + if err := encodeRLPGeneric(bb.requests, requestsLen, w, b[:]); err != nil { + return err + } + } return nil } @@ -1486,6 +1552,25 @@ func decodeWithdrawals(appendList *[]*Withdrawal, s *rlp.Stream) error { return checkErrListEnd(s, err) } +func decodeRequests(appendList *[]*Request, s *rlp.Stream) error { + var err error + if _, err = s.List(); err != nil { + if errors.Is(err, rlp.EOL) { + *appendList = nil + return nil + } + return fmt.Errorf("read requests: %v", err) + } + for err == nil { + var r Request + if err = r.DecodeRLP(s); err != nil { + break + } + *appendList = append(*appendList, &r) + } + return checkErrListEnd(s, err) +} + func checkErrListEnd(s *rlp.Stream, err error) error { if !errors.Is(err, rlp.EOL) { return err diff --git a/core/types/deposit.go b/core/types/deposit.go index 3cd8f86e883..00b25a66080 100644 --- a/core/types/deposit.go +++ b/core/types/deposit.go @@ -30,11 +30,11 @@ var ( ) type Deposit struct { - Pubkey [pLen]byte - WithdrawalCredentials libcommon.Hash - Amount uint64 - Signature [sLen]byte - Index uint64 + Pubkey [pLen]byte `json:"pubkey"` // public key of validator + WithdrawalCredentials libcommon.Hash `json:"withdrawalCredentials"` // beneficiary of the validator + Amount uint64 `json:"amount"` // deposit size in Gwei + Signature [sLen]byte `json:"signature"` // signature over deposit msg + Index uint64 `json:"index"` // deposit count value } func (d *Deposit) requestType() byte { return DepositRequestType } @@ -50,6 +50,16 @@ func (d *Deposit) copy() RequestData { } } +func (d *Deposit) encodingSize() (encodingSize int) { + encodingSize++ + encodingSize += rlp.IntLenExcludingHead(d.Amount) + encodingSize++ + encodingSize += rlp.IntLenExcludingHead(d.Index) + + encodingSize += 180 // 1 + 48 + 1 + 32 + 1 + 1 + 96 (0x80 + pLen, 0x80 + wLen, 0xb8 + 2 + sLen) + return encodingSize +} + // field type overrides for abi upacking type depositUnpacking struct { Pubkey []byte diff --git a/core/types/encdec_test.go b/core/types/encdec_test.go index 1fa59917a06..09fb401fb20 100644 --- a/core/types/encdec_test.go +++ b/core/types/encdec_test.go @@ -228,11 +228,20 @@ func (tr *TRand) RandWithdrawals(size int) []*Withdrawal { return withdrawals } +func (tr *TRand) RandRequests(size int) []*Request { + requests := make([]*Request, size) + for i := 0; i < size; i++ { + requests[i] = tr.RandRequest() + } + return requests +} + func (tr *TRand) RandRawBody() *RawBody { return &RawBody{ - Transactions: tr.RandRawTransactions(tr.RandIntInRange(1, 6)), - Uncles: tr.RandHeaders(tr.RandIntInRange(1, 6)), - Withdrawals: tr.RandWithdrawals(tr.RandIntInRange(1, 6)), + // Transactions: tr.RandRawTransactions(tr.RandIntInRange(1, 6)), + Uncles: tr.RandHeaders(tr.RandIntInRange(1, 6)), + Withdrawals: tr.RandWithdrawals(tr.RandIntInRange(1, 6)), + Requests: tr.RandRequests(tr.RandIntInRange(1, 6)), } } @@ -259,6 +268,7 @@ func (tr *TRand) RandBody() *Body { Transactions: tr.RandTransactions(tr.RandIntInRange(1, 6)), Uncles: tr.RandHeaders(tr.RandIntInRange(1, 6)), Withdrawals: tr.RandWithdrawals(tr.RandIntInRange(1, 6)), + Requests: tr.RandRequests(tr.RandIntInRange(1, 6)), } } @@ -278,7 +288,7 @@ func check(t *testing.T, f string, want, got interface{}) { } } -func compareHeaders(t *testing.T, a, b *Header) { +func checkHeaders(t *testing.T, a, b *Header) { check(t, "Header.ParentHash", a.ParentHash, b.ParentHash) check(t, "Header.UncleHash", a.UncleHash, b.UncleHash) check(t, "Header.Coinbase", a.Coinbase, b.Coinbase) @@ -301,7 +311,7 @@ func compareHeaders(t *testing.T, a, b *Header) { check(t, "Header.ParentBeaconBlockRoot", a.ParentBeaconBlockRoot, b.ParentBeaconBlockRoot) } -func compareWithdrawals(t *testing.T, a, b *Withdrawal) { +func checkWithdrawals(t *testing.T, a, b *Withdrawal) { check(t, "Withdrawal.Index", a.Index, b.Index) check(t, "Withdrawal.Validator", a.Validator, b.Validator) check(t, "Withdrawal.Address", a.Address, b.Address) @@ -337,77 +347,91 @@ func compareDeposits(t *testing.T, a, b *Deposit) { check(t, "Deposit.Index", a.Index, b.Index) } -func compareRawBodies(t *testing.T, a, b *RawBody) error { - - atLen, btLen := len(a.Transactions), len(b.Transactions) - if atLen != btLen { - return fmt.Errorf("transactions len mismatch: expected: %v, got: %v", atLen, btLen) +func checkRequests(t *testing.T, a, b *Request) { + if a.Type() != b.Type() { + t.Errorf("request type mismatch: request-a: %v, request-b: %v", a.Type(), b.Type()) } - for i := 0; i < atLen; i++ { - if !isEqualBytes(a.Transactions[i], b.Transactions[i]) { - return fmt.Errorf("byte transactions are not equal") - } + switch a.Type() { + case DepositRequestType: + c := a.inner.(*Deposit) + d := b.inner.(*Deposit) + compareDeposits(t, c, d) + default: + t.Errorf("unknown request type: %v", a.Type()) } +} - auLen, buLen := len(a.Uncles), len(b.Uncles) +func compareHeaders(t *testing.T, a, b []*Header) error { + auLen, buLen := len(a), len(b) if auLen != buLen { return fmt.Errorf("uncles len mismatch: expected: %v, got: %v", auLen, buLen) } for i := 0; i < auLen; i++ { - compareHeaders(t, a.Uncles[i], b.Uncles[i]) + checkHeaders(t, a[i], b[i]) } + return nil +} - awLen, bwLen := len(a.Withdrawals), len(b.Withdrawals) +func compareWithdrawals(t *testing.T, a, b []*Withdrawal) error { + awLen, bwLen := len(a), len(b) if awLen != bwLen { - return fmt.Errorf("withdrawals len mismatch: expected: %v, got: %v", auLen, buLen) + return fmt.Errorf("withdrawals len mismatch: expected: %v, got: %v", awLen, bwLen) } for i := 0; i < awLen; i++ { - compareWithdrawals(t, a.Withdrawals[i], b.Withdrawals[i]) + checkWithdrawals(t, a[i], b[i]) + } + return nil +} + +func compareRequests(t *testing.T, a, b []*Request) error { + arLen, brLen := len(a), len(b) + if arLen != brLen { + return fmt.Errorf("requests len mismatch: expected: %v, got: %v", arLen, brLen) } + for i := 0; i < arLen; i++ { + checkRequests(t, a[i], b[i]) + } return nil } -func compareBodies(t *testing.T, a, b *Body) error { +func compareRawBodies(t *testing.T, a, b *RawBody) error { atLen, btLen := len(a.Transactions), len(b.Transactions) if atLen != btLen { - return fmt.Errorf("txns len mismatch: expected: %v, got: %v", atLen, btLen) + return fmt.Errorf("transactions len mismatch: expected: %v, got: %v", atLen, btLen) } for i := 0; i < atLen; i++ { - compareTransactions(t, a.Transactions[i], b.Transactions[i]) + if !isEqualBytes(a.Transactions[i], b.Transactions[i]) { + return fmt.Errorf("byte transactions are not equal") + } } - auLen, buLen := len(a.Uncles), len(b.Uncles) - if auLen != buLen { - return fmt.Errorf("uncles len mismatch: expected: %v, got: %v", auLen, buLen) - } + compareHeaders(t, a.Uncles, b.Uncles) + compareWithdrawals(t, a.Withdrawals, b.Withdrawals) + compareRequests(t, a.Requests, b.Requests) - for i := 0; i < auLen; i++ { - compareHeaders(t, a.Uncles[i], b.Uncles[i]) - } + return nil +} - awLen, bwLen := len(a.Withdrawals), len(b.Withdrawals) - if awLen != bwLen { - return fmt.Errorf("withdrawals len mismatch: expected: %v, got: %v", awLen, bwLen) - } +func compareBodies(t *testing.T, a, b *Body) error { - for i := 0; i < awLen; i++ { - compareWithdrawals(t, a.Withdrawals[i], b.Withdrawals[i]) + atLen, btLen := len(a.Transactions), len(b.Transactions) + if atLen != btLen { + return fmt.Errorf("txns len mismatch: expected: %v, got: %v", atLen, btLen) } - // adLen, bdLen := len(a.deposits), len(b.deposits) - // if adLen != bdLen { - // return fmt.Errorf("deposits len mismatch: expected: %v, got: %v", adLen, bdLen) - // } + for i := 0; i < atLen; i++ { + compareTransactions(t, a.Transactions[i], b.Transactions[i]) + } - // for i := 0; i < adLen; i++ { - // compareDeposits(t, a.deposits[i], b.deposits[i]) - // } + compareHeaders(t, a.Uncles, b.Uncles) + compareWithdrawals(t, a.Withdrawals, b.Withdrawals) + compareRequests(t, a.Requests, b.Requests) return nil } diff --git a/core/types/request.go b/core/types/request.go index 0e10c8c644d..aa4ddaaacc8 100644 --- a/core/types/request.go +++ b/core/types/request.go @@ -5,6 +5,7 @@ import ( "fmt" "io" + rlp2 "github.com/ledgerwatch/erigon-lib/rlp" "github.com/ledgerwatch/erigon/rlp" ) @@ -16,6 +17,14 @@ type Request struct { inner RequestData } +type RequestData interface { + encodeRLP(*bytes.Buffer) error + decodeRLP([]byte) error + requestType() byte + copy() RequestData + encodingSize() int +} + func (r *Request) Type() byte { return r.inner.requestType() } @@ -26,6 +35,16 @@ func NewRequest(inner RequestData) *Request { return req } +func (r *Request) EncodingSize() int { + switch r.Type() { + case DepositRequestType: + total := r.inner.encodingSize() + 1 // +1 byte for requset type + return rlp2.ListPrefixLen(total) + total + default: + panic(fmt.Sprintf("Unknown request type: %d", r.Type())) + } +} + func (r *Request) EncodeRLP(w io.Writer) error { var buf bytes.Buffer // TODO(racytech): find a solution to reuse the same buffer instead of recreating it buf.WriteByte(r.Type()) // first write type of request then encode inner data @@ -81,10 +100,3 @@ func (r Requests) Len() int { return len(r) } func (r Requests) EncodeIndex(i int, w *bytes.Buffer) { rlp.Encode(w, r[i]) } - -type RequestData interface { - encodeRLP(*bytes.Buffer) error - decodeRLP([]byte) error - requestType() byte - copy() RequestData -} From a250bf9c6440411891e5f38800cd0b2bb0b7c0c5 Mon Sep 17 00:00:00 2001 From: racytech Date: Fri, 3 May 2024 02:42:38 +0500 Subject: [PATCH 5/7] add request to accessors_chain --- .../block_collector/block_collector.go | 2 +- .../execution_client_direct.go | 2 +- core/rawdb/accessors_chain.go | 5 +- core/rawdb/accessors_chain_test.go | 52 ++++++++++++++++++- core/types/block.go | 13 +++-- core/types/encdec_test.go | 4 +- core/types/request.go | 10 ++++ .../block_downloader.go | 2 +- turbo/engineapi/engine_server.go | 2 +- .../snapshotsync/freezeblocks/block_reader.go | 7 ++- 10 files changed, 83 insertions(+), 16 deletions(-) diff --git a/cl/phase1/execution_client/block_collector/block_collector.go b/cl/phase1/execution_client/block_collector/block_collector.go index 933dbba2118..6565ae02b01 100644 --- a/cl/phase1/execution_client/block_collector/block_collector.go +++ b/cl/phase1/execution_client/block_collector/block_collector.go @@ -109,7 +109,7 @@ func (b *blockCollector) Flush(ctx context.Context) error { b.logger.Warn("bad blocks segment received", "err", err) return err } - blocksBatch = append(blocksBatch, types.NewBlockFromStorage(executionPayload.BlockHash, header, txs, nil, body.Withdrawals)) + blocksBatch = append(blocksBatch, types.NewBlockFromStorage(executionPayload.BlockHash, header, txs, nil, body.Withdrawals, body.Requests)) if len(blocksBatch) >= batchSize { if err := b.engine.InsertBlocks(ctx, blocksBatch, true); err != nil { b.logger.Warn("failed to insert blocks", "err", err) diff --git a/cl/phase1/execution_client/execution_client_direct.go b/cl/phase1/execution_client/execution_client_direct.go index 6679e38dfb1..5ff16bb0df7 100644 --- a/cl/phase1/execution_client/execution_client_direct.go +++ b/cl/phase1/execution_client/execution_client_direct.go @@ -40,7 +40,7 @@ func (cc *ExecutionClientDirect) NewPayload(ctx context.Context, payload *cltype return true, err } - if err := cc.chainRW.InsertBlockAndWait(ctx, types.NewBlockFromStorage(payload.BlockHash, header, txs, nil, body.Withdrawals)); err != nil { + if err := cc.chainRW.InsertBlockAndWait(ctx, types.NewBlockFromStorage(payload.BlockHash, header, txs, nil, body.Withdrawals, body.Requests)); err != nil { return false, err } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 7f06b8ed8eb..ed3572ac7d6 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -610,6 +610,7 @@ func ReadBody(db kv.Getter, hash common.Hash, number uint64) (*types.Body, uint6 body := new(types.Body) body.Uncles = bodyForStorage.Uncles body.Withdrawals = bodyForStorage.Withdrawals + body.Requests = bodyForStorage.Requests if bodyForStorage.TxAmount < 2 { panic(fmt.Sprintf("block body hash too few txs amount: %d, %d", number, bodyForStorage.TxAmount)) @@ -654,6 +655,7 @@ func WriteRawBody(db kv.RwTx, hash common.Hash, number uint64, body *types.RawBo TxAmount: uint32(len(body.Transactions)) + 2, /*system txs*/ Uncles: body.Uncles, Withdrawals: body.Withdrawals, + Requests: body.Requests, } if err = WriteBodyForStorage(db, hash, number, &data); err != nil { return false, fmt.Errorf("WriteBodyForStorage: %w", err) @@ -677,6 +679,7 @@ func WriteBody(db kv.RwTx, hash common.Hash, number uint64, body *types.Body) (e TxAmount: uint32(len(body.Transactions)) + 2, Uncles: body.Uncles, Withdrawals: body.Withdrawals, + Requests: body.Requests, } if err = WriteBodyForStorage(db, hash, number, &data); err != nil { return fmt.Errorf("failed to write body: %w", err) @@ -983,7 +986,7 @@ func ReadBlock(tx kv.Getter, hash common.Hash, number uint64) *types.Block { if body == nil { return nil } - return types.NewBlockFromStorage(hash, header, body.Transactions, body.Uncles, body.Withdrawals) + return types.NewBlockFromStorage(hash, header, body.Transactions, body.Uncles, body.Withdrawals, body.Requests) } // HasBlock - is more efficient than ReadBlock because doesn't read transactions. diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 9b6e9a84e77..9449f8ef641 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -25,6 +25,7 @@ import ( "testing" libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/turbo/stages/mock" @@ -573,6 +574,32 @@ func TestBlockWithdrawalsStorage(t *testing.T) { withdrawals = append(withdrawals, &w) withdrawals = append(withdrawals, &w2) + pk := [48]byte{} + copy(pk[:], libcommon.Hex2Bytes("3d1291c96ad36914068b56d93974c1b1d5afcb3fcd37b2ac4b144afd3f6fec5b")) + sig := [96]byte{} + copy(sig[:], libcommon.Hex2Bytes("20a0a807c717055ecb60dc9d5071fbd336f7f238d61a288173de20f33f79ebf4")) + r1 := types.Deposit{ + Pubkey: pk, + WithdrawalCredentials: libcommon.Hash(hexutility.Hex2Bytes("15095f80cde9763665d2eee3f8dfffc4a4405544c6fece33130e6e98809c4b98")), + Amount: 12324, + Signature: sig, + Index: 0, + } + pk2 := [48]byte{} + copy(pk2[:], libcommon.Hex2Bytes("d40ffb510bfc52b058d5e934026ce3eddaf0a4b1703920f03b32b97de2196a93")) + sig2 := [96]byte{} + copy(sig2[:], libcommon.Hex2Bytes("dc40cf2c33c6fb17e11e3ffe455063f1bf2280a3b08563f8b33aa359a16a383c")) + r2 := types.Deposit{ + Pubkey: pk2, + WithdrawalCredentials: libcommon.Hash(hexutility.Hex2Bytes("d73d9332eb1229e58aa7e33e9a5079d9474f68f747544551461bf3ff9f7ccd64")), + Amount: 12324, + Signature: sig2, + Index: 0, + } + deposits := make(types.Deposits, 0) + deposits = append(deposits, &r1) + deposits = append(deposits, &r2) + reqs := deposits.ToRequests() // Create a test block to move around the database and make sure it's really new block := types.NewBlockWithHeader(&types.Header{ Number: big.NewInt(1), @@ -592,8 +619,7 @@ func TestBlockWithdrawalsStorage(t *testing.T) { } // Write withdrawals to block - wBlock := types.NewBlockFromStorage(block.Hash(), block.Header(), block.Transactions(), block.Uncles(), withdrawals) - + wBlock := types.NewBlockFromStorage(block.Hash(), block.Header(), block.Transactions(), block.Uncles(), withdrawals, reqs) if err := rawdb.WriteHeader(tx, wBlock.HeaderNoCopy()); err != nil { t.Fatalf("Could not write body: %v", err) } @@ -647,6 +673,28 @@ func TestBlockWithdrawalsStorage(t *testing.T) { require.Equal(libcommon.Address{0: 0xff}, rw2.Address) require.Equal(uint64(1001), rw2.Amount) + readRequests := entry.Requests + require.True(len(entry.Requests) == 2) + rd1 := readRequests[0] + rd2 := readRequests[1] + require.True(rd1.Type() == types.DepositRequestType) + require.True(rd2.Type() == types.DepositRequestType) + + readDeposits := (types.Requests)(readRequests).Deposits() + d1 := readDeposits[0] + d2 := readDeposits[1] + require.Equal(d1.Pubkey, r1.Pubkey) + require.Equal(d1.Amount, r1.Amount) + require.Equal(d1.Signature, r1.Signature) + require.Equal(d1.WithdrawalCredentials, r1.WithdrawalCredentials) + require.Equal(d1.Index, r1.Index) + + require.Equal(d2.Pubkey, r2.Pubkey) + require.Equal(d2.Amount, r2.Amount) + require.Equal(d2.Signature, r2.Signature) + require.Equal(d2.WithdrawalCredentials, r2.WithdrawalCredentials) + require.Equal(d2.Index, r2.Index) + // Delete the block and verify the execution if err := rawdb.TruncateBlocks(context.Background(), tx, block.NumberU64()); err != nil { t.Fatal(err) diff --git a/core/types/block.go b/core/types/block.go index 71f47a4474c..646daa61810 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -1051,8 +1051,8 @@ func NewBlock(header *Header, txs []Transaction, uncles []*Header, receipts []*R // NewBlockFromStorage like NewBlock but used to create Block object when read it from DB // in this case no reason to copy parts, or re-calculate headers fields - they are all stored in DB -func NewBlockFromStorage(hash libcommon.Hash, header *Header, txs []Transaction, uncles []*Header, withdrawals []*Withdrawal) *Block { - b := &Block{header: header, transactions: txs, uncles: uncles, withdrawals: withdrawals} +func NewBlockFromStorage(hash libcommon.Hash, header *Header, txs []Transaction, uncles []*Header, withdrawals []*Withdrawal, requests []*Request) *Block { + b := &Block{header: header, transactions: txs, uncles: uncles, withdrawals: withdrawals, requests: requests} b.hash.Store(hash) return b } @@ -1072,6 +1072,7 @@ func NewBlockFromNetwork(header *Header, body *Body) *Block { transactions: body.Transactions, uncles: body.Uncles, withdrawals: body.Withdrawals, + requests: body.Requests, } } @@ -1113,6 +1114,10 @@ func CopyHeader(h *Header) *Header { cpy.ParentBeaconBlockRoot = new(libcommon.Hash) cpy.ParentBeaconBlockRoot.SetBytes(h.ParentBeaconBlockRoot.Bytes()) } + if h.RequestsRoot != nil { + cpy.RequestsRoot = new(libcommon.Hash) + cpy.RequestsRoot.SetBytes(h.RequestsRoot.Bytes()) + } return &cpy } @@ -1260,6 +1265,8 @@ func (b *Block) BaseFee() *big.Int { func (b *Block) WithdrawalsHash() *libcommon.Hash { return b.header.WithdrawalsHash } func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } func (b *Block) ParentBeaconBlockRoot() *libcommon.Hash { return b.header.ParentBeaconBlockRoot } +func (b *Block) RequestsRoot() *libcommon.Hash { return b.header.RequestsRoot } +func (b *Block) Requests() Requests { return b.requests } // Header returns a deep-copy of the entire block header using CopyHeader() func (b *Block) Header() *Header { return CopyHeader(b.header) } @@ -1267,7 +1274,7 @@ func (b *Block) HeaderNoCopy() *Header { return b.header } // Body returns the non-header content of the block. func (b *Block) Body() *Body { - bd := &Body{Transactions: b.transactions, Uncles: b.uncles, Withdrawals: b.withdrawals} + bd := &Body{Transactions: b.transactions, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: b.requests} bd.SendersFromTxs() return bd } diff --git a/core/types/encdec_test.go b/core/types/encdec_test.go index 09fb401fb20..33da6276574 100644 --- a/core/types/encdec_test.go +++ b/core/types/encdec_test.go @@ -15,7 +15,7 @@ import ( "github.com/ledgerwatch/erigon/rlp" ) -const RUNS = 10 // for local tests increase this number +const RUNS = 2 // for local tests increase this number type TRand struct { rnd *rand.Rand @@ -340,7 +340,7 @@ func compareTransactions(t *testing.T, a, b Transaction) { } func compareDeposits(t *testing.T, a, b *Deposit) { - check(t, "Deposit.Pubkey", a.Index, b.Index) + check(t, "Deposit.Pubkey", a.Pubkey, b.Pubkey) check(t, "Deposit.WithdrawalCredentials", a.WithdrawalCredentials, b.WithdrawalCredentials) check(t, "Deposit.Amount", a.Amount, b.Amount) check(t, "Deposit.Signature", a.Signature, b.Signature) diff --git a/core/types/request.go b/core/types/request.go index aa4ddaaacc8..8326e67b76f 100644 --- a/core/types/request.go +++ b/core/types/request.go @@ -90,6 +90,16 @@ func (r *Request) decode(data []byte) error { return nil } +func (r Requests) Deposits() Deposits { + deposits := make(Deposits, 0, len(r)) + for _, req := range r { + if req.Type() == DepositRequestType { + deposits = append(deposits, req.inner.(*Deposit)) + } + } + return deposits +} + type Requests []*Request func (r Requests) Len() int { return len(r) } diff --git a/turbo/engineapi/engine_block_downloader/block_downloader.go b/turbo/engineapi/engine_block_downloader/block_downloader.go index fd6d35a083a..a300748b005 100644 --- a/turbo/engineapi/engine_block_downloader/block_downloader.go +++ b/turbo/engineapi/engine_block_downloader/block_downloader.go @@ -250,7 +250,7 @@ func (e *EngineBlockDownloader) insertHeadersAndBodies(ctx context.Context, tx k if body == nil { return fmt.Errorf("missing body at block=%d", number) } - blocksBatch = append(blocksBatch, types.NewBlockFromStorage(hash, header, body.Transactions, body.Uncles, body.Withdrawals)) + blocksBatch = append(blocksBatch, types.NewBlockFromStorage(hash, header, body.Transactions, body.Uncles, body.Withdrawals, body.Requests)) if number%uint64(blockWrittenLogSize) == 0 { e.logger.Info("[insertHeadersAndBodies] Written blocks", "progress", number, "to", toBlock) } diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go index 2c193986b32..3f68e302f68 100644 --- a/turbo/engineapi/engine_server.go +++ b/turbo/engineapi/engine_server.go @@ -261,7 +261,7 @@ func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.Executi defer s.lock.Unlock() s.logger.Debug("[NewPayload] sending block", "height", header.Number, "hash", blockHash) - block := types.NewBlockFromStorage(blockHash, &header, transactions, nil /* uncles */, withdrawals) + block := types.NewBlockFromStorage(blockHash, &header, transactions, nil /* uncles */, withdrawals, requests) payloadStatus, err := s.HandleNewPayload(ctx, "NewPayload", block, expectedBlobHashes) if err != nil { diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index 431e49aeb16..d1e1eccc57e 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -479,7 +479,6 @@ func (r *BlockReader) BodyWithTransactions(ctx context.Context, tx kv.Getter, ha return body, nil } } - view := r.sn.View() defer view.Close() @@ -638,7 +637,7 @@ func (r *BlockReader) blockWithSenders(ctx context.Context, tx kv.Getter, hash c return } if txsAmount == 0 { - block = types.NewBlockFromStorage(hash, h, nil, b.Uncles, b.Withdrawals) + block = types.NewBlockFromStorage(hash, h, nil, b.Uncles, b.Withdrawals, b.Requests) if len(senders) != block.Transactions().Len() { if dbgLogs { log.Info(dbgPrefix + fmt.Sprintf("found block with %d transactions, but %d senders", block.Transactions().Len(), len(senders))) @@ -661,7 +660,7 @@ func (r *BlockReader) blockWithSenders(ctx context.Context, tx kv.Getter, hash c if err != nil { return nil, nil, err } - block = types.NewBlockFromStorage(hash, h, txs, b.Uncles, b.Withdrawals) + block = types.NewBlockFromStorage(hash, h, txs, b.Uncles, b.Withdrawals, b.Requests) if len(senders) != block.Transactions().Len() { if dbgLogs { log.Info(dbgPrefix + fmt.Sprintf("found block with %d transactions, but %d senders", block.Transactions().Len(), len(senders))) @@ -746,10 +745,10 @@ func (r *BlockReader) bodyFromSnapshot(blockHeight uint64, sn *Segment, buf []by if b == nil { return nil, 0, 0, buf, nil } - body := new(types.Body) body.Uncles = b.Uncles body.Withdrawals = b.Withdrawals + body.Requests = b.Requests var txsAmount uint32 if b.TxAmount >= 2 { txsAmount = b.TxAmount - 2 From c365a8654b7fe7305e5236c175105d0451d31457 Mon Sep 17 00:00:00 2001 From: racytech Date: Tue, 7 May 2024 01:54:12 +0500 Subject: [PATCH 6/7] add requests to Finalize and FinalizeAndAssamble --- cl/cltypes/beacon_block_test.go | 2 +- cmd/evm/internal/t8ntool/transition.go | 2 +- cmd/state/commands/opcode_tracer.go | 2 +- cmd/state/exec3/state.go | 2 +- cmd/state/exec3/state_recon.go | 2 +- cmd/state/exec3/trace_worker2.go | 2 +- consensus/aura/aura.go | 8 ++++---- consensus/clique/clique.go | 12 ++++++------ consensus/consensus.go | 6 ++---- consensus/ethash/consensus.go | 8 ++++---- consensus/merge/merge.go | 13 ++++++------- core/blockchain.go | 9 +++++---- core/chain_makers.go | 4 ++-- core/genesis_write.go | 7 ++++++- core/rawdb/accessors_indexes_test.go | 2 +- core/types/block.go | 17 ++++++++++++++++- core/types/block_test.go | 6 +++--- core/types/request.go | 1 - eth/stagedsync/stage_mining_create_block.go | 1 + eth/stagedsync/stage_mining_exec.go | 7 +++++-- eth/stagedsync/stage_mining_finish.go | 2 +- polygon/bor/bor.go | 6 +++--- polygon/bor/fake.go | 4 ++-- polygon/p2p/message_listener_test.go | 2 +- tests/statedb_insert_chain_transaction_test.go | 18 +++++++++--------- .../eth1/eth1_chain_reader.go/chain_reader.go | 4 ++-- turbo/execution/eth1/eth1_utils/grpc_test.go | 9 ++++++++- 27 files changed, 93 insertions(+), 65 deletions(-) diff --git a/cl/cltypes/beacon_block_test.go b/cl/cltypes/beacon_block_test.go index ae9c18347c1..73e4c111ec1 100644 --- a/cl/cltypes/beacon_block_test.go +++ b/cl/cltypes/beacon_block_test.go @@ -39,7 +39,7 @@ func TestBeaconBody(t *testing.T) { BaseFee: big.NewInt(1), }, []types.Transaction{types.NewTransaction(1, [20]byte{}, uint256.NewInt(1), 5, uint256.NewInt(2), nil)}, nil, nil, types.Withdrawals{&types.Withdrawal{ Index: 69, - }}) + }}, nil /*requests*/) // Test BeaconBody body := &BeaconBody{ diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 095c626807e..c9b8acd23d0 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -279,7 +279,7 @@ func Main(ctx *cli.Context) error { ommerN.SetUint64(header.Number.Uint64() - ommer.Delta) ommerHeaders[i] = &types.Header{Coinbase: ommer.Address, Number: &ommerN} } - block := types.NewBlock(header, txs, ommerHeaders, nil /* receipts */, prestate.Env.Withdrawals) + block := types.NewBlock(header, txs, ommerHeaders, nil /* receipts */, prestate.Env.Withdrawals, nil /*requests*/) var hashError error getHash := func(num uint64) libcommon.Hash { diff --git a/cmd/state/commands/opcode_tracer.go b/cmd/state/commands/opcode_tracer.go index 3f19b3bbe80..39ff645b249 100644 --- a/cmd/state/commands/opcode_tracer.go +++ b/cmd/state/commands/opcode_tracer.go @@ -732,7 +732,7 @@ func runBlock(engine consensus.Engine, ibs *state.IntraBlockState, txnWriter sta if !vmConfig.ReadOnly { // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) tx := block.Transactions() - if _, _, _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, tx, block.Uncles(), receipts, block.Withdrawals(), nil, nil, nil, logger); err != nil { + if _, _, _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, tx, block.Uncles(), receipts, block.Withdrawals(), block.Requests(), nil, nil, nil, logger); err != nil { return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err) } diff --git a/cmd/state/exec3/state.go b/cmd/state/exec3/state.go index 2f2beaab96b..2640255771d 100644 --- a/cmd/state/exec3/state.go +++ b/cmd/state/exec3/state.go @@ -205,7 +205,7 @@ func (rw *Worker) RunTxTaskNoLock(txTask *state.TxTask) { return core.SysCallContract(contract, data, rw.chainConfig, ibs, header, rw.engine, false /* constCall */) } - _, _, err := rw.engine.Finalize(rw.chainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, rw.chain, syscall, rw.logger) + _, _, err := rw.engine.Finalize(rw.chainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, nil /*requests*/, rw.chain, syscall, rw.logger) if err != nil { txTask.Error = err } else { diff --git a/cmd/state/exec3/state_recon.go b/cmd/state/exec3/state_recon.go index ebdd9f8c33b..dfa25de7eaf 100644 --- a/cmd/state/exec3/state_recon.go +++ b/cmd/state/exec3/state_recon.go @@ -308,7 +308,7 @@ func (rw *ReconWorker) runTxTask(txTask *state.TxTask) error { syscall := func(contract libcommon.Address, data []byte) ([]byte, error) { return core.SysCallContract(contract, data, rw.chainConfig, ibs, header, rw.engine, false /* constCall */) } - if _, _, err := rw.engine.Finalize(rw.chainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, rw.chain, syscall, rw.logger); err != nil { + if _, _, err := rw.engine.Finalize(rw.chainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, nil /*requests*/, rw.chain, syscall, rw.logger); err != nil { if _, readError := rw.stateReader.ReadError(); !readError { return fmt.Errorf("finalize of block %d failed: %w", txTask.BlockNum, err) } diff --git a/cmd/state/exec3/trace_worker2.go b/cmd/state/exec3/trace_worker2.go index 1e8fccdec36..448ac3d521e 100644 --- a/cmd/state/exec3/trace_worker2.go +++ b/cmd/state/exec3/trace_worker2.go @@ -155,7 +155,7 @@ func (rw *TraceWorker2) RunTxTask(txTask *state.TxTask) { return core.SysCallContract(contract, data, rw.execArgs.ChainConfig, ibs, header, rw.execArgs.Engine, false /* constCall */) } - _, _, err := rw.execArgs.Engine.Finalize(rw.execArgs.ChainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, rw.chain, syscall, rw.logger) + _, _, err := rw.execArgs.Engine.Finalize(rw.execArgs.ChainConfig, types.CopyHeader(header), ibs, txTask.Txs, txTask.Uncles, txTask.BlockReceipts, txTask.Withdrawals, nil /*requests*/, rw.chain, syscall, rw.logger) if err != nil { txTask.Error = err } diff --git a/consensus/aura/aura.go b/consensus/aura/aura.go index 9b571d2513b..2d1d84b97b2 100644 --- a/consensus/aura/aura.go +++ b/consensus/aura/aura.go @@ -703,7 +703,7 @@ func (c *AuRa) applyRewards(header *types.Header, state *state.IntraBlockState, // word `signal epoch` == word `pending epoch` func (c *AuRa) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, txs types.Transactions, - uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, + uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { if err := c.applyRewards(header, state, syscall); err != nil { @@ -842,14 +842,14 @@ func allHeadersUntil(chain consensus.ChainHeaderReader, from *types.Header, to l //} // FinalizeAndAssemble implements consensus.Engine -func (c *AuRa) FinalizeAndAssemble(config *chain.Config, header *types.Header, state *state.IntraBlockState, txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger) (*types.Block, types.Transactions, types.Receipts, error) { - outTxs, outReceipts, err := c.Finalize(config, header, state, txs, uncles, receipts, withdrawals, chain, syscall, logger) +func (c *AuRa) FinalizeAndAssemble(config *chain.Config, header *types.Header, state *state.IntraBlockState, txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger) (*types.Block, types.Transactions, types.Receipts, error) { + outTxs, outReceipts, err := c.Finalize(config, header, state, txs, uncles, receipts, withdrawals, requests, chain, syscall, logger) if err != nil { return nil, nil, nil, err } // Assemble and return the final block for sealing - return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals), outTxs, outReceipts, nil + return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals, requests), outTxs, outReceipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 6efe46f21ae..6885c8218d4 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -22,14 +22,15 @@ import ( "context" "errors" "fmt" - "github.com/ledgerwatch/erigon-lib/common/hexutil" - "github.com/ledgerwatch/erigon-lib/kv/dbutils" "io" "math/big" "math/rand" "sync" "time" + "github.com/ledgerwatch/erigon-lib/common/hexutil" + "github.com/ledgerwatch/erigon-lib/kv/dbutils" + "github.com/goccy/go-json" lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/erigon/turbo/services" @@ -377,7 +378,7 @@ func (c *Clique) CalculateRewards(config *chain.Config, header *types.Header, un // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. func (c *Clique) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped @@ -388,14 +389,13 @@ func (c *Clique) Finalize(config *chain.Config, header *types.Header, state *sta // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. func (c *Clique) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, + txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped header.UncleHash = types.CalcUncleHash(nil) // Assemble and return the final block for sealing - return types.NewBlock(header, txs, nil, receipts, withdrawals), txs, receipts, nil + return types.NewBlock(header, txs, nil, receipts, withdrawals, requests), txs, receipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/consensus.go b/consensus/consensus.go index 334b7f85a1f..3e58f732144 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -154,8 +154,7 @@ type EngineWriter interface { // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain ChainReader, syscall SystemCall, logger log.Logger, + txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain ChainReader, syscall SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block @@ -164,8 +163,7 @@ type EngineWriter interface { // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). FinalizeAndAssemble(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain ChainReader, syscall SystemCall, call Call, logger log.Logger, + txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain ChainReader, syscall SystemCall, call Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) // Seal generates a new sealing request for the given input block and pushes diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 00c26a60d86..5642478d317 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -562,7 +562,7 @@ func (ethash *Ethash) Initialize(config *chain.Config, chain consensus.ChainHead // Finalize implements consensus.Engine, accumulating the block and uncle rewards, // setting the final state on the header func (ethash *Ethash) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { // Accumulate any block and uncle rewards and commit the final state root @@ -573,17 +573,17 @@ func (ethash *Ethash) Finalize(config *chain.Config, header *types.Header, state // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. func (ethash *Ethash) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) { // Finalize block - outTxs, outR, err := ethash.Finalize(chainConfig, header, state, txs, uncles, r, withdrawals, chain, syscall, logger) + outTxs, outR, err := ethash.Finalize(chainConfig, header, state, txs, uncles, r, withdrawals, requests, chain, syscall, logger) if err != nil { return nil, nil, nil, err } // Header seems complete, assemble into a block and return - return types.NewBlock(header, outTxs, uncles, outR, withdrawals), outTxs, outR, nil + return types.NewBlock(header, outTxs, uncles, outR, withdrawals, requests), outTxs, outR, nil } // SealHash returns the hash of a block prior to it being sealed. diff --git a/consensus/merge/merge.go b/consensus/merge/merge.go index c5544ef33bd..aabd1724867 100644 --- a/consensus/merge/merge.go +++ b/consensus/merge/merge.go @@ -131,11 +131,11 @@ func (s *Merge) CalculateRewards(config *chain.Config, header *types.Header, unc } func (s *Merge) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { if !misc.IsPoSHeader(header) { - return s.eth1Engine.Finalize(config, header, state, txs, uncles, r, withdrawals, chain, syscall, logger) + return s.eth1Engine.Finalize(config, header, state, txs, uncles, r, withdrawals, requests, chain, syscall, logger) } rewards, err := s.CalculateRewards(config, header, uncles, syscall) @@ -163,17 +163,16 @@ func (s *Merge) Finalize(config *chain.Config, header *types.Header, state *stat } func (s *Merge) FinalizeAndAssemble(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, - chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, + txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) { if !misc.IsPoSHeader(header) { - return s.eth1Engine.FinalizeAndAssemble(config, header, state, txs, uncles, receipts, withdrawals, chain, syscall, call, logger) + return s.eth1Engine.FinalizeAndAssemble(config, header, state, txs, uncles, receipts, withdrawals, requests, chain, syscall, call, logger) } - outTxs, outReceipts, err := s.Finalize(config, header, state, txs, uncles, receipts, withdrawals, chain, syscall, logger) + outTxs, outReceipts, err := s.Finalize(config, header, state, txs, uncles, receipts, withdrawals, requests, chain, syscall, logger) if err != nil { return nil, nil, nil, err } - return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals), outTxs, outReceipts, nil + return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals, requests), outTxs, outReceipts, nil } func (s *Merge) SealHash(header *types.Header) (hash libcommon.Hash) { diff --git a/core/blockchain.go b/core/blockchain.go index 924cc9bc7d6..f65764299e2 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -165,7 +165,7 @@ func ExecuteBlockEphemerally( } if !vmConfig.ReadOnly { txs := block.Transactions() - if _, _, _, err := FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), chainReader, false, logger); err != nil { + if _, _, _, err := FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), block.Requests(), chainReader, false, logger); err != nil { return nil, err } } @@ -212,6 +212,7 @@ func ExecuteBlockEphemerally( rh := types.DeriveSha(requests) if *block.Header().RequestsRoot != rh { // TODO(racytech): do we have to check it here? + return nil, fmt.Errorf("error: parsed requests root hash mismatch, expected: %v, got :%v", *block.Header().RequestsRoot, rh) } } @@ -329,7 +330,7 @@ func FinalizeBlockExecution( header *types.Header, txs types.Transactions, uncles []*types.Header, stateWriter state.StateWriter, cc *chain.Config, ibs *state.IntraBlockState, receipts types.Receipts, - withdrawals []*types.Withdrawal, chainReader consensus.ChainReader, + withdrawals []*types.Withdrawal, requests []*types.Request, chainReader consensus.ChainReader, isMining bool, logger log.Logger, ) (newBlock *types.Block, newTxs types.Transactions, newReceipt types.Receipts, err error) { @@ -337,9 +338,9 @@ func FinalizeBlockExecution( return SysCallContract(contract, data, cc, ibs, header, engine, false /* constCall */) } if isMining { - newBlock, newTxs, newReceipt, err = engine.FinalizeAndAssemble(cc, header, ibs, txs, uncles, receipts, withdrawals, chainReader, syscall, nil, logger) + newBlock, newTxs, newReceipt, err = engine.FinalizeAndAssemble(cc, header, ibs, txs, uncles, receipts, withdrawals, requests, chainReader, syscall, nil, logger) } else { - _, _, err = engine.Finalize(cc, header, ibs, txs, uncles, receipts, withdrawals, chainReader, syscall, logger) + _, _, err = engine.Finalize(cc, header, ibs, txs, uncles, receipts, withdrawals, requests, chainReader, syscall, logger) } if err != nil { return nil, nil, nil, err diff --git a/core/chain_makers.go b/core/chain_makers.go index 5e3c6447d08..1def7444a17 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -379,7 +379,7 @@ func GenerateChain(config *chain.Config, parent *types.Block, engine consensus.E txNumIncrement() if b.engine != nil { // Finalize and seal the block - if _, _, _, err := b.engine.FinalizeAndAssemble(config, b.header, ibs, b.txs, b.uncles, b.receipts, nil, nil, nil, nil, logger); err != nil { + if _, _, _, err := b.engine.FinalizeAndAssemble(config, b.header, ibs, b.txs, b.uncles, b.receipts, nil, nil, nil, nil, nil, logger); err != nil { return nil, nil, fmt.Errorf("call to FinaliseAndAssemble: %w", err) } // Write state changes to db @@ -407,7 +407,7 @@ func GenerateChain(config *chain.Config, parent *types.Block, engine consensus.E } _ = err // Recreating block to make sure Root makes it into the header - block := types.NewBlock(b.header, b.txs, b.uncles, b.receipts, nil /* withdrawals */) + block := types.NewBlock(b.header, b.txs, b.uncles, b.receipts, nil /* withdrawals */, nil /*requests*/) return block, b.receipts, nil } return nil, nil, fmt.Errorf("no engine to generate blocks") diff --git a/core/genesis_write.go b/core/genesis_write.go index 915718f63e9..40c83e879ba 100644 --- a/core/genesis_write.go +++ b/core/genesis_write.go @@ -548,6 +548,11 @@ func GenesisToBlock(g *types.Genesis, tmpDir string, logger log.Logger) (*types. } } + var requests []*types.Request // TODO(racytech): revisit this after merge, make sure everythin is correct + if g.Config != nil && g.Config.IsPrague(g.Timestamp) { + requests = []*types.Request{} + } + var root libcommon.Hash var statedb *state.IntraBlockState wg := sync.WaitGroup{} @@ -624,7 +629,7 @@ func GenesisToBlock(g *types.Genesis, tmpDir string, logger log.Logger) (*types. head.Root = root - return types.NewBlock(head, nil, nil, nil, withdrawals), statedb, nil + return types.NewBlock(head, nil, nil, nil, withdrawals, requests), statedb, nil } func sortedAllocKeys(m types.GenesisAlloc) []string { diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 6901a6c5eb3..2845724b61e 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -63,7 +63,7 @@ func TestLookupStorage(t *testing.T) { tx3 := types.NewTransaction(3, libcommon.BytesToAddress([]byte{0x33}), uint256.NewInt(333), 3333, uint256.NewInt(33333), []byte{0x33, 0x33, 0x33}) txs := []types.Transaction{tx1, tx2, tx3} - block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, nil) + block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, nil, nil /*requests*/) // Check that no transactions entries are in a pristine database for i, txn := range txs { diff --git a/core/types/block.go b/core/types/block.go index 646daa61810..fb0282e67d2 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -999,7 +999,7 @@ func (bb *Body) DecodeRLP(s *rlp.Stream) error { // The values of TxHash, UncleHash, ReceiptHash, Bloom, and WithdrawalHash // in the header are ignored and set to the values derived from // the given txs, uncles, receipts, and withdrawals. -func NewBlock(header *Header, txs []Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal) *Block { +func NewBlock(header *Header, txs []Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal, requests []*Request) *Block { b := &Block{header: CopyHeader(header)} // TODO: panic if len(txs) != len(receipts) @@ -1046,6 +1046,21 @@ func NewBlock(header *Header, txs []Transaction, uncles []*Header, receipts []*R b.header.ParentBeaconBlockRoot = header.ParentBeaconBlockRoot + if requests == nil { + b.header.RequestsRoot = nil + } else if len(requests) == 0 { + b.header.RequestsRoot = &EmptyRootHash // TODO(racytech): is this correct? + b.requests = make(Requests, len(requests)) + } else { + h := DeriveSha(Requests(requests)) + b.header.RequestsRoot = &h + b.requests = make(Requests, len(requests)) + for i, r := range requests { + rCopy := *r + b.requests[i] = &rCopy + } + } + return b } diff --git a/core/types/block_test.go b/core/types/block_test.go index 9db421134ac..7d7ac4a4da3 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -358,7 +358,7 @@ func makeBenchBlock() *Block { Extra: []byte("benchmark uncle"), } } - return NewBlock(header, txs, uncles, receipts, nil /* withdrawals */) + return NewBlock(header, txs, uncles, receipts, nil /* withdrawals */, nil /*requests*/) } func TestCanEncodeAndDecodeRawBody(t *testing.T) { @@ -506,7 +506,7 @@ func TestWithdrawalsEncoding(t *testing.T) { Amount: 5_000_000_000, } - block := NewBlock(&header, nil, nil, nil, withdrawals) + block := NewBlock(&header, nil, nil, nil, withdrawals, nil /*requests*/) _ = block.Size() encoded, err := rlp.EncodeToBytes(block) @@ -518,7 +518,7 @@ func TestWithdrawalsEncoding(t *testing.T) { assert.Equal(t, block, &decoded) // Now test with empty withdrawals - block2 := NewBlock(&header, nil, nil, nil, []*Withdrawal{}) + block2 := NewBlock(&header, nil, nil, nil, []*Withdrawal{}, nil /*requests*/) _ = block2.Size() encoded2, err := rlp.EncodeToBytes(block2) diff --git a/core/types/request.go b/core/types/request.go index 8326e67b76f..1423be32c62 100644 --- a/core/types/request.go +++ b/core/types/request.go @@ -66,7 +66,6 @@ func (r *Request) DecodeRLP(s *rlp.Stream) error { if buf, err = s.Bytes(); err != nil { return err } - return r.decode(buf) } } diff --git a/eth/stagedsync/stage_mining_create_block.go b/eth/stagedsync/stage_mining_create_block.go index a2edf156ded..ea1a5b3e032 100644 --- a/eth/stagedsync/stage_mining_create_block.go +++ b/eth/stagedsync/stage_mining_create_block.go @@ -32,6 +32,7 @@ type MiningBlock struct { Receipts types.Receipts Withdrawals []*types.Withdrawal PreparedTxs types.TransactionsStream + Requests []*types.Request } type MiningState struct { diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go index 0d474e6ad1a..65dfca31052 100644 --- a/eth/stagedsync/stage_mining_exec.go +++ b/eth/stagedsync/stage_mining_exec.go @@ -184,14 +184,17 @@ func SpawnMiningExecStage(s *StageState, txc wrap.TxContainer, cfg MiningExecCfg if current.Receipts == nil { current.Receipts = types.Receipts{} } + if current.Requests == nil { + current.Requests = types.Requests{} + } var err error - _, current.Txs, current.Receipts, err = core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, &state.NoopWriter{}, &cfg.chainConfig, ibs, current.Receipts, current.Withdrawals, ChainReaderImpl{config: &cfg.chainConfig, tx: txc.Tx, blockReader: cfg.blockReader, logger: logger}, true, logger) + _, current.Txs, current.Receipts, err = core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, &state.NoopWriter{}, &cfg.chainConfig, ibs, current.Receipts, current.Withdrawals, current.Requests, ChainReaderImpl{config: &cfg.chainConfig, tx: txc.Tx, blockReader: cfg.blockReader, logger: logger}, true, logger) if err != nil { return err } - block := types.NewBlock(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals) + block := types.NewBlock(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals, current.Requests) // Simulate the block execution to get the final state root if err := rawdb.WriteHeader(txc.Tx, block.Header()); err != nil { return fmt.Errorf("cannot write header: %s", err) diff --git a/eth/stagedsync/stage_mining_finish.go b/eth/stagedsync/stage_mining_finish.go index d3d36dfbab6..408a7990e71 100644 --- a/eth/stagedsync/stage_mining_finish.go +++ b/eth/stagedsync/stage_mining_finish.go @@ -52,7 +52,7 @@ func SpawnMiningFinishStage(s *StageState, tx kv.RwTx, cfg MiningFinishCfg, quit // continue //} - block := types.NewBlock(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals) + block := types.NewBlock(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals, current.Requests) blockWithReceipts := &types.BlockWithReceipts{Block: block, Receipts: current.Receipts} *current = MiningBlock{} // hack to clean global data diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 504d6d1ec7f..05525941386 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -974,7 +974,7 @@ func (c *Bor) CalculateRewards(config *chain.Config, header *types.Header, uncle // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. func (c *Bor) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { headerNumber := header.Number.Uint64() @@ -1038,7 +1038,7 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.Intra // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. func (c *Bor) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) { // stateSyncData := []*types.StateSyncData{} @@ -1078,7 +1078,7 @@ func (c *Bor) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Heade header.UncleHash = types.CalcUncleHash(nil) // Assemble block - block := types.NewBlock(header, txs, nil, receipts, withdrawals) + block := types.NewBlock(header, txs, nil, receipts, withdrawals, requests) // set state sync // bc := chain.(*core.BlockChain) diff --git a/polygon/bor/fake.go b/polygon/bor/fake.go index fb79b7642da..fc3485eef54 100644 --- a/polygon/bor/fake.go +++ b/polygon/bor/fake.go @@ -21,8 +21,8 @@ func NewFaker() *FakeBor { } func (f *FakeBor) Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, - txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, + txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests []*types.Request, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, error) { - return f.FakeEthash.Finalize(config, header, state, txs, uncles, r, withdrawals, chain, syscall, logger) + return f.FakeEthash.Finalize(config, header, state, txs, uncles, r, withdrawals, requests, chain, syscall, logger) } diff --git a/polygon/p2p/message_listener_test.go b/polygon/p2p/message_listener_test.go index 601fd38fe47..dc55a209d61 100644 --- a/polygon/p2p/message_listener_test.go +++ b/polygon/p2p/message_listener_test.go @@ -416,7 +416,7 @@ func blockHeadersPacket66Bytes(t *testing.T, requestId uint64, headers []*types. func newMockNewBlockPacketBytes(t *testing.T) []byte { newBlockPacket := eth.NewBlockPacket{ - Block: types.NewBlock(newMockBlockHeaders(1)[0], nil, nil, nil, nil), + Block: types.NewBlock(newMockBlockHeaders(1)[0], nil, nil, nil, nil, nil), } newBlockPacketBytes, err := rlp.EncodeToBytes(&newBlockPacket) require.NoError(t, err) diff --git a/tests/statedb_insert_chain_transaction_test.go b/tests/statedb_insert_chain_transaction_test.go index 63edc94e617..e4499feace1 100644 --- a/tests/statedb_insert_chain_transaction_test.go +++ b/tests/statedb_insert_chain_transaction_test.go @@ -52,7 +52,7 @@ func TestInsertIncorrectStateRootDifferentAccounts(t *testing.T) { t.Fatal("roots are the same") } - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -119,7 +119,7 @@ func TestInsertIncorrectStateRootSameAccount(t *testing.T) { t.Fatal("roots are the same") } - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -181,7 +181,7 @@ func TestInsertIncorrectStateRootSameAccountSameAmount(t *testing.T) { incorrectHeader := *chain.Headers[0] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -243,7 +243,7 @@ func TestInsertIncorrectStateRootAllFundsRoot(t *testing.T) { incorrectHeader := *chain.Headers[0] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -304,7 +304,7 @@ func TestInsertIncorrectStateRootAllFunds(t *testing.T) { // BLOCK 1 incorrectHeader := *chain.Headers[0] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { @@ -385,7 +385,7 @@ func TestAccountDeployIncorrectRoot(t *testing.T) { incorrectHeader := *chain.Headers[1] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[0].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[1].Transactions(), chain.Blocks[1].Uncles(), chain.Receipts[1], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[1].Transactions(), chain.Blocks[1].Uncles(), chain.Receipts[1], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} // BLOCK 2 - INCORRECT @@ -492,7 +492,7 @@ func TestAccountCreateIncorrectRoot(t *testing.T) { // BLOCK 3 - INCORRECT incorrectHeader := *chain.Headers[2] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[2].Transactions(), chain.Blocks[2].Uncles(), chain.Receipts[2], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[2].Transactions(), chain.Blocks[2].Uncles(), chain.Receipts[2], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { @@ -581,7 +581,7 @@ func TestAccountUpdateIncorrectRoot(t *testing.T) { // BLOCK 4 - INCORRECT incorrectHeader := *chain.Headers[3] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { @@ -669,7 +669,7 @@ func TestAccountDeleteIncorrectRoot(t *testing.T) { // BLOCK 4 - INCORRECT incorrectHeader := *chain.Headers[3] // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil) + incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") diff --git a/turbo/execution/eth1/eth1_chain_reader.go/chain_reader.go b/turbo/execution/eth1/eth1_chain_reader.go/chain_reader.go index d09b415f523..c31330b6bca 100644 --- a/turbo/execution/eth1/eth1_chain_reader.go/chain_reader.go +++ b/turbo/execution/eth1/eth1_chain_reader.go/chain_reader.go @@ -107,7 +107,7 @@ func (c ChainReaderWriterEth1) GetBlockByHash(ctx context.Context, hash libcommo log.Warn("[engine] GetBlockByHash", "err", err) return nil } - return types.NewBlock(header, txs, nil, nil, body.Withdrawals) + return types.NewBlock(header, txs, nil, nil, body.Withdrawals, body.Requests) } func (c ChainReaderWriterEth1) GetBlockByNumber(ctx context.Context, number uint64) *types.Block { @@ -136,7 +136,7 @@ func (c ChainReaderWriterEth1) GetBlockByNumber(ctx context.Context, number uint log.Warn("[engine] GetBlockByNumber", "err", err) return nil } - return types.NewBlock(header, txs, nil, nil, body.Withdrawals) + return types.NewBlock(header, txs, nil, nil, body.Withdrawals, body.Requests) } func (c ChainReaderWriterEth1) GetHeaderByHash(ctx context.Context, hash libcommon.Hash) *types.Header { diff --git a/turbo/execution/eth1/eth1_utils/grpc_test.go b/turbo/execution/eth1/eth1_utils/grpc_test.go index eeb684d5062..3c593337c34 100644 --- a/turbo/execution/eth1/eth1_utils/grpc_test.go +++ b/turbo/execution/eth1/eth1_utils/grpc_test.go @@ -58,7 +58,14 @@ func makeBlock(txCount, uncleCount, withdrawalCount int) *types.Block { Amount: uint64(10 * i), } } - return types.NewBlock(header, txs, uncles, receipts, withdrawals) + for i := range withdrawals { + withdrawals[i] = &types.Withdrawal{ + Index: uint64(i), + Validator: uint64(i), + Amount: uint64(10 * i), + } + } + return types.NewBlock(header, txs, uncles, receipts, withdrawals, nil) // TODO(racytech): add requests } func TestBlockRpcConversion(t *testing.T) { From fb360c0fe50631bdbe3a792595c48320bfe6e482 Mon Sep 17 00:00:00 2001 From: racytech Date: Tue, 7 May 2024 02:09:59 +0500 Subject: [PATCH 7/7] add if vmConfig.NoReceipts check --- core/blockchain.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index f65764299e2..0120dbd7cbb 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -210,9 +210,9 @@ func ExecuteBlockEphemerally( } rh := types.DeriveSha(requests) - if *block.Header().RequestsRoot != rh { + if *block.Header().RequestsRoot != rh && !vmConfig.NoReceipts { // TODO(racytech): do we have to check it here? - return nil, fmt.Errorf("error: parsed requests root hash mismatch, expected: %v, got :%v", *block.Header().RequestsRoot, rh) + return nil, fmt.Errorf("error: invalid requests root hash, expected: %v, got :%v", *block.Header().RequestsRoot, rh) } }