github.com/prysmaticlabs/prysm@v1.4.4/shared/htrutils/htrutils.go (about) 1 // Package htrutils defines HashTreeRoot utility functions. 2 package htrutils 3 4 import ( 5 "bytes" 6 "encoding/binary" 7 8 "github.com/pkg/errors" 9 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 10 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 11 "github.com/prysmaticlabs/prysm/shared/bytesutil" 12 "github.com/prysmaticlabs/prysm/shared/hashutil" 13 "github.com/prysmaticlabs/prysm/shared/params" 14 ) 15 16 // Uint64Root computes the HashTreeRoot Merkleization of 17 // a simple uint64 value according to the Ethereum 18 // Simple Serialize specification. 19 func Uint64Root(val uint64) [32]byte { 20 buf := make([]byte, 8) 21 binary.LittleEndian.PutUint64(buf, val) 22 root := bytesutil.ToBytes32(buf) 23 return root 24 } 25 26 // ForkRoot computes the HashTreeRoot Merkleization of 27 // a Fork struct value according to the Ethereum 28 // Simple Serialize specification. 29 func ForkRoot(fork *pb.Fork) ([32]byte, error) { 30 fieldRoots := make([][]byte, 3) 31 if fork != nil { 32 prevRoot := bytesutil.ToBytes32(fork.PreviousVersion) 33 fieldRoots[0] = prevRoot[:] 34 currRoot := bytesutil.ToBytes32(fork.CurrentVersion) 35 fieldRoots[1] = currRoot[:] 36 forkEpochBuf := make([]byte, 8) 37 binary.LittleEndian.PutUint64(forkEpochBuf, uint64(fork.Epoch)) 38 epochRoot := bytesutil.ToBytes32(forkEpochBuf) 39 fieldRoots[2] = epochRoot[:] 40 } 41 return BitwiseMerkleize(hashutil.CustomSHA256Hasher(), fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) 42 } 43 44 // CheckpointRoot computes the HashTreeRoot Merkleization of 45 // a InitWithReset struct value according to the Ethereum 46 // Simple Serialize specification. 47 func CheckpointRoot(hasher HashFn, checkpoint *ethpb.Checkpoint) ([32]byte, error) { 48 fieldRoots := make([][]byte, 2) 49 if checkpoint != nil { 50 epochBuf := make([]byte, 8) 51 binary.LittleEndian.PutUint64(epochBuf, uint64(checkpoint.Epoch)) 52 epochRoot := bytesutil.ToBytes32(epochBuf) 53 fieldRoots[0] = epochRoot[:] 54 ckpRoot := bytesutil.ToBytes32(checkpoint.Root) 55 fieldRoots[1] = ckpRoot[:] 56 } 57 return BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots))) 58 } 59 60 // HistoricalRootsRoot computes the HashTreeRoot Merkleization of 61 // a list of [32]byte historical block roots according to the Ethereum 62 // Simple Serialize specification. 63 func HistoricalRootsRoot(historicalRoots [][]byte) ([32]byte, error) { 64 result, err := BitwiseMerkleize(hashutil.CustomSHA256Hasher(), historicalRoots, uint64(len(historicalRoots)), params.BeaconConfig().HistoricalRootsLimit) 65 if err != nil { 66 return [32]byte{}, errors.Wrap(err, "could not compute historical roots merkleization") 67 } 68 historicalRootsBuf := new(bytes.Buffer) 69 if err := binary.Write(historicalRootsBuf, binary.LittleEndian, uint64(len(historicalRoots))); err != nil { 70 return [32]byte{}, errors.Wrap(err, "could not marshal historical roots length") 71 } 72 // We need to mix in the length of the slice. 73 historicalRootsOutput := make([]byte, 32) 74 copy(historicalRootsOutput, historicalRootsBuf.Bytes()) 75 mixedLen := MixInLength(result, historicalRootsOutput) 76 return mixedLen, nil 77 } 78 79 // SlashingsRoot computes the HashTreeRoot Merkleization of 80 // a list of uint64 slashing values according to the Ethereum 81 // Simple Serialize specification. 82 func SlashingsRoot(slashings []uint64) ([32]byte, error) { 83 slashingMarshaling := make([][]byte, params.BeaconConfig().EpochsPerSlashingsVector) 84 for i := 0; i < len(slashings) && i < len(slashingMarshaling); i++ { 85 slashBuf := make([]byte, 8) 86 binary.LittleEndian.PutUint64(slashBuf, slashings[i]) 87 slashingMarshaling[i] = slashBuf 88 } 89 slashingChunks, err := Pack(slashingMarshaling) 90 if err != nil { 91 return [32]byte{}, errors.Wrap(err, "could not pack slashings into chunks") 92 } 93 return BitwiseMerkleize(hashutil.CustomSHA256Hasher(), slashingChunks, uint64(len(slashingChunks)), uint64(len(slashingChunks))) 94 }