github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/merkle/memory_merkle_tree_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 "encoding/hex" 20 "errors" 21 "fmt" 22 "math/rand" 23 "testing" 24 25 "github.com/google/trillian/merkle/hashers" 26 "github.com/google/trillian/merkle/rfc6962" 27 ) 28 29 // Note test inputs came from the values used by the C++ code. The original 30 // is in the main certificate transparency repo at cpp/merkletree/merkletree_test.cc 31 32 var fuzzTestSize = int64(256) 33 34 // This is the hash of an empty string 35 var emptyTreeHashValue = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 36 37 // Inputs to the reference tree, which has eight leaves. 38 var leafInputs = []string{"", "00", "10", "2021", "3031", "40414243", 39 "5051525354555657", "606162636465666768696a6b6c6d6e6f"} 40 41 // Level counts for number of leaves in trees from [1, 8] 42 var levelCounts = []int64{1, 2, 3, 3, 4, 4, 4, 4} 43 44 // Incremental roots from building the reference tree from inputs leaf-by-leaf. 45 // Generated from ReferenceMerkleTreeHash in C++. 46 var rootsAtSize = []string{ 47 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 48 "fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 49 "aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 50 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 51 "4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 52 "76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 53 "ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 54 "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328"} 55 56 // Some paths for the reference tree. 57 type pathTestVector struct { 58 leaf int64 59 snapshot int64 60 pathLength int64 61 testVector []string 62 } 63 64 // Generated from C++ ReferenceMerklePath, not the Go one so we can verify 65 // that they are both producing the same paths in a sanity test. 66 var testPaths = []pathTestVector{ 67 {0, 0, 0, []string{""}}, 68 {1, 1, 0, []string{""}}, 69 {1, 70 8, 71 3, 72 []string{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 73 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 74 "6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4"}}, 75 {6, 76 8, 77 3, 78 []string{"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 79 "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 80 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"}}, 81 {3, 82 3, 83 1, 84 []string{"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125"}}, 85 {2, 86 5, 87 3, 88 []string{"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 89 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 90 "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b"}}} 91 92 type proofTestVector struct { 93 snapshot1 int64 94 snapshot2 int64 95 proofLength int64 96 proof []string 97 } 98 99 // Generated from ReferenceSnapshotConsistency in C++ version. 100 var testProofs = []proofTestVector{ 101 {1, 1, 0, []string{""}}, 102 {1, 8, 3, []string{ 103 "96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 104 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 105 "6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4"}}, 106 {6, 8, 3, []string{ 107 "0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", 108 "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 109 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"}}, 110 {2, 5, 2, []string{ 111 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 112 "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b"}}} 113 114 func decodeHexStringOrPanic(hs string) []byte { 115 data, err := hex.DecodeString(hs) 116 if err != nil { 117 panic(fmt.Errorf("failed to decode test data: %s", hs)) 118 } 119 120 return data 121 } 122 123 func makeEmptyTree() *InMemoryMerkleTree { 124 return NewInMemoryMerkleTree(rfc6962.DefaultHasher) 125 } 126 127 func makeFuzzTestData() [][]byte { 128 var data [][]byte 129 130 for s := int64(0); s < fuzzTestSize; s++ { 131 data = append(data, make([]byte, 1)) 132 data[s][0] = byte(s) 133 } 134 135 return data 136 } 137 138 func getRootAsString(mt InMemoryMerkleTree, leaf int64) string { 139 node := mt.RootAtSnapshot(leaf) 140 141 if node.hash == nil { 142 // Doesn't matter what this is as long as it could never be a valid 143 // hex encoding of a hash 144 return "<nil>" 145 } 146 147 return hex.EncodeToString(node.hash) 148 } 149 150 // REFERENCE IMPLEMENTATIONS 151 152 // Get the largest power of two smaller than i. 153 func downToPowerOfTwo(i int64) int64 { 154 if i < 2 { 155 panic(errors.New("Requested downToPowerOf2 for value < 2")) 156 } 157 158 // Find the smallest power of two greater than or equal to i. We 159 // know i > 2 160 split := int64(2) 161 162 for split < i { 163 split <<= 1 164 } 165 166 // Get the largest power of two smaller than i. 167 return split >> 1 168 } 169 170 // Reference implementation of Merkle hash, for cross-checking. 171 func referenceMerkleTreeHash(inputs [][]byte, treehasher hashers.LogHasher) ([]byte, error) { 172 if len(inputs) == 0 { 173 return treehasher.EmptyRoot(), nil 174 } 175 176 if len(inputs) == 1 { 177 leafHash, err := treehasher.HashLeaf(inputs[0]) 178 if err != nil { 179 return nil, err 180 } 181 return leafHash, nil 182 } 183 184 split := downToPowerOfTwo(int64(len(inputs))) 185 186 lhs, err := referenceMerkleTreeHash(inputs[:split], treehasher) 187 if err != nil { 188 return nil, err 189 } 190 rhs, err := referenceMerkleTreeHash(inputs[split:], treehasher) 191 if err != nil { 192 return nil, err 193 } 194 return treehasher.HashChildren(lhs, rhs), nil 195 } 196 197 // Reference implementation of Merkle paths. Path from leaf to root, 198 // excluding the leaf and root themselves. 199 func referenceMerklePath(inputs [][]byte, leaf int64, treehasher hashers.LogHasher) ([][]byte, error) { 200 var path [][]byte 201 202 inputLen := int64(len(inputs)) 203 if leaf > inputLen || leaf == 0 { 204 return path, nil 205 } 206 207 if inputLen == 1 { 208 return path, nil 209 } 210 211 split := downToPowerOfTwo(inputLen) 212 213 var subpath [][]byte 214 215 if leaf <= split { 216 s, err := referenceMerklePath(inputs[:split], leaf, treehasher) 217 if err != nil { 218 return nil, err 219 } 220 subpath = s 221 path = append(path, subpath...) 222 refHash, err := referenceMerkleTreeHash(inputs[split:], treehasher) 223 if err != nil { 224 return nil, err 225 } 226 path = append(path, refHash) 227 } else { 228 s, err := referenceMerklePath(inputs[split:], leaf-split, treehasher) 229 if err != nil { 230 return nil, err 231 } 232 subpath = s 233 path = append(path, subpath...) 234 refHash, err := referenceMerkleTreeHash(inputs[:split], treehasher) 235 if err != nil { 236 return nil, err 237 } 238 path = append(path, refHash) 239 } 240 241 return path, nil 242 } 243 244 // Reference implementation of snapshot consistency. 245 // Call with haveRoot1 = true. 246 func referenceSnapshotConsistency(inputs [][]byte, snapshot2 int64, 247 snapshot1 int64, treehasher hashers.LogHasher, haveRoot1 bool) ([][]byte, error) { 248 249 var proof [][]byte 250 251 if snapshot1 == 0 || snapshot1 > snapshot2 { 252 return proof, nil 253 } 254 255 if snapshot1 == snapshot2 { 256 // Consistency proof for two equal subtrees is empty. 257 if !haveRoot1 { 258 // Record the hash of this subtree unless it's the root for which 259 // the proof was originally requested. (This happens when the snapshot1 260 // tree is balanced.) 261 refHash, err := referenceMerkleTreeHash(inputs[:snapshot1], treehasher) 262 if err != nil { 263 return nil, err 264 } 265 proof = append(proof, refHash) 266 } 267 return proof, nil 268 } 269 270 // 0 < snapshot1 < snapshot2 271 split := downToPowerOfTwo(snapshot2) 272 273 var subproof [][]byte 274 if snapshot1 <= split { 275 // Root of snapshot1 is in the left subtree of snapshot2. 276 // Prove that the left subtrees are consistent. 277 s, err := referenceSnapshotConsistency(inputs[:split], split, snapshot1, treehasher, haveRoot1) 278 if err != nil { 279 return nil, err 280 } 281 subproof = s 282 proof = append(proof, subproof...) 283 // Record the hash of the right subtree (only present in snapshot2). 284 h, err := referenceMerkleTreeHash(inputs[split:], treehasher) 285 if err != nil { 286 return nil, err 287 } 288 proof = append(proof, h) 289 } else { 290 // Snapshot1 root is at the same level as snapshot2 root. 291 // Prove that the right subtrees are consistent. The right subtree 292 // doesn't contain the root of snapshot1, so set haveRoot1 = false. 293 s, err := referenceSnapshotConsistency(inputs[split:], snapshot2-split, snapshot1-split, treehasher, false) 294 if err != nil { 295 return nil, err 296 } 297 subproof = s 298 299 proof = append(proof, subproof...) 300 // Record the hash of the left subtree (equal in both trees). 301 refHash, err := referenceMerkleTreeHash(inputs[:split], treehasher) 302 if err != nil { 303 return nil, err 304 } 305 proof = append(proof, refHash) 306 } 307 return proof, nil 308 } 309 310 func TestEmptyTreeIsEmpty(t *testing.T) { 311 mt := makeEmptyTree() 312 313 if mt.LevelCount() != 0 { 314 t.Errorf("Empty tree had levels: %d", mt.LevelCount()) 315 } 316 317 if mt.LeafCount() != 0 { 318 t.Errorf("Empty tree had leaves: %d", mt.LeafCount()) 319 } 320 } 321 322 func TestEmptyTreeHash(t *testing.T) { 323 actual := makeEmptyTree().CurrentRoot().hash 324 actualStr := hex.EncodeToString(actual) 325 326 if actualStr != emptyTreeHashValue { 327 t.Errorf("Unexpected empty tree hash: %s", actualStr) 328 } 329 } 330 331 func validateTree(mt *InMemoryMerkleTree, l int64, t *testing.T) { 332 if mt.LeafCount() != l+1 { 333 t.Errorf("Incorrect leaf count %d, expecting %d", mt.LeafCount(), l+1) 334 } 335 336 if mt.LevelCount() != levelCounts[l] { 337 t.Errorf("Incorrect leaf count %d, expecting %d", mt.LevelCount(), 338 levelCounts[l]) 339 } 340 341 if getRootAsString(*mt, l+1) != rootsAtSize[l] { 342 t.Errorf("Incorrect root %d, got %s", l, getRootAsString(*mt, l+1)) 343 } 344 345 if getRootAsString(*mt, 0) != emptyTreeHashValue { 346 t.Errorf("Incorrect root(0) %d, got %s", l, getRootAsString(*mt, 0)) 347 } 348 349 for j := int64(0); j <= l; j++ { 350 if getRootAsString(*mt, j+1) != rootsAtSize[j] { 351 t.Errorf("Incorrect root %d, %d, got %s", l, j, getRootAsString(*mt, j+1)) 352 } 353 } 354 355 for k := l + 1; k <= 8; k++ { 356 if getRootAsString(*mt, k+1) != "<nil>" { 357 t.Errorf("Got root for missing leaf %d, %d, %s", l, k, 358 getRootAsString(*mt, k+1)) 359 } 360 } 361 } 362 363 func TestBuildTreeBuildOneAtATime(t *testing.T) { 364 mt := makeEmptyTree() 365 366 // Add to the tree, checking after each leaf 367 for l := int64(0); l < 8; l++ { 368 mt.AddLeaf(decodeHexStringOrPanic(leafInputs[l])) 369 validateTree(mt, l, t) 370 } 371 } 372 373 func TestBuildTreeBuildAllAtOnce(t *testing.T) { 374 mt := makeEmptyTree() 375 376 for l := 0; l < 3; l++ { 377 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[l])); err != nil { 378 t.Fatalf("AddLeaf(%v): %v", leafInputs[l], err) 379 } 380 } 381 382 // Check the intermediate state 383 validateTree(mt, 2, t) 384 385 for l := 3; l < 8; l++ { 386 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[l])); err != nil { 387 t.Fatalf("AddLeaf(%v): %v", leafInputs[l], err) 388 } 389 } 390 391 // Check the final state 392 validateTree(mt, 7, t) 393 } 394 395 func TestBuildTreeBuildTwoChunks(t *testing.T) { 396 mt := makeEmptyTree() 397 398 // Add to the tree, checking after each leaf 399 for l := 0; l < 8; l++ { 400 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[l])); err != nil { 401 t.Fatalf("AddLeaf(%v): %v", leafInputs[l], err) 402 } 403 } 404 405 validateTree(mt, 7, t) 406 } 407 408 func TestDownToPowerOfTwoSanity(t *testing.T) { 409 if downToPowerOfTwo(7) != 4 { 410 t.Errorf("Down to power of 2 returned 7 -> %d", downToPowerOfTwo(7)) 411 } 412 if downToPowerOfTwo(8) != 4 { 413 t.Errorf("Down to power of 2 returned 8 -> %d", downToPowerOfTwo(8)) 414 } 415 if downToPowerOfTwo(63) != 32 { 416 t.Errorf("Down to power of 2 returned 63 -> %d", downToPowerOfTwo(63)) 417 } 418 if downToPowerOfTwo(28973) != 16384 { 419 t.Errorf("Down to power of 2 returned 63 -> %d", downToPowerOfTwo(28973)) 420 } 421 } 422 423 func TestReferenceMerklePathSanity(t *testing.T) { 424 var data [][]byte 425 426 mt := makeEmptyTree() 427 428 for s := 0; s < 8; s++ { 429 data = append(data, decodeHexStringOrPanic(leafInputs[s])) 430 } 431 432 for _, path := range testPaths { 433 referencePath, err := referenceMerklePath(data[:path.snapshot], path.leaf, mt.hasher) 434 if err != nil { 435 t.Fatalf("referenceMerklePath(): %v", err) 436 } 437 438 if int64(len(referencePath)) != path.pathLength { 439 t.Errorf("Mismatched path length: %d, %d: %v %v", 440 len(referencePath), path.pathLength, path, referencePath) 441 } 442 443 for i := int64(0); i < path.pathLength; i++ { 444 if (bytes.Compare(referencePath[i], decodeHexStringOrPanic(path.testVector[i]))) != 0 { 445 t.Errorf("Path mismatch: %s, %s", hex.EncodeToString(referencePath[i]), 446 path.testVector[i]) 447 } 448 } 449 } 450 } 451 452 func TestMerkleTreeRootFuzz(t *testing.T) { 453 data := makeFuzzTestData() 454 455 for treeSize := int64(1); treeSize <= fuzzTestSize; treeSize++ { 456 mt := makeEmptyTree() 457 458 for l := int64(0); l < treeSize; l++ { 459 if _, _, err := mt.AddLeaf(data[l]); err != nil { 460 t.Fatalf("AddLeaf(%v): %v", data[l], err) 461 } 462 } 463 464 // Since the tree is evaluated lazily, the order of queries is significant. 465 // Generate a random sequence of 8 queries for each tree. 466 for j := int64(0); j < 8; j++ { 467 // A snapshot in the range 0...tree_size. 468 snapshot := rand.Int63n(treeSize + 1) 469 470 h1 := mt.RootAtSnapshot(snapshot).hash 471 h2, err := referenceMerkleTreeHash(data[:snapshot], mt.hasher) 472 if err != nil { 473 t.Fatalf("referenceMerkleTreeHash(): %v", err) 474 } 475 476 if !bytes.Equal(h1, h2) { 477 t.Errorf("Mismatched hash: %x, %x", h1, h2) 478 } 479 } 480 } 481 } 482 483 // Make random path queries and check against the reference implementation. 484 func TestMerkleTreePathFuzz(t *testing.T) { 485 data := makeFuzzTestData() 486 487 for treeSize := int64(1); treeSize <= fuzzTestSize; treeSize++ { 488 //mt := makeLoggingEmptyTree(t) 489 mt := makeEmptyTree() 490 491 for l := int64(0); l < treeSize; l++ { 492 if _, _, err := mt.AddLeaf(data[l]); err != nil { 493 t.Fatalf("AddLeaf(%v): %v", data[l], err) 494 } 495 } 496 497 // Since the tree is evaluated lazily, the order of queries is significant. 498 // Generate a random sequence of 8 queries for each tree. 499 for j := 0; j < 8; j++ { 500 // A snapshot in the range 0... length. 501 snapshot := rand.Int63n(treeSize + 1) 502 // A leaf in the range 0... snapshot. 503 leaf := rand.Int63n(snapshot + 1) 504 505 p1 := mt.PathToRootAtSnapshot(leaf, snapshot) 506 507 //for i, p := range p1 { 508 // t.Logf("P %d: %d %d %v", i, p.xCoord, p.yCoord, p.value) 509 //} 510 511 p2, err := referenceMerklePath(data[:snapshot], leaf, mt.hasher) 512 if err != nil { 513 t.Fatalf("referenceMerklePath(): %v", err) 514 } 515 516 if len(p1) != len(p2) { 517 t.Errorf("Different path lengths %v, %v", p1, p2) 518 } else { 519 for i := 0; i < len(p1); i++ { 520 if !bytes.Equal(p1[i].Value.hash, p2[i]) { 521 t.Errorf("Mismatched hash %d %d %d: %v, %v", snapshot, leaf, i, 522 p1[i].Value.hash, p2[i]) 523 } 524 } 525 } 526 } 527 } 528 } 529 530 // Make random proof queries and check against the reference implementation. 531 func TestMerkleTreeConsistencyFuzz(t *testing.T) { 532 data := makeFuzzTestData() 533 534 for treeSize := int64(1); treeSize <= fuzzTestSize; treeSize++ { 535 mt := makeEmptyTree() 536 537 for l := int64(0); l < treeSize; l++ { 538 if _, _, err := mt.AddLeaf(data[l]); err != nil { 539 t.Fatalf("AddLeaf(%v): %v", data[l], err) 540 } 541 } 542 543 // Since the tree is evaluated lazily, the order of queries is significant. 544 // Generate a random sequence of 8 queries for each tree. 545 for j := 0; j < 8; j++ { 546 // A snapshot in the range 0... length. 547 snapshot2 := rand.Int63n(treeSize + 1) 548 // A snapshot in the range 0... snapshot. 549 snapshot1 := rand.Int63n(snapshot2 + 1) 550 551 c1 := mt.SnapshotConsistency(snapshot1, snapshot2) 552 c2, err := referenceSnapshotConsistency(data[:snapshot2], snapshot2, snapshot1, mt.hasher, true) 553 if err != nil { 554 t.Fatalf("referenceSnapshotConsistency(): %v", err) 555 } 556 557 if len(c1) != len(c2) { 558 t.Errorf("Different proof lengths: %d %d %d", treeSize, snapshot2, 559 snapshot1) 560 } 561 562 for i := 0; i < len(c1); i++ { 563 if !bytes.Equal(c1[i].Value.hash, c2[i]) { 564 t.Errorf("Different proof: %d %d %d %d, %s, %s", treeSize, 565 snapshot2, snapshot1, i, hex.EncodeToString(c1[i].Value.hash), 566 hex.EncodeToString(c2[i])) 567 } 568 } 569 } 570 } 571 } 572 573 func TestMerkleTreePathBuildOnce(t *testing.T) { 574 // First tree: build in one go. 575 mt := makeEmptyTree() 576 577 for i := 0; i < 8; i++ { 578 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[i])); err != nil { 579 t.Fatalf("AddLeaf(%v): %v", leafInputs[i], err) 580 } 581 } 582 583 if mt.LeafCount() != 8 { 584 t.Fatalf("8 leaves added but tree size is %d", mt.LeafCount()) 585 } 586 587 if !bytes.Equal(mt.CurrentRoot().hash, decodeHexStringOrPanic(rootsAtSize[7])) { 588 t.Fatalf("Got unexpected root hash: %s %s", 589 hex.EncodeToString(mt.CurrentRoot().hash), rootsAtSize[7]) 590 } 591 592 if len(mt.PathToCurrentRoot(9)) > 0 { 593 t.Fatalf("Obtained a path for non existent leaf 9: %v", mt.PathToCurrentRoot(9)) 594 } 595 596 for i := 0; i < 6; i++ { 597 p1 := mt.PathToRootAtSnapshot(testPaths[i].leaf, testPaths[i].snapshot) 598 599 var p2 []string 600 601 for j := int64(0); j < testPaths[i].pathLength; j++ { 602 p2 = append(p2, testPaths[i].testVector[j]) 603 } 604 605 if len(p1) != len(p2) { 606 t.Errorf("Different path lengths %d %d", len(p1), len(p2)) 607 t.FailNow() 608 } 609 610 for j := range p2 { 611 if got, want := p1[j].Value.hash, decodeHexStringOrPanic(testPaths[i].testVector[j]); !bytes.Equal(got, want) { 612 t.Errorf("Path mismatch: got: %v want: %v", got, want) 613 } 614 } 615 } 616 } 617 618 func TestMerkleTreePathBuildIncrementally(t *testing.T) { 619 // Second tree: build incrementally. 620 // First tree: build in one go. 621 mt := makeEmptyTree() 622 623 for i := 0; i < 8; i++ { 624 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[i])); err != nil { 625 t.Fatalf("AddLeaf(%v): %v", leafInputs[i], err) 626 } 627 } 628 629 mt2 := makeEmptyTree() 630 631 p1 := mt2.PathToCurrentRoot(0) 632 p2 := mt.PathToRootAtSnapshot(0, 0) 633 634 if len(p1) != 0 || len(p2) != 0 { 635 t.Errorf("Path mismatch at root for snapshot 0: %d %d", len(p1), len(p2)) 636 t.FailNow() 637 } 638 639 for i := int64(0); i < 8; i++ { 640 if _, _, err := mt2.AddLeaf(decodeHexStringOrPanic(leafInputs[i])); err != nil { 641 t.Fatalf("AddLeaf(%v): %v", leafInputs[i], err) 642 } 643 644 for j := int64(0); j <= i+1; j++ { 645 p1 := mt.PathToRootAtSnapshot(j, i+1) 646 p2 := mt2.PathToCurrentRoot(j) 647 648 if len(p1) != len(p2) { 649 t.Errorf("Different path lengths %d %d", len(p1), len(p2)) 650 t.FailNow() 651 } 652 653 for j := 0; j < len(p2); j++ { 654 if !bytes.Equal(p1[j].Value.hash, p2[j].Value.hash) { 655 t.Errorf("Path mismatch: %s %s", hex.EncodeToString(p1[j].Value.hash), 656 hex.EncodeToString(p2[j].Value.hash)) 657 } 658 } 659 } 660 661 for k := i + 2; k <= 9; k++ { 662 if len(mt.PathToRootAtSnapshot(k, i+1)) != 0 { 663 t.Errorf("Got non empty path unexpectedly: %d %d %d", i, k, 664 len(mt.PathToRootAtSnapshot(k, i+1))) 665 } 666 } 667 } 668 } 669 670 func TestProofConsistencyTestVectors(t *testing.T) { 671 mt := makeEmptyTree() 672 673 for i := 0; i < 8; i++ { 674 if _, _, err := mt.AddLeaf(decodeHexStringOrPanic(leafInputs[i])); err != nil { 675 t.Fatalf("AddLeaf(%v): %v", leafInputs[i], err) 676 } 677 } 678 679 if mt.LeafCount() != 8 { 680 t.Errorf("8 leaves added but tree size is %d", mt.LeafCount()) 681 t.FailNow() 682 } 683 684 if !bytes.Equal(mt.CurrentRoot().hash, decodeHexStringOrPanic(rootsAtSize[7])) { 685 t.Errorf("Got unexpected root hash: %s %s", 686 hex.EncodeToString(mt.CurrentRoot().hash), rootsAtSize[7]) 687 t.FailNow() 688 } 689 690 for i := 0; i < 4; i++ { 691 p1 := mt.SnapshotConsistency(testProofs[i].snapshot1, testProofs[i].snapshot2) 692 693 var p2 []string 694 for j := int64(0); j < testProofs[i].proofLength; j++ { 695 p2 = append(p2, testProofs[i].proof[j]) 696 } 697 698 if len(p1) != len(p2) { 699 t.Errorf("Different proof lengths %d %d", len(p1), len(p2)) 700 t.FailNow() 701 } 702 703 for j := 0; j < len(p2); j++ { 704 if got, want := p1[j].Value.hash, decodeHexStringOrPanic(testProofs[i].proof[j]); !bytes.Equal(got, want) { 705 t.Errorf("Path mismatch: got: %v want: %v", got, want) 706 } 707 } 708 } 709 } 710 711 func TestAddLeafHash(t *testing.T) { 712 mt := makeEmptyTree() 713 hash := "0123456789abcdef0123456789abcdef" 714 715 index, treeEntry := mt.addLeafHash(decodeHexStringOrPanic(hash)) 716 717 if index != 1 { 718 t.Errorf("Expected 1 for first leaf sequence number but got: %d", index) 719 } 720 721 if !bytes.Equal(decodeHexStringOrPanic(hash), treeEntry.hash) { 722 t.Error("Hash value was not copied into leaf correctly") 723 } 724 } 725 726 func TestHashAccessor(t *testing.T) { 727 mt := makeEmptyTree() 728 hash := "0123456789abcdef0123456789abcdef" 729 730 index, treeEntry := mt.addLeafHash(decodeHexStringOrPanic(hash)) 731 732 if index != 1 { 733 t.Errorf("Expected 1 for first leaf sequence number but got: %d", index) 734 } 735 736 if !bytes.Equal(decodeHexStringOrPanic(hash), treeEntry.Hash()) { 737 t.Error("Hash value was not copied into leaf correctly") 738 } 739 } 740 741 func TestHashIntoAccessor(t *testing.T) { 742 mt := makeEmptyTree() 743 hash := "0123456789abcdef0123456789abcdef" 744 745 index, treeEntry := mt.addLeafHash(decodeHexStringOrPanic(hash)) 746 747 if index != 1 { 748 t.Errorf("Expected 1 for first leaf sequence number but got: %d", index) 749 } 750 751 var dest []byte 752 dest = treeEntry.HashInto(dest) 753 754 if !bytes.Equal(decodeHexStringOrPanic(hash), dest) { 755 t.Error("Hash value was not copied into leaf correctly") 756 } 757 758 if len(dest) != len(decodeHexStringOrPanic(hash)) { 759 t.Errorf("Did not get correct length hash: %d", len(dest)) 760 } 761 762 dest[0] = dest[0] + 1 // Make the hash invalid 763 764 if !bytes.Equal(decodeHexStringOrPanic(hash), treeEntry.HashInto(dest)) { 765 t.Error("Hash value was not copied into leaf correctly") 766 } 767 }