prysm-pulse/shared/trieutil/deposit_trie.go
Raul Jordan 5dc5f1d1c8 Update Contract to Use Little Endian And Encoding Across Entire Repo (#1536)
* using little endian and tests for encoding dep inputs

* use decode value and timestamp method in state

* updated comments to match serialization format

* latest compiled contract, abi, bytecode, and bindings

* to little endian everywhere

* fix all tests except for contract tests

* include contract changes

* address broken build

* compile with vyper v8

* update readme

* fix pkg name

* add skip chainstart delay

* skip chainstart delay tests pass

* to little endian timestamp
2019-02-12 09:27:00 +05:30

126 lines
3.1 KiB
Go

// Package trieutil contains definitions for building a Merkle trie for validator deposits
// as defined in the Ethereum Serenity specification, as well as utilities to generate
// and verify Merkle proofs.
package trieutil
import (
"encoding/binary"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// DepositTrie represents a Merkle trie tracking deposits on the ETH 1.0
// PoW chain contract created in Vyper.
type DepositTrie struct {
depositCount uint64
branch [32][32]byte
zeroHashes [32][32]byte
}
// NewDepositTrie creates a new struct instance representing a Merkle trie for deposits
// and tracking an initial deposit count of 0.
func NewDepositTrie() *DepositTrie {
var zeroHashes [32][32]byte
var branch [32][32]byte
zeroHashes[0] = params.BeaconConfig().ZeroHash
branch[0] = params.BeaconConfig().ZeroHash
for i := 0; i < 31; i++ {
zeroHashes[i+1] = hashutil.Hash(append(zeroHashes[i][:], zeroHashes[i][:]...))
branch[i+1] = zeroHashes[i+1]
}
return &DepositTrie{
depositCount: 0,
zeroHashes: zeroHashes,
branch: branch,
}
}
// UpdateDepositTrie updates the Merkle trie representing deposits on
// the ETH 1.0 PoW chain contract.
func (d *DepositTrie) UpdateDepositTrie(depositData []byte) {
index := d.depositCount
i := 0
powerOf2 := uint64(2)
for j := 0; j < 32; j++ {
if (index+1)%powerOf2 != 0 {
break
}
i++
powerOf2 *= 2
}
hashedData := hashutil.Hash(depositData)
for k := 0; k < 32; k++ {
if k < i {
hashedData = hashutil.Hash(append(d.branch[k][:], hashedData[:]...))
}
}
d.branch[i] = hashedData
d.depositCount++
}
// Root returns the Merkle root of the calculated deposit trie.
func (d *DepositTrie) Root() [32]byte {
root := params.BeaconConfig().ZeroHash
size := d.depositCount
for i := 0; i < 32; i++ {
if size%2 == 1 {
root = hashutil.Hash(append(d.branch[i][:], root[:]...))
} else {
root = hashutil.Hash(append(root[:], d.zeroHashes[i][:]...))
}
size /= 2
}
return root
}
// Branch returns the merkle branch of the left most leaf of the trie.
func (d *DepositTrie) Branch() [][]byte {
nBranch := make([][]byte, 32)
for i := range nBranch {
nBranch[i] = d.branch[i][:]
}
return nBranch
}
// VerifyMerkleBranch verifies a Merkle path in a trie
// by checking the aggregated hash of contiguous leaves along a path
// eventually equals the root hash of the Merkle trie.
func VerifyMerkleBranch(branch [][]byte, root [32]byte, merkleTreeIndex []byte) bool {
computedRoot := params.BeaconConfig().ZeroHash
index := binary.LittleEndian.Uint64(merkleTreeIndex)
size := index + 1
zHashes := zeroHashes()
for i := 0; i < 32; i++ {
if size%2 == 1 {
computedRoot = hashutil.Hash(append(branch[i][:], computedRoot[:]...))
} else {
computedRoot = hashutil.Hash(append(computedRoot[:], zHashes[i][:]...))
}
size /= 2
}
return computedRoot == root
}
func zeroHashes() [32][32]byte {
var zeroHashes [32][32]byte
zeroHashes[0] = params.BeaconConfig().ZeroHash
for i := 0; i < 31; i++ {
zeroHashes[i+1] = hashutil.Hash(append(zeroHashes[i][:], zeroHashes[i][:]...))
}
return zeroHashes
}