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 a3f23822a8..0000000000 Binary files a/core/types/testdata/22615532_block_access_list_with_reads_eip7928.ssz and /dev/null differ