diff --git a/encoding/ssz/BUILD.bazel b/encoding/ssz/BUILD.bazel index e178d785ac..5463e11ec5 100644 --- a/encoding/ssz/BUILD.bazel +++ b/encoding/ssz/BUILD.bazel @@ -29,18 +29,18 @@ go_test( name = "go_default_test", size = "small", srcs = [ + "export_test.go", "hashers_test.go", "helpers_test.go", "htrutils_fuzz_test.go", "htrutils_test.go", "merkleize_test.go", ], + embed = [":go_default_library"], deps = [ - ":go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//crypto/hash:go_default_library", - "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/encoding/ssz/export_test.go b/encoding/ssz/export_test.go new file mode 100644 index 0000000000..f066be0bb5 --- /dev/null +++ b/encoding/ssz/export_test.go @@ -0,0 +1,3 @@ +package ssz + +var WithdrawalRoot = withdrawalRoot diff --git a/encoding/ssz/htrutils.go b/encoding/ssz/htrutils.go index 17089b8295..49f5d20f41 100644 --- a/encoding/ssz/htrutils.go +++ b/encoding/ssz/htrutils.go @@ -165,15 +165,14 @@ func transactionRoot(tx []byte) ([32]byte, error) { } func withdrawalRoot(hasher HashFn, w *enginev1.Withdrawal) ([32]byte, error) { - fieldRoots := make([][32]byte, 3) + fieldRoots := make([][32]byte, 4) if w != nil { - indexBuf := make([]byte, 32) - binary.LittleEndian.PutUint64(indexBuf, w.WithdrawalIndex) - fieldRoots[0] = bytesutil.ToBytes32(indexBuf) - fieldRoots[1] = bytesutil.ToBytes32(w.ExecutionAddress) - amountBuf := make([]byte, 8) - binary.LittleEndian.PutUint64(amountBuf, w.Amount) - fieldRoots[2] = bytesutil.ToBytes32(amountBuf) + binary.LittleEndian.PutUint64(fieldRoots[0][:], w.WithdrawalIndex) + + binary.LittleEndian.PutUint64(fieldRoots[1][:], uint64(w.ValidatorIndex)) + + fieldRoots[2] = bytesutil.ToBytes32(w.ExecutionAddress) + binary.LittleEndian.PutUint64(fieldRoots[3][:], w.Amount) } return BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) } diff --git a/encoding/ssz/htrutils_test.go b/encoding/ssz/htrutils_test.go index 8daad3e89f..eeca0b730f 100644 --- a/encoding/ssz/htrutils_test.go +++ b/encoding/ssz/htrutils_test.go @@ -2,12 +2,10 @@ package ssz_test import ( "reflect" - "strconv" "testing" fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/crypto/hash" - "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v3/encoding/ssz" enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" @@ -126,78 +124,6 @@ func TestTransactionsRoot(t *testing.T) { } } -func TestWithdrawalQueueRoot(t *testing.T) { - const limit = 16 - tests := []struct { - name string - ws []*enginev1.Withdrawal - want [32]byte - wantErr bool - }{ - { - name: "nil", - ws: nil, - want: [32]byte{121, 41, 48, 187, 213, 186, 172, 67, 188, 199, 152, 238, 73, 170, 129, 133, 239, 118, 187, 59, 68, 186, 98, 185, 29, 134, 174, 86, 158, 75, 181, 53}, - }, - { - name: "empty", - ws: []*enginev1.Withdrawal{}, - want: [32]byte{121, 41, 48, 187, 213, 186, 172, 67, 188, 199, 152, 238, 73, 170, 129, 133, 239, 118, 187, 59, 68, 186, 98, 185, 29, 134, 174, 86, 158, 75, 181, 53}, - }, - { - name: "one", - ws: []*enginev1.Withdrawal{{ - WithdrawalIndex: 123, - ExecutionAddress: bytesutil.PadTo([]byte("address"), 20), - Amount: 123, - }}, - want: [32]byte{242, 16, 137, 49, 219, 35, 236, 39, 191, 96, 52, 104, 35, 98, 250, 177, 189, 65, 113, 185, 51, 107, 115, 26, 229, 168, 40, 189, 200, 152, 225, 24}, - }, - { - name: "max withdrawals", - ws: func() []*enginev1.Withdrawal { - var ws []*enginev1.Withdrawal - for i := 0; i < limit; i++ { - ws = append(ws, &enginev1.Withdrawal{ - WithdrawalIndex: uint64(i), - ExecutionAddress: bytesutil.PadTo([]byte("address"+strconv.Itoa(i)), 20), - Amount: uint64(i), - }) - } - return ws - }(), - want: [32]byte{252, 43, 118, 69, 222, 73, 222, 196, 52, 234, 247, 49, 98, 54, 19, 146, 204, 246, 12, 139, 179, 167, 117, 216, 77, 159, 84, 154, 9, 103, 28, 226}, - }, - { - name: "exceed max withdrawals", - ws: func() []*enginev1.Withdrawal { - var ws []*enginev1.Withdrawal - for i := 0; i < limit+1; i++ { - ws = append(ws, &enginev1.Withdrawal{ - WithdrawalIndex: uint64(i), - ExecutionAddress: bytesutil.PadTo([]byte("address"+strconv.Itoa(i)), 20), - Amount: uint64(i), - }) - } - return ws - }(), - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), tt.ws, limit) - if (err != nil) != tt.wantErr { - t.Errorf("error = %v, wantErr = %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("got = %v, want %v", got, tt.want) - } - }) - } -} - func TestPackByChunk_SingleList(t *testing.T) { tests := []struct { name string @@ -233,3 +159,75 @@ func TestPackByChunk_SingleList(t *testing.T) { }) } } + +func TestWithdrawalRoot(t *testing.T) { + tests := []struct { + name string + input *enginev1.Withdrawal + want [32]byte + }{ + { + name: "nil", + input: &enginev1.Withdrawal{}, + want: [32]byte{0xdb, 0x56, 0x11, 0x4e, 0x0, 0xfd, 0xd4, 0xc1, 0xf8, 0x5c, 0x89, 0x2b, 0xf3, 0x5a, 0xc9, 0xa8, 0x92, 0x89, 0xaa, 0xec, 0xb1, 0xeb, 0xd0, 0xa9, 0x6c, 0xde, 0x60, 0x6a, 0x74, 0x8b, 0x5d, 0x71}, + }, + { + name: "empty", + input: &enginev1.Withdrawal{ + ExecutionAddress: make([]byte, 20), + }, + want: [32]byte{0xdb, 0x56, 0x11, 0x4e, 0x0, 0xfd, 0xd4, 0xc1, 0xf8, 0x5c, 0x89, 0x2b, 0xf3, 0x5a, 0xc9, 0xa8, 0x92, 0x89, 0xaa, 0xec, 0xb1, 0xeb, 0xd0, 0xa9, 0x6c, 0xde, 0x60, 0x6a, 0x74, 0x8b, 0x5d, 0x71}, + }, + { + name: "non-empty", + input: &enginev1.Withdrawal{ + WithdrawalIndex: 123, + ValidatorIndex: 123123, + ExecutionAddress: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + Amount: 50, + }, + want: [32]byte{0x4f, 0xca, 0x3a, 0x43, 0x6e, 0xcc, 0x34, 0xad, 0x33, 0xde, 0x3c, 0x22, 0xa3, 0x32, 0x27, 0xa, 0x8c, 0x4e, 0x75, 0xd8, 0x39, 0xc1, 0xd7, 0x55, 0x78, 0x77, 0xd7, 0x14, 0x6b, 0x34, 0x6a, 0xb6}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hasher := hash.CustomSHA256Hasher() + got, err := ssz.WithdrawalRoot(hasher, tt.input) + require.NoError(t, err) + require.DeepSSZEqual(t, tt.want, got) + }) + } +} + +func TestWithrawalSliceRoot(t *testing.T) { + tests := []struct { + name string + input []*enginev1.Withdrawal + want [32]byte + }{ + { + name: "empty", + input: make([]*enginev1.Withdrawal, 0), + want: [32]byte{0x79, 0x29, 0x30, 0xbb, 0xd5, 0xba, 0xac, 0x43, 0xbc, 0xc7, 0x98, 0xee, 0x49, 0xaa, 0x81, 0x85, 0xef, 0x76, 0xbb, 0x3b, 0x44, 0xba, 0x62, 0xb9, 0x1d, 0x86, 0xae, 0x56, 0x9e, 0x4b, 0xb5, 0x35}, + }, + { + name: "non-empty", + input: []*enginev1.Withdrawal{&enginev1.Withdrawal{ + WithdrawalIndex: 123, + ValidatorIndex: 123123, + ExecutionAddress: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + Amount: 50, + }, + }, + want: [32]byte{0x10, 0x34, 0x29, 0xd1, 0x34, 0x30, 0xa0, 0x1c, 0x4, 0xdd, 0x3, 0xed, 0xe6, 0xa6, 0x33, 0xb2, 0xc9, 0x24, 0x23, 0x5c, 0x43, 0xca, 0xb2, 0x32, 0xaa, 0xed, 0xfe, 0xd5, 0x9, 0x78, 0xd1, 0x6f}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hasher := hash.CustomSHA256Hasher() + got, err := ssz.WithdrawalSliceRoot(hasher, tt.input, 16) + require.NoError(t, err) + require.DeepSSZEqual(t, tt.want, got) + }) + } +}