-
Notifications
You must be signed in to change notification settings - Fork 0
/
row_proof.go
75 lines (67 loc) · 2.25 KB
/
row_proof.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package celestia_da_light_client
import (
"errors"
"fmt"
"github.com/cometbft/cometbft/crypto/merkle"
tmbytes "github.com/cometbft/cometbft/libs/bytes"
)
// RowProof is a Merkle proof that a set of rows exist in a Merkle tree with a
// given data root.
type rowProof struct {
// RowRoots are the roots of the rows being proven.
RowRoots []tmbytes.HexBytes `json:"row_roots"`
// Proofs is a list of Merkle proofs where each proof proves that a row
// exists in a Merkle tree with a given data root.
Proofs []*merkle.Proof `json:"proofs"`
StartRow uint32 `json:"start_row"`
EndRow uint32 `json:"end_row"`
}
// Validate performs checks on the fields of this RowProof. Returns an error if
// the proof fails validation. If the proof passes validation, this function
// attempts to verify the proof. It returns nil if the proof is valid.
func (rp rowProof) Validate(root []byte) error {
// HACKHACK performing subtraction with unsigned integers is unsafe.
if int(rp.EndRow-rp.StartRow+1) != len(rp.RowRoots) {
return fmt.Errorf("the number of rows %d must equal the number of row roots %d", int(rp.EndRow-rp.StartRow+1), len(rp.RowRoots))
}
if len(rp.Proofs) != len(rp.RowRoots) {
return fmt.Errorf("the number of proofs %d must equal the number of row roots %d", len(rp.Proofs), len(rp.RowRoots))
}
if !rp.VerifyProof(root) {
return errors.New("row proof failed to verify")
}
return nil
}
// VerifyProof verifies that all the row roots in this RowProof exist in a
// Merkle tree with the given root. Returns true if all proofs are valid.
func (rp rowProof) VerifyProof(root []byte) bool {
for i, proof := range rp.Proofs {
err := proof.Verify(root, rp.RowRoots[i])
if err != nil {
return false
}
}
return true
}
func rowProofFromProto(p *RowProof) rowProof {
if p == nil {
return rowProof{}
}
rowRoots := make([]tmbytes.HexBytes, len(p.RowRoots))
rowProofs := make([]*merkle.Proof, len(p.Proofs))
for i := range p.Proofs {
rowRoots[i] = p.RowRoots[i]
rowProofs[i] = &merkle.Proof{
Total: p.Proofs[i].Total,
Index: p.Proofs[i].Index,
LeafHash: p.Proofs[i].LeafHash,
Aunts: p.Proofs[i].Aunts,
}
}
return rowProof{
RowRoots: rowRoots,
Proofs: rowProofs,
StartRow: p.StartRow,
EndRow: p.EndRow,
}
}