mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Merkle Proof Support for BeaconState Finalized Root and Sync Committees (#10029)
This commit is contained in:
@@ -180,8 +180,8 @@ func (m *SparseMerkleTrie) ToProto() *protodb.SparseMerkleTrie {
|
||||
return trie
|
||||
}
|
||||
|
||||
// VerifyMerkleBranch verifies a Merkle branch against a root of a trie.
|
||||
func VerifyMerkleBranch(root, item []byte, merkleIndex int, proof [][]byte, depth uint64) bool {
|
||||
// VerifyMerkleProofWithDepth verifies a Merkle branch against a root of a trie.
|
||||
func VerifyMerkleProofWithDepth(root, item []byte, merkleIndex int, proof [][]byte, depth uint64) bool {
|
||||
if len(proof) != int(depth)+1 {
|
||||
return false
|
||||
}
|
||||
@@ -197,6 +197,20 @@ func VerifyMerkleBranch(root, item []byte, merkleIndex int, proof [][]byte, dept
|
||||
return bytes.Equal(root, node[:])
|
||||
}
|
||||
|
||||
// VerifyMerkleProof given a trie root, a leaf, the generalized merkle index
|
||||
// of the leaf in the trie, and the proof itself.
|
||||
func VerifyMerkleProof(root, item []byte, merkleIndex uint64, proof [][]byte) bool {
|
||||
node := bytesutil.ToBytes32(item)
|
||||
for i := 0; i < len(proof); i++ {
|
||||
if (merkleIndex / math.PowerOf2(uint64(i)) % 2) != 0 {
|
||||
node = hash.Hash(append(proof[i], node[:]...))
|
||||
} else {
|
||||
node = hash.Hash(append(node[:], proof[i]...))
|
||||
}
|
||||
}
|
||||
return bytes.Equal(root, node[:])
|
||||
}
|
||||
|
||||
// Copy performs a deep copy of the trie.
|
||||
func (m *SparseMerkleTrie) Copy() *SparseMerkleTrie {
|
||||
dstBranches := make([][][]byte, len(m.branches))
|
||||
|
||||
@@ -87,6 +87,32 @@ func TestGenerateTrieFromItems_NoItemsProvided(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMerkleTrie_VerifyMerkleProofWithDepth(t *testing.T) {
|
||||
items := [][]byte{
|
||||
[]byte("A"),
|
||||
[]byte("B"),
|
||||
[]byte("C"),
|
||||
[]byte("D"),
|
||||
[]byte("E"),
|
||||
[]byte("F"),
|
||||
[]byte("G"),
|
||||
[]byte("H"),
|
||||
}
|
||||
m, err := trie.GenerateTrieFromItems(items, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err)
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int(params.BeaconConfig().DepositContractTreeDepth)+1, len(proof))
|
||||
root := m.HashTreeRoot()
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], items[0], 0, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
t.Error("First Merkle proof did not verify")
|
||||
}
|
||||
proof, err = m.MerkleProof(3)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, trie.VerifyMerkleProofWithDepth(root[:], items[3], 3, proof, params.BeaconConfig().DepositContractTreeDepth))
|
||||
require.Equal(t, false, trie.VerifyMerkleProofWithDepth(root[:], []byte("buzz"), 3, proof, params.BeaconConfig().DepositContractTreeDepth))
|
||||
}
|
||||
|
||||
func TestMerkleTrie_VerifyMerkleProof(t *testing.T) {
|
||||
items := [][]byte{
|
||||
[]byte("A"),
|
||||
@@ -104,13 +130,13 @@ func TestMerkleTrie_VerifyMerkleProof(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int(params.BeaconConfig().DepositContractTreeDepth)+1, len(proof))
|
||||
root := m.HashTreeRoot()
|
||||
if ok := trie.VerifyMerkleBranch(root[:], items[0], 0, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
if ok := trie.VerifyMerkleProof(root[:], items[0], 0, proof); !ok {
|
||||
t.Error("First Merkle proof did not verify")
|
||||
}
|
||||
proof, err = m.MerkleProof(3)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, trie.VerifyMerkleBranch(root[:], items[3], 3, proof, params.BeaconConfig().DepositContractTreeDepth))
|
||||
require.Equal(t, false, trie.VerifyMerkleBranch(root[:], []byte("buzz"), 3, proof, params.BeaconConfig().DepositContractTreeDepth))
|
||||
require.Equal(t, true, trie.VerifyMerkleProof(root[:], items[3], 3, proof))
|
||||
require.Equal(t, false, trie.VerifyMerkleProof(root[:], []byte("buzz"), 3, proof))
|
||||
}
|
||||
|
||||
func TestMerkleTrie_NegativeIndexes(t *testing.T) {
|
||||
@@ -144,17 +170,17 @@ func TestMerkleTrie_VerifyMerkleProof_TrieUpdated(t *testing.T) {
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
root := m.HashTreeRoot()
|
||||
require.Equal(t, true, trie.VerifyMerkleBranch(root[:], items[0], 0, proof, depth))
|
||||
require.Equal(t, true, trie.VerifyMerkleProofWithDepth(root[:], items[0], 0, proof, depth))
|
||||
|
||||
// Now we update the trie.
|
||||
assert.NoError(t, m.Insert([]byte{5}, 3))
|
||||
proof, err = m.MerkleProof(3)
|
||||
require.NoError(t, err)
|
||||
root = m.HashTreeRoot()
|
||||
if ok := trie.VerifyMerkleBranch(root[:], []byte{5}, 3, proof, depth); !ok {
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], []byte{5}, 3, proof, depth); !ok {
|
||||
t.Error("Second Merkle proof did not verify")
|
||||
}
|
||||
if ok := trie.VerifyMerkleBranch(root[:], []byte{4}, 3, proof, depth); ok {
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], []byte{4}, 3, proof, depth); ok {
|
||||
t.Error("Old item should not verify")
|
||||
}
|
||||
|
||||
@@ -253,7 +279,7 @@ func BenchmarkGenerateProof(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerifyMerkleBranch(b *testing.B) {
|
||||
func BenchmarkVerifyMerkleProofWithDepth(b *testing.B) {
|
||||
b.StopTimer()
|
||||
items := [][]byte{
|
||||
[]byte("A"),
|
||||
@@ -272,7 +298,7 @@ func BenchmarkVerifyMerkleBranch(b *testing.B) {
|
||||
root := m.HashTreeRoot()
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if ok := trie.VerifyMerkleBranch(root[:], items[2], 2, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], items[2], 2, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
b.Error("Merkle proof did not verify")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user