From ef5206359b467e70c596854191a6157dd110844a Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Thu, 10 Jul 2025 11:18:41 +0800 Subject: [PATCH] core/types/bal: add EncodeFullRLP --- core/types/bal/bal_encoding.go | 21 ++++- core/types/bal/bal_test.go | 77 ++++++++++++++++++ ...2_block_access_list_with_reads_eip7928.ssz | Bin 36280 -> 0 bytes 3 files changed, 97 insertions(+), 1 deletion(-) delete mode 100644 core/types/testdata/22615532_block_access_list_with_reads_eip7928.ssz diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index c5e32dc1c3..870f33d7a7 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -221,7 +221,7 @@ func (b *BlockAccessList) EncodeRLP(wr io.Writer) error { return w.Flush() } -// DecodeRLP decodes the access list +// DecodeRLP decodes the bloc accessList. func (b *BlockAccessList) DecodeRLP(s *rlp.Stream) error { encBytes, err := s.Bytes() if err != nil { @@ -230,6 +230,25 @@ func (b *BlockAccessList) DecodeRLP(s *rlp.Stream) error { return b.decodeSSZ(encBytes) } +// EncodeFullRLP returns the RLP-encoded access list wrapped into RLP bytes. +func (b *BlockAccessList) EncodeFullRLP(wr io.Writer) error { + return b.toEncodingObj().EncodeRLP(wr) +} + +// DecodeFullRLP decodes the block accessList with full RLP format. +func (b *BlockAccessList) DecodeFullRLP(s *rlp.Stream) error { + var obj encodingBlockAccessList + if err := obj.DecodeRLP(s); err != nil { + return err + } + al, err := obj.toBlockAccessList() + if err != nil { + return err + } + *b = *al + return nil +} + var _ rlp.Encoder = &BlockAccessList{} var _ rlp.Decoder = &BlockAccessList{} diff --git a/core/types/bal/bal_test.go b/core/types/bal/bal_test.go index 585aeb845b..89dd0e3b79 100644 --- a/core/types/bal/bal_test.go +++ b/core/types/bal/bal_test.go @@ -21,6 +21,7 @@ import ( "io/fs" "os" "path/filepath" + "reflect" "testing" "github.com/ethereum/go-ethereum/common" @@ -28,6 +29,34 @@ import ( "github.com/holiman/uint256" ) +func equalBALs(a *BlockAccessList, b *BlockAccessList) bool { + if len(a.Accounts) != len(b.Accounts) { + return false + } + for addr, aaA := range a.Accounts { + aaB, ok := b.Accounts[addr] + if !ok { + return false + } + if !reflect.DeepEqual(aaA.StorageWrites, aaB.StorageWrites) { + return false + } + if !reflect.DeepEqual(aaA.StorageReads, aaB.StorageReads) { + return false + } + if !reflect.DeepEqual(aaA.BalanceChanges, aaB.BalanceChanges) { + return false + } + if !reflect.DeepEqual(aaA.NonceChanges, aaB.NonceChanges) { + return false + } + if !reflect.DeepEqual(aaA.CodeChange, aaB.CodeChange) { + return false + } + } + return true +} + func makeTestBAL() *BlockAccessList { return &BlockAccessList{ map[common.Address]*AccountAccess{ @@ -97,6 +126,29 @@ func TestBALEncoding(t *testing.T) { if dec.Hash() != bal.Hash() { t.Fatalf("encoded block hash doesn't match decoded") } + if !equalBALs(bal, &dec) { + t.Fatal("decoded BAL doesn't match") + } +} + +// TestBALEncoding tests that a populated access list can be encoded/decoded correctly. +func TestBALFullRLPEncoding(t *testing.T) { + var buf bytes.Buffer + bal := makeTestBAL() + err := bal.EncodeFullRLP(&buf) + if err != nil { + t.Fatalf("encoding failed: %v\n", err) + } + var dec BlockAccessList + if err := dec.DecodeFullRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 10000000)); err != nil { + t.Fatalf("decoding failed: %v\n", err) + } + if dec.Hash() != bal.Hash() { + t.Fatalf("encoded block hash doesn't match decoded") + } + if !equalBALs(bal, &dec) { + t.Fatal("decoded BAL doesn't match") + } } // TestBALDecoding tests that a mainnet BAL produced by https://github.com/nerolation/eth-bal-analysis @@ -120,3 +172,28 @@ func TestBALDecoding(t *testing.T) { return nil }) } + +func TestBALEncodeSizeDifference(t *testing.T) { + filepath.WalkDir("testdata/ssz", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var b BlockAccessList + if err := b.decodeSSZ(data); err != nil { + t.Fatal(err) + } + var buf bytes.Buffer + if err := b.EncodeFullRLP(&buf); err != nil { + t.Fatal(err) + } + t.Logf("SSZ: %v, RLP: %v\n", common.StorageSize(len(data)), common.StorageSize(buf.Len())) + return nil + }) +} diff --git a/core/types/testdata/22615532_block_access_list_with_reads_eip7928.ssz b/core/types/testdata/22615532_block_access_list_with_reads_eip7928.ssz deleted file mode 100644 index a3f23822a81c995a4b4679dca0bb1676d7a479e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36280 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%0DMJ%G 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