mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
refactor: removing redundant codes in htrutils.go (#15453)
* refactor: use auto-generated HashTreeRoot functions in htrutil.go * refactor: use type alias for Transaction & use SliceRoot for TransactionsRoot * changelog * fix: TransactionsRoot receives raw 2d bytes as an argument * fix: handle nil argument * test: add nil test for fork and checkpoint --------- Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
3
changelog/syjn99_refactor-htrutil.md
Normal file
3
changelog/syjn99_refactor-htrutil.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Refactor `htrutil.go` by removing redundant codes.
|
||||
@@ -11,6 +11,12 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Transaction []byte
|
||||
|
||||
func (t Transaction) HashTreeRoot() ([32]byte, error) {
|
||||
return ByteSliceRoot(t, fieldparams.MaxBytesPerTxLength)
|
||||
}
|
||||
|
||||
// Uint64Root computes the HashTreeRoot Merkleization of
|
||||
// a simple uint64 value according to the Ethereum
|
||||
// Simple Serialize specification.
|
||||
@@ -21,33 +27,22 @@ func Uint64Root(val uint64) [32]byte {
|
||||
return root
|
||||
}
|
||||
|
||||
// ForkRoot computes the HashTreeRoot Merkleization of
|
||||
// a Fork struct value according to the Ethereum
|
||||
// Simple Serialize specification.
|
||||
// ForkRoot computes the HashTreeRoot Merkleization of Fork
|
||||
func ForkRoot(fork *ethpb.Fork) ([32]byte, error) {
|
||||
if fork == nil {
|
||||
fieldRoots := make([][32]byte, 3)
|
||||
if fork != nil {
|
||||
fieldRoots[0] = bytesutil.ToBytes32(fork.PreviousVersion)
|
||||
fieldRoots[1] = bytesutil.ToBytes32(fork.CurrentVersion)
|
||||
forkEpochBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(forkEpochBuf, uint64(fork.Epoch))
|
||||
fieldRoots[2] = bytesutil.ToBytes32(forkEpochBuf)
|
||||
}
|
||||
return BitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
}
|
||||
return fork.HashTreeRoot()
|
||||
}
|
||||
|
||||
// CheckpointRoot computes the HashTreeRoot Merkleization of
|
||||
// a InitWithReset struct value according to the Ethereum
|
||||
// Simple Serialize specification.
|
||||
// CheckpointRoot computes the HashTreeRoot Merkleization of Checkpoint
|
||||
func CheckpointRoot(checkpoint *ethpb.Checkpoint) ([32]byte, error) {
|
||||
if checkpoint == nil {
|
||||
fieldRoots := make([][32]byte, 2)
|
||||
if checkpoint != nil {
|
||||
epochBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(epochBuf, uint64(checkpoint.Epoch))
|
||||
fieldRoots[0] = bytesutil.ToBytes32(epochBuf)
|
||||
fieldRoots[1] = bytesutil.ToBytes32(checkpoint.Root)
|
||||
}
|
||||
return BitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
}
|
||||
return checkpoint.HashTreeRoot()
|
||||
}
|
||||
|
||||
// ByteArrayRootWithLimit computes the HashTreeRoot Merkleization of
|
||||
@@ -91,54 +86,18 @@ func SlashingsRoot(slashings []uint64) ([32]byte, error) {
|
||||
}
|
||||
|
||||
// TransactionsRoot computes the HTR for the Transactions' property of the ExecutionPayload
|
||||
// The code was largely copy/pasted from the code generated to compute the HTR of the entire
|
||||
// ExecutionPayload.
|
||||
func TransactionsRoot(txs [][]byte) ([32]byte, error) {
|
||||
txRoots := make([][32]byte, 0)
|
||||
for i := 0; i < len(txs); i++ {
|
||||
rt, err := ByteSliceRoot(txs[i], fieldparams.MaxBytesPerTxLength) // getting the transaction root here
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
transactions := make([]Transaction, len(txs))
|
||||
for i, tx := range txs {
|
||||
transactions[i] = Transaction(tx)
|
||||
}
|
||||
txRoots = append(txRoots, rt)
|
||||
}
|
||||
|
||||
bytesRoot, err := BitwiseMerkleize(txRoots, uint64(len(txRoots)), fieldparams.MaxTxsPerPayloadLength)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute merkleization")
|
||||
}
|
||||
bytesRootBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(bytesRootBuf, binary.LittleEndian, uint64(len(txs))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal length")
|
||||
}
|
||||
bytesRootBufRoot := make([]byte, 32)
|
||||
copy(bytesRootBufRoot, bytesRootBuf.Bytes())
|
||||
return MixInLength(bytesRoot, bytesRootBufRoot), nil
|
||||
return SliceRoot(transactions, fieldparams.MaxTxsPerPayloadLength)
|
||||
}
|
||||
|
||||
// WithdrawalSliceRoot computes the HTR of a slice of withdrawals.
|
||||
// The limit parameter is used as input to the bitwise merkleization algorithm.
|
||||
func WithdrawalSliceRoot(withdrawals []*enginev1.Withdrawal, limit uint64) ([32]byte, error) {
|
||||
roots := make([][32]byte, len(withdrawals))
|
||||
for i := 0; i < len(withdrawals); i++ {
|
||||
r, err := withdrawalRoot(withdrawals[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
roots[i] = r
|
||||
}
|
||||
|
||||
bytesRoot, err := BitwiseMerkleize(roots, uint64(len(roots)), limit)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute merkleization")
|
||||
}
|
||||
bytesRootBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(bytesRootBuf, binary.LittleEndian, uint64(len(withdrawals))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal length")
|
||||
}
|
||||
bytesRootBufRoot := make([]byte, 32)
|
||||
copy(bytesRootBufRoot, bytesRootBuf.Bytes())
|
||||
return MixInLength(bytesRoot, bytesRootBufRoot), nil
|
||||
return SliceRoot(withdrawals, limit)
|
||||
}
|
||||
|
||||
// DepositRequestsSliceRoot computes the HTR of a slice of deposit requests.
|
||||
@@ -176,14 +135,9 @@ func ByteSliceRoot(slice []byte, maxLength uint64) ([32]byte, error) {
|
||||
}
|
||||
|
||||
func withdrawalRoot(w *enginev1.Withdrawal) ([32]byte, error) {
|
||||
if w == nil {
|
||||
fieldRoots := make([][32]byte, 4)
|
||||
if w != nil {
|
||||
binary.LittleEndian.PutUint64(fieldRoots[0][:], w.Index)
|
||||
|
||||
binary.LittleEndian.PutUint64(fieldRoots[1][:], uint64(w.ValidatorIndex))
|
||||
|
||||
fieldRoots[2] = bytesutil.ToBytes32(w.Address)
|
||||
binary.LittleEndian.PutUint64(fieldRoots[3][:], w.Amount)
|
||||
}
|
||||
return BitwiseMerkleize(fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
|
||||
}
|
||||
return w.HashTreeRoot()
|
||||
}
|
||||
|
||||
@@ -22,28 +22,62 @@ func TestUint64Root(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestForkRoot(t *testing.T) {
|
||||
testFork := ethpb.Fork{
|
||||
PreviousVersion: []byte{123},
|
||||
CurrentVersion: []byte{124},
|
||||
tests := []struct {
|
||||
name string
|
||||
fork *ethpb.Fork
|
||||
expected [32]byte
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
fork: nil,
|
||||
expected: [32]byte{219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113},
|
||||
},
|
||||
{
|
||||
name: "valid fork",
|
||||
fork: ðpb.Fork{
|
||||
PreviousVersion: []byte{123, 0, 0, 0},
|
||||
CurrentVersion: []byte{124, 0, 0, 0},
|
||||
Epoch: 1234567890,
|
||||
},
|
||||
expected: [32]byte{19, 46, 77, 103, 92, 175, 247, 33, 100, 64, 17, 111, 199, 145, 69, 38, 217, 112, 6, 16, 149, 201, 225, 144, 192, 228, 197, 172, 157, 78, 114, 140},
|
||||
},
|
||||
}
|
||||
expected := [32]byte{19, 46, 77, 103, 92, 175, 247, 33, 100, 64, 17, 111, 199, 145, 69, 38, 217, 112, 6, 16, 149, 201, 225, 144, 192, 228, 197, 172, 157, 78, 114, 140}
|
||||
|
||||
result, err := ssz.ForkRoot(&testFork)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := ssz.ForkRoot(tt.fork)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckPointRoot(t *testing.T) {
|
||||
testCheckpoint := ethpb.Checkpoint{
|
||||
tests := []struct {
|
||||
name string
|
||||
checkpoint *ethpb.Checkpoint
|
||||
expected [32]byte
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
checkpoint: nil,
|
||||
expected: [32]byte{245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75},
|
||||
},
|
||||
{
|
||||
name: "valid checkpoint",
|
||||
checkpoint: ðpb.Checkpoint{
|
||||
Epoch: 1234567890,
|
||||
Root: []byte{222},
|
||||
Root: []byte{222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
expected: [32]byte{228, 65, 39, 109, 183, 249, 167, 232, 125, 239, 25, 155, 207, 4, 84, 174, 176, 229, 175, 224, 62, 33, 215, 254, 170, 220, 132, 65, 246, 128, 68, 194},
|
||||
},
|
||||
}
|
||||
expected := [32]byte{228, 65, 39, 109, 183, 249, 167, 232, 125, 239, 25, 155, 207, 4, 84, 174, 176, 229, 175, 224, 62, 33, 215, 254, 170, 220, 132, 65, 246, 128, 68, 194}
|
||||
|
||||
result, err := ssz.CheckpointRoot(&testCheckpoint)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := ssz.CheckpointRoot(tt.checkpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteArrayRootWithLimit(t *testing.T) {
|
||||
@@ -219,7 +253,7 @@ func TestWithdrawalRoot(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
input: &enginev1.Withdrawal{},
|
||||
input: nil,
|
||||
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},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user