1
1
package proofs
2
2
3
- import fmt "fmt"
3
+ import (
4
+ "bytes"
5
+ "fmt"
6
+ )
4
7
5
8
// Calculate determines the root hash that matches the given proof.
6
9
// You must validate the result is what you have in a header.
@@ -10,19 +13,71 @@ func (p *ExistenceProof) Calculate() ([]byte, error) {
10
13
return nil , fmt .Errorf ("Existence Proof needs at least one step" )
11
14
}
12
15
13
- first , rem := p .Steps [0 ], p .Steps [1 :]
14
- // first step takes the key and value as input
15
- res , err := first .Apply (p .Key , p .Value )
16
+ leaf , inners := p .Steps [0 ], p .Steps [1 :]
17
+ // leaf step takes the key and value as input
18
+ res , err := leaf .Apply (p .Key , p .Value )
16
19
if err != nil {
17
20
return nil , err
18
21
}
19
22
20
23
// the rest just take the output of the last step (reducing it)
21
- for _ , step := range rem {
24
+ for _ , step := range inners {
22
25
res , err = step .Apply (res )
23
26
if err != nil {
24
27
return nil , err
25
28
}
26
29
}
27
30
return res , nil
28
31
}
32
+
33
+ func (p * ExistenceProof ) ValidSpec (spec * ProofSpec ) error {
34
+ if len (p .Steps ) == 0 {
35
+ return fmt .Errorf ("Existence Proof needs at least one step" )
36
+ }
37
+
38
+ leafOp , inners := p .Steps [0 ], p .Steps [1 :]
39
+ leaf , err := asLeaf (leafOp )
40
+ if err != nil {
41
+ return err
42
+ }
43
+ err = p .checkLeaf (leaf , spec .LeafSpec )
44
+ if err != nil {
45
+ return err
46
+ }
47
+ for _ , innerOp := range inners {
48
+ inner , err := asInner (innerOp )
49
+ if err != nil {
50
+ return err
51
+ }
52
+ if err := p .checkInner (inner , spec .LeafSpec .Prefix ); err != nil {
53
+ return err
54
+ }
55
+ }
56
+ return nil
57
+ }
58
+
59
+ func (p * ExistenceProof ) checkLeaf (leaf * LeafOp , spec * LeafOp ) error {
60
+ if leaf .Hash != spec .Hash {
61
+ return fmt .Errorf ("Unexpected HashOp: %d" , leaf .Hash )
62
+ }
63
+ if leaf .PrehashKey != spec .PrehashKey {
64
+ return fmt .Errorf ("Unexpected PrehashKey: %d" , leaf .PrehashKey )
65
+ }
66
+ if leaf .PrehashValue != spec .PrehashValue {
67
+ return fmt .Errorf ("Unexpected PrehashValue: %d" , leaf .PrehashValue )
68
+ }
69
+ if leaf .Length != spec .Length {
70
+ return fmt .Errorf ("Unexpected LengthOp: %d" , leaf .Length )
71
+ }
72
+ if ! bytes .HasPrefix (leaf .Prefix , spec .Prefix ) {
73
+ return fmt .Errorf ("Leaf Prefix doesn't start with %X" , spec .Prefix )
74
+ }
75
+ return nil
76
+ }
77
+
78
+ func (p * ExistenceProof ) checkInner (inner * InnerOp , leafPrefix []byte ) error {
79
+ if bytes .HasPrefix (inner .Prefix , leafPrefix ) {
80
+ return fmt .Errorf ("Inner Prefix starts with %X" , leafPrefix )
81
+ }
82
+ return nil
83
+ }
0 commit comments