diff --git a/core/types/blob_sidecars.go b/core/types/blob_sidecars.go index cc954aad8e6..dd7444a66a1 100644 --- a/core/types/blob_sidecars.go +++ b/core/types/blob_sidecars.go @@ -62,9 +62,21 @@ func (s *BlobSidecar) EncodeRLP(w io.Writer) error { if err := EncodeStructSizePrefix(s.payloadSize(), w, b[:]); err != nil { return err } - if err := s.BlobTxSidecar.EncodeRLP(w); err != nil { + // blobs + if err := s.Blobs.encodePayload(w, b[:], s.Blobs.payloadSize()); err != nil { return err } + + // commitments + if err := s.Commitments.encodePayload(w, b[:], s.Commitments.payloadSize()); err != nil { + return err + } + + // proofs + if err := s.Proofs.encodePayload(w, b[:], s.Proofs.payloadSize()); err != nil { + return err + } + if err := rlp.Encode(w, s.BlockNumber); err != nil { return err } @@ -86,27 +98,31 @@ func (sc *BlobSidecar) DecodeRLP(s *rlp.Stream) error { if err != nil { return err } - if err := sc.BlobTxSidecar.DecodeRLP(s); err != nil { - return err + + if err := sc.Blobs.DecodeRLP(s); err != nil { + return fmt.Errorf("decode Blobs: %w", err) + } + + if err := sc.Commitments.DecodeRLP(s); err != nil { + return fmt.Errorf("decode Commitments: %w", err) } - var b []byte - if b, err = s.Bytes(); err != nil { + + if err := sc.Proofs.DecodeRLP(s); err != nil { + return fmt.Errorf("decode Proofs: %w", err) + } + sc.BlockNumber = new(big.Int) + if err := s.Decode(sc.BlockNumber); err != nil { return err } - sc.BlockNumber = new(big.Int).SetBytes(b) - if b, err = s.Bytes(); err != nil { + if err := s.Decode(&sc.BlockHash); err != nil { return err } - sc.BlockHash = libcommon.BytesToHash(b) - - if sc.TxIndex, err = s.Uint(); err != nil { + if err := s.Decode(&sc.TxIndex); err != nil { return err } - - if b, err = s.Bytes(); err != nil { + if err := s.Decode(&sc.TxHash); err != nil { return err } - sc.TxHash = libcommon.BytesToHash(b) if err = s.ListEnd(); err != nil { return fmt.Errorf("close BlobSidecar: %w", err) @@ -116,10 +132,10 @@ func (sc *BlobSidecar) DecodeRLP(s *rlp.Stream) error { func (s *BlobSidecar) payloadSize() int { size := s.BlobTxSidecar.payloadSize() - size += rlp.BigIntLenExcludingHead(s.BlockNumber) - size += 32 - size += 8 - size += 32 + size += 1 + rlp.BigIntLenExcludingHead(s.BlockNumber) + size += 33 + size += 1 + rlp.IntLenExcludingHead(s.TxIndex) + size += 33 return size } diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 85e656505c8..51fd31e770f 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -19,14 +19,13 @@ package eth import ( "errors" "fmt" + rlp2 "github.com/ledgerwatch/erigon-lib/rlp" "io" "math/big" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/direct" proto_sentry "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" - rlp2 "github.com/ledgerwatch/erigon-lib/rlp" - "github.com/ledgerwatch/erigon/core/forkid" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/rlp" @@ -266,7 +265,7 @@ type BlockHeadersPacket66 struct { type NewBlockPacket struct { Block *types.Block TD *big.Int - Sidecars types.BlobSidecars + Sidecars types.BlobSidecars `rlp:"optional"` } func (nbp NewBlockPacket) EncodeRLP(w io.Writer) error { @@ -284,6 +283,14 @@ func (nbp NewBlockPacket) EncodeRLP(w io.Writer) error { } } encodingSize += tdLen + if len(nbp.Sidecars) > 0 { + sidecarsLen := 0 + for _, item := range nbp.Sidecars { + size := item.EncodingSize() + sidecarsLen += rlp2.ListPrefixLen(size) + size + } + encodingSize += rlp2.ListPrefixLen(sidecarsLen) + sidecarsLen + } var b [33]byte // prefix if err := types.EncodeStructSizePrefix(encodingSize, w, b[:]); err != nil { diff --git a/eth/protocols/eth/protocol_test.go b/eth/protocols/eth/protocol_test.go index b99caaf8e10..53c0a19599a 100644 --- a/eth/protocols/eth/protocol_test.go +++ b/eth/protocols/eth/protocol_test.go @@ -18,6 +18,10 @@ package eth import ( "bytes" + "github.com/holiman/uint256" + types2 "github.com/ledgerwatch/erigon-lib/types" + "github.com/ledgerwatch/erigon/params" + "github.com/stretchr/testify/require" "math/big" "testing" @@ -229,3 +233,87 @@ func TestEth66Messages(t *testing.T) { } } } + +func TestNewBlockPacket_EncodeDecode(t *testing.T) { + dynamicTx := &types.DynamicFeeTransaction{ + CommonTx: types.CommonTx{ + Nonce: 0, + Gas: 25000, + To: &libcommon.Address{0x03, 0x04, 0x05}, + Value: uint256.NewInt(99), // wei amount + Data: make([]byte, 50), + }, + ChainID: uint256.NewInt(716), + Tip: uint256.NewInt(22), + FeeCap: uint256.NewInt(5), + AccessList: types2.AccessList{}, + } + txSidecar := types.BlobTxSidecar{ + Blobs: types.Blobs{types.Blob{}, types.Blob{}}, + Commitments: types.BlobKzgs{types.KZGCommitment{}, types.KZGCommitment{}}, + Proofs: types.KZGProofs{types.KZGProof{}, types.KZGProof{}}, + } + blobTx := &types.BlobTx{ + DynamicFeeTransaction: *dynamicTx, + MaxFeePerBlobGas: uint256.NewInt(5), + BlobVersionedHashes: []libcommon.Hash{{}}, + } + blobGasUsed := uint64(params.BlobTxBlobGasPerBlob) + excessBlobGas := uint64(0) + withdrawalsHash := libcommon.Hash{} + header := &types.Header{ + ParentHash: libcommon.HexToHash("0x85a8f2a2d4d2b3e73154d8ed1b5deb7c7c395dde7b934058bcc5d0efb69dff60"), + UncleHash: types.EmptyUncleHash, + Coinbase: libcommon.HexToAddress("0x76d76ee8823de52a1a431884c2ca930c5e72bff3 "), + Root: types.EmptyRootHash, + TxHash: libcommon.HexToHash("0xa84b1b157b86ed7e1352fa8e6518cd31e9be686bd27b1fe79d7ae6ebc02b29bb"), + ReceiptHash: libcommon.HexToHash("https://testnet.bscscan.com/tx/0x5ebb92a3a3660c18655a29be937ac2704b807545996672836ea907e2685bc8fc"), + Bloom: types.Bloom{}, + Difficulty: new(big.Int).SetUint64(2), + Number: new(big.Int).SetUint64(1), + GasLimit: 69998932, + GasUsed: 998363, + Time: 1715485382, + Extra: make([]byte, 64), + MixDigest: libcommon.Hash{}, + Nonce: types.BlockNonce{}, + BaseFee: new(big.Int).SetUint64(0), + WithdrawalsHash: &withdrawalsHash, + BlobGasUsed: &blobGasUsed, + ExcessBlobGas: &excessBlobGas, + } + + tests := []struct { + msg NewBlockPacket + }{ + {msg: NewBlockPacket{ + Block: types.NewBlockWithHeader(header), + TD: new(big.Int).SetUint64(1), + }}, + {msg: NewBlockPacket{ + Block: types.NewBlock(header, []types.Transaction{dynamicTx}, nil, nil, types.Withdrawals{}), + TD: new(big.Int).SetUint64(1), + }}, + {msg: NewBlockPacket{ + Block: types.NewBlock(header, []types.Transaction{dynamicTx, blobTx}, nil, nil, types.Withdrawals{}), + TD: new(big.Int).SetUint64(1), + Sidecars: types.BlobSidecars{&types.BlobSidecar{ + BlobTxSidecar: txSidecar, + BlockNumber: new(big.Int).SetUint64(1), + BlockHash: libcommon.Hash{}, + TxIndex: 1, + TxHash: libcommon.Hash{}, + }}, + }}, + } + + for _, item := range tests { + item.msg.Block.Size() + enc, err := rlp.EncodeToBytes(item.msg) + require.NoError(t, err) + var actual NewBlockPacket + err = rlp.DecodeBytes(enc, &actual) + require.NoError(t, err) + require.Equal(t, item.msg, actual) + } +}