internal.gno
1.56 Kb · 66 lines
1package merkle
2
3import "crypto/sha256"
4
5// encodeSlices renders items in the wire shape crypto/merkle.HashFromByteSlices
6// expects: a 4-byte big-endian count, then per item a 4-byte big-endian length
7// followed by its bytes. The native side decodes this back into [][]byte; gno
8// cannot hand a slice of slices to a native directly.
9func encodeSlices(items [][]byte) []byte {
10 n := 0
11 for _, it := range items {
12 n += 4 + len(it)
13 }
14 out := make([]byte, 0, 4+n)
15 out = appendBE32(out, len(items))
16 for _, it := range items {
17 out = appendBE32(out, len(it))
18 out = append(out, it...)
19 }
20 return out
21}
22
23func appendBE32(dst []byte, n int) []byte {
24 return append(dst, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
25}
26
27// hashSortedPair is the commutative node hash: SHA256 over the two children in
28// ascending byte order, so a proof needs no left/right flag. Used only by
29// VerifySorted.
30func hashSortedPair(a, b []byte) []byte {
31 d := make([]byte, 0, len(a)+len(b))
32 if less(a, b) {
33 d = append(append(d, a...), b...)
34 } else {
35 d = append(append(d, b...), a...)
36 }
37 h := sha256.Sum256(d)
38 return h[:]
39}
40
41// less reports a < b in lexicographic byte order. gno's bytes package is
42// available, but keeping the comparison here keeps this package import-light.
43func less(a, b []byte) bool {
44 n := len(a)
45 if len(b) < n {
46 n = len(b)
47 }
48 for i := 0; i < n; i++ {
49 if a[i] != b[i] {
50 return a[i] < b[i]
51 }
52 }
53 return len(a) < len(b)
54}
55
56func equal(a, b []byte) bool {
57 if len(a) != len(b) {
58 return false
59 }
60 for i := range a {
61 if a[i] != b[i] {
62 return false
63 }
64 }
65 return true
66}