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  }