github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/merkle/hstar2_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package merkle 16 17 import ( 18 "bytes" 19 "fmt" 20 "math/big" 21 "testing" 22 23 "github.com/google/trillian/merkle/hashers" 24 "github.com/google/trillian/merkle/maphasher" 25 "github.com/google/trillian/storage" 26 "github.com/google/trillian/testonly" 27 ) 28 29 const treeID = int64(0) 30 31 var ( 32 deB64 = testonly.MustDecodeBase64 33 ) 34 35 // Some known answers for incrementally adding index/value pairs to a sparse tree. 36 // rootB64 is the incremental root after adding the corresponding i/v pair, and 37 // all i/v pairs which come before it. 38 // 39 // Values were calculated with the C++/Python sparse Merkle tree code in the 40 // github.com/google/certificate-transparency repo. 41 // TODO(alcutter): replace with hash-dependent computation. How is this computed? 42 var simpleTestVector = []struct { 43 index, value, root []byte 44 }{ 45 {nil, nil, deB64("xmifEIEqCYCXbZUz2Dh1KCFmFZVn7DUVVxbBQTr1PWo=")}, // Empty tree. 46 {testonly.HashKey("a"), []byte("0"), deB64("nP1psZp1bu3jrY5Yv89rI+w5ywe9lLqI2qZi5ibTSF0=")}, 47 {testonly.HashKey("b"), []byte("1"), deB64("EJ1Rw6DQT9bDn2Zbn7u+9/j799PSdqT9gfBymS9MBZY=")}, 48 {testonly.HashKey("a"), []byte("2"), deB64("2rAZz4HJAMJqJ5c8ClS4wEzTP71GTdjMZMe1rKWPA5o=")}, 49 } 50 51 // createHStar2Leaves returns a []HStar2LeafHash formed by the mapping of index, value ... 52 // createHStar2Leaves panics if len(iv) is odd. Duplicate i/v pairs get over written. 53 func createHStar2Leaves(treeID int64, hasher hashers.MapHasher, iv ...[]byte) ([]HStar2LeafHash, error) { 54 if len(iv)%2 != 0 { 55 panic(fmt.Sprintf("merkle: createHstar2Leaves got odd number of iv pairs: %v", len(iv))) 56 } 57 m := make(map[string]HStar2LeafHash) 58 var index []byte 59 for i, b := range iv { 60 if i%2 == 0 { 61 index = b 62 continue 63 } 64 leafHash, err := hasher.HashLeaf(treeID, index, b) 65 if err != nil { 66 return nil, err 67 } 68 m[fmt.Sprintf("%x", index)] = HStar2LeafHash{ 69 Index: new(big.Int).SetBytes(index), 70 LeafHash: leafHash, 71 } 72 } 73 74 r := make([]HStar2LeafHash, 0, len(m)) 75 for _, v := range m { 76 r = append(r, v) 77 } 78 return r, nil 79 } 80 81 func TestHStar2SimpleDataSetKAT(t *testing.T) { 82 s := NewHStar2(treeID, maphasher.Default) 83 84 iv := [][]byte{} 85 for i, x := range simpleTestVector { 86 iv = append(iv, x.index, x.value) 87 values, err := createHStar2Leaves(treeID, maphasher.Default, iv...) 88 if err != nil { 89 t.Fatalf("createHStar2Leaves(): %v", err) 90 } 91 root, err := s.HStar2Root(s.hasher.BitLen(), values) 92 if err != nil { 93 t.Errorf("Failed to calculate root at iteration %d: %v", i, err) 94 continue 95 } 96 if got, want := root, x.root; !bytes.Equal(got, want) { 97 t.Errorf("Root: %x, want: %x", got, want) 98 } 99 } 100 } 101 102 // TestHStar2GetSet ensures that we get the same roots as above when we 103 // incrementally calculate roots. 104 func TestHStar2GetSet(t *testing.T) { 105 // Node cache is shared between tree builds and in effect plays the role of 106 // the TreeStorage layer. 107 cache := make(map[string][]byte) 108 hasher := maphasher.Default 109 110 for i, x := range simpleTestVector { 111 s := NewHStar2(treeID, hasher) 112 values, err := createHStar2Leaves(treeID, hasher, x.index, x.value) 113 if err != nil { 114 t.Fatalf("createHStar2Leaves(): %v", err) 115 } 116 // ensure we're going incrementally, one leaf at a time. 117 if len(values) != 1 { 118 t.Fatalf("Should only have 1 leaf per run, got %d", len(values)) 119 } 120 root, err := s.HStar2Nodes(nil, s.hasher.BitLen(), values, 121 func(depth int, index *big.Int) ([]byte, error) { 122 return cache[fmt.Sprintf("%x/%d", index, depth)], nil 123 }, 124 func(depth int, index *big.Int, hash []byte) error { 125 cache[fmt.Sprintf("%x/%d", index, depth)] = hash 126 return nil 127 }) 128 if err != nil { 129 t.Errorf("Failed to calculate root at iteration %d: %v", i, err) 130 continue 131 } 132 if got, want := root, x.root; !bytes.Equal(got, want) { 133 t.Errorf("Root: %x, want: %x", got, want) 134 } 135 } 136 } 137 138 // Create intermediate "root" values for the passed in HStar2LeafHashes. 139 // These "root" hashes are from (assumed distinct) subtrees of size 140 // 256-prefixSize, and can be passed in as leaves to top-subtree calculation. 141 func rootsForTrimmedKeys(t *testing.T, prefixSize int, lh []HStar2LeafHash) []HStar2LeafHash { 142 var ret []HStar2LeafHash 143 hasher := maphasher.Default 144 s := NewHStar2(treeID, hasher) 145 for i := range lh { 146 subtreeDepth := s.hasher.BitLen() - prefixSize 147 prefix := lh[i].Index.Bytes() 148 // Left pad prefix with zeros back out to 32 bytes. 149 for len(prefix) < 32 { 150 prefix = append([]byte{0}, prefix...) 151 } 152 prefix = prefix[:prefixSize/8] // We only want the first prefixSize bytes. 153 root, err := s.HStar2Nodes(prefix, subtreeDepth, []HStar2LeafHash{lh[i]}, nil, nil) 154 if err != nil { 155 t.Fatalf("Failed to calculate root %v", err) 156 } 157 158 ret = append(ret, HStar2LeafHash{ 159 Index: storage.NewNodeIDFromPrefixSuffix(prefix, storage.Suffix{}, hasher.BitLen()).BigInt(), 160 LeafHash: root, 161 }) 162 } 163 return ret 164 } 165 166 // Checks that splitting the calculation of a 256-level tree into two phases 167 // (single top subtree of size n, and multipl bottom subtrees of size 256-n) 168 // still arrives at the same Known Answers for root hash. 169 func TestHStar2OffsetRootKAT(t *testing.T) { 170 s := NewHStar2(treeID, maphasher.Default) 171 iv := [][]byte{} 172 for i, x := range simpleTestVector { 173 iv = append(iv, x.index, x.value) 174 // start at 24 so we can assume that key prefixes are probably unique by then 175 // TODO(al): improve rootsForTrimmedKeys to use a map and remove this 176 // requirement. 177 for size := 24; size < 256; size += 8 { 178 leaves, err := createHStar2Leaves(treeID, maphasher.Default, iv...) 179 if err != nil { 180 t.Fatalf("createHStar2Leaves(): %v", err) 181 } 182 intermediates := rootsForTrimmedKeys(t, size, leaves) 183 184 root, err := s.HStar2Nodes(nil, size, intermediates, nil, nil) 185 if err != nil { 186 t.Errorf("Failed to calculate root at iteration %d: %v", i, err) 187 continue 188 } 189 if got, want := root, x.root; !bytes.Equal(got, want) { 190 t.Errorf("HStar2Nodes(i: %v, size:%v): %x, want: %x", i, size, got, want) 191 } 192 } 193 } 194 } 195 196 func TestHStar2NegativeTreeLevelOffset(t *testing.T) { 197 s := NewHStar2(treeID, maphasher.Default) 198 199 _, err := s.HStar2Nodes(make([]byte, 31), 9, []HStar2LeafHash{}, nil, nil) 200 if got, want := err, ErrSubtreeOverrun; got != want { 201 t.Fatalf("Hstar2Nodes(): %v, want %v", got, want) 202 } 203 }