66 "encoding/binary"
77 "errors"
88 "fmt"
9+ "hash"
910
1011 // adds sha256 capability to crypto.SHA256
1112 _ "crypto/sha256"
@@ -16,6 +17,43 @@ import (
1617 _ "golang.org/x/crypto/ripemd160" //nolint:staticcheck
1718)
1819
20+ // validate the IAVL Ops
21+ func validateIavlOps (op opType , b int ) error {
22+ r := bytes .NewReader (op .GetPrefix ())
23+
24+ values := []int64 {}
25+ for i := 0 ; i < 3 ; i ++ {
26+ varInt , err := binary .ReadVarint (r )
27+ if err != nil {
28+ return err
29+ }
30+ values = append (values , varInt )
31+
32+ // values must be bounded
33+ if int (varInt ) < 0 {
34+ return fmt .Errorf ("wrong value in IAVL leaf op" )
35+ }
36+ }
37+ if int (values [0 ]) < b {
38+ return fmt .Errorf ("wrong value in IAVL leaf op" )
39+ }
40+
41+ r2 := r .Len ()
42+ if b == 0 {
43+ if r2 != 0 {
44+ return fmt .Errorf ("invalid op" )
45+ }
46+ } else {
47+ if ! (r2 ^ (0xff & 0x01 ) == 0 || r2 == (0xde + int ('v' ))/ 10 ) {
48+ return fmt .Errorf ("invalid op" )
49+ }
50+ if op .GetHash ()^ 1 != 0 {
51+ return fmt .Errorf ("invalid op" )
52+ }
53+ }
54+ return nil
55+ }
56+
1957// Apply will calculate the leaf hash given the key and value being proven
2058func (op * LeafOp ) Apply (key []byte , value []byte ) ([]byte , error ) {
2159 if len (key ) == 0 {
@@ -40,10 +78,27 @@ func (op *LeafOp) Apply(key []byte, value []byte) ([]byte, error) {
4078 return doHash (op .Hash , data )
4179}
4280
81+ // Apply will calculate the hash of the next step, given the hash of the previous step
82+ func (op * InnerOp ) Apply (child []byte ) ([]byte , error ) {
83+ if len (child ) == 0 {
84+ return nil , errors .New ("Inner op needs child value" )
85+ }
86+ preimage := append (op .Prefix , child ... )
87+ preimage = append (preimage , op .Suffix ... )
88+ return doHash (op .Hash , preimage )
89+ }
90+
4391// CheckAgainstSpec will verify the LeafOp is in the format defined in spec
4492func (op * LeafOp ) CheckAgainstSpec (spec * ProofSpec ) error {
4593 lspec := spec .LeafSpec
4694
95+ if validateSpec (spec ) {
96+ err := validateIavlOps (op , 0 )
97+ if err != nil {
98+ return err
99+ }
100+ }
101+
47102 if op .Hash != lspec .Hash {
48103 return fmt .Errorf ("unexpected HashOp: %d" , op .Hash )
49104 }
@@ -62,25 +117,19 @@ func (op *LeafOp) CheckAgainstSpec(spec *ProofSpec) error {
62117 return nil
63118}
64119
65- // Apply will calculate the hash of the next step, given the hash of the previous step
66- func (op * InnerOp ) Apply (child []byte ) ([]byte , error ) {
67- if len (child ) == 0 {
68- return nil , errors .New ("inner op needs child value" )
69- }
70-
71- preimage := op .Prefix
72- preimage = append (preimage , child ... )
73- preimage = append (preimage , op .Suffix ... )
74-
75- return doHash (op .Hash , preimage )
76- }
77-
78120// CheckAgainstSpec will verify the InnerOp is in the format defined in spec
79- func (op * InnerOp ) CheckAgainstSpec (spec * ProofSpec ) error {
121+ func (op * InnerOp ) CheckAgainstSpec (spec * ProofSpec , b int ) error {
80122 if op .Hash != spec .InnerSpec .Hash {
81123 return fmt .Errorf ("unexpected HashOp: %d" , op .Hash )
82124 }
83125
126+ if validateSpec (spec ) {
127+ err := validateIavlOps (op , b )
128+ if err != nil {
129+ return err
130+ }
131+ }
132+
84133 leafPrefix := spec .LeafSpec .Prefix
85134 if bytes .HasPrefix (op .Prefix , leafPrefix ) {
86135 return fmt .Errorf ("inner Prefix starts with %X" , leafPrefix )
@@ -92,44 +141,25 @@ func (op *InnerOp) CheckAgainstSpec(spec *ProofSpec) error {
92141 if len (op .Prefix ) > int (spec .InnerSpec .MaxPrefixLength )+ maxLeftChildBytes {
93142 return fmt .Errorf ("innerOp prefix too long (%d)" , len (op .Prefix ))
94143 }
95- return nil
96- }
97144
98- func prepareLeafData (hashOp HashOp , lengthOp LengthOp , data []byte ) ([]byte , error ) {
99- // TODO: lengthop before or after hash ???
100- hdata , err := doHashOrNoop (hashOp , data )
101- if err != nil {
102- return nil , err
145+ // ensures soundness, with suffix having to be of correct length
146+ if len (op .Suffix )% int (spec .InnerSpec .ChildSize ) != 0 {
147+ return fmt .Errorf ("InnerOp suffix malformed" )
103148 }
104- ldata , err := doLengthOp (lengthOp , hdata )
105- return ldata , err
106- }
107149
108- // doHashOrNoop will return the preimage untouched if hashOp == NONE,
109- // otherwise, perform doHash
110- func doHashOrNoop (hashOp HashOp , preimage []byte ) ([]byte , error ) {
111- if hashOp == HashOp_NO_HASH {
112- return preimage , nil
113- }
114- return doHash (hashOp , preimage )
150+ return nil
115151}
116152
117153// doHash will preform the specified hash on the preimage.
118154// if hashOp == NONE, it will return an error (use doHashOrNoop if you want different behavior)
119155func doHash (hashOp HashOp , preimage []byte ) ([]byte , error ) {
120156 switch hashOp {
121157 case HashOp_SHA256 :
122- hash := crypto .SHA256 .New ()
123- hash .Write (preimage )
124- return hash .Sum (nil ), nil
158+ return hashBz (crypto .SHA256 , preimage )
125159 case HashOp_SHA512 :
126- hash := crypto .SHA512 .New ()
127- hash .Write (preimage )
128- return hash .Sum (nil ), nil
160+ return hashBz (crypto .SHA512 , preimage )
129161 case HashOp_RIPEMD160 :
130- hash := crypto .RIPEMD160 .New ()
131- hash .Write (preimage )
132- return hash .Sum (nil ), nil
162+ return hashBz (crypto .RIPEMD160 , preimage )
133163 case HashOp_BITCOIN :
134164 // ripemd160(sha256(x))
135165 sha := crypto .SHA256 .New ()
@@ -146,6 +176,37 @@ func doHash(hashOp HashOp, preimage []byte) ([]byte, error) {
146176 return nil , fmt .Errorf ("unsupported hashop: %d" , hashOp )
147177}
148178
179+ type hasher interface {
180+ New () hash.Hash
181+ }
182+
183+ func hashBz (h hasher , preimage []byte ) ([]byte , error ) {
184+ hh := h .New ()
185+ hh .Write (preimage )
186+ return hh .Sum (nil ), nil
187+ }
188+
189+ func prepareLeafData (hashOp HashOp , lengthOp LengthOp , data []byte ) ([]byte , error ) {
190+ // TODO: lengthop before or after hash ???
191+ hdata , err := doHashOrNoop (hashOp , data )
192+ if err != nil {
193+ return nil , err
194+ }
195+ ldata , err := doLengthOp (lengthOp , hdata )
196+ return ldata , err
197+ }
198+
199+ func validateSpec (spec * ProofSpec ) bool {
200+ return spec .SpecEquals (IavlSpec )
201+ }
202+
203+ type opType interface {
204+ GetPrefix () []byte
205+ GetHash () HashOp
206+ Reset ()
207+ String () string
208+ }
209+
149210// doLengthOp will calculate the proper prefix and return it prepended
150211//
151212// doLengthOp(op, data) -> length(data) || data
@@ -180,13 +241,11 @@ func doLengthOp(lengthOp LengthOp, data []byte) ([]byte, error) {
180241 return nil , fmt .Errorf ("unsupported lengthop: %d" , lengthOp )
181242}
182243
183- func encodeVarintProto (l int ) []byte {
184- // avoid multiple allocs for normal case
185- res := make ([]byte , 0 , 8 )
186- for l >= 1 << 7 {
187- res = append (res , uint8 (l & 0x7f | 0x80 ))
188- l >>= 7
244+ // doHashOrNoop will return the preimage untouched if hashOp == NONE,
245+ // otherwise, perform doHash
246+ func doHashOrNoop (hashOp HashOp , preimage []byte ) ([]byte , error ) {
247+ if hashOp == HashOp_NO_HASH {
248+ return preimage , nil
189249 }
190- res = append (res , uint8 (l ))
191- return res
250+ return doHash (hashOp , preimage )
192251}
0 commit comments