github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/crypto/merkle_test.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/rand"
     5  	"testing"
     6  )
     7  
     8  // TestTreeBuilder builds a tree and gets the merkle root.
     9  func TestTreeBuilder(t *testing.T) {
    10  	tree := NewTree()
    11  	tree.PushObject("a")
    12  	tree.PushObject("b")
    13  	_ = tree.Root()
    14  
    15  	// Correctness is assumed, as it's tested by the merkletree package. This
    16  	// function is really for code coverage.
    17  }
    18  
    19  // TestCalculateLeaves probes the CalculateLeaves function.
    20  func TestCalculateLeaves(t *testing.T) {
    21  	tests := []struct {
    22  		size, expSegs uint64
    23  	}{
    24  		{0, 1},
    25  		{63, 1},
    26  		{64, 1},
    27  		{65, 2},
    28  		{127, 2},
    29  		{128, 2},
    30  		{129, 3},
    31  	}
    32  
    33  	for i, test := range tests {
    34  		if segs := CalculateLeaves(test.size); segs != test.expSegs {
    35  			t.Errorf("miscalculation for test %v: expected %v, got %v", i, test.expSegs, segs)
    36  		}
    37  	}
    38  }
    39  
    40  // TestStorageProof builds a storage proof and checks that it verifies
    41  // correctly.
    42  func TestStorageProof(t *testing.T) {
    43  	// Generate proof data.
    44  	numSegments := uint64(7)
    45  	data := make([]byte, numSegments*SegmentSize)
    46  	rand.Read(data)
    47  	rootHash := MerkleRoot(data)
    48  
    49  	// Create and verify proofs for all indices.
    50  	for i := uint64(0); i < numSegments; i++ {
    51  		baseSegment, hashSet := MerkleProof(data, i)
    52  		if !VerifySegment(baseSegment, hashSet, numSegments, i, rootHash) {
    53  			t.Error("Proof", i, "did not pass verification")
    54  		}
    55  	}
    56  
    57  	// Try an incorrect proof.
    58  	baseSegment, hashSet := MerkleProof(data, 3)
    59  	if VerifySegment(baseSegment, hashSet, numSegments, 4, rootHash) {
    60  		t.Error("Verified a bad proof")
    61  	}
    62  }
    63  
    64  // TestNonMultipleNumberOfSegmentsStorageProof builds a storage proof that has
    65  // a last leaf of size less than SegmentSize.
    66  func TestNonMultipleLeafSizeStorageProof(t *testing.T) {
    67  	// Generate proof data.
    68  	data := make([]byte, (2*SegmentSize)+10)
    69  	rand.Read(data)
    70  	rootHash := MerkleRoot(data)
    71  
    72  	// Create and verify a proof for the last index.
    73  	baseSegment, hashSet := MerkleProof(data, 2)
    74  	if !VerifySegment(baseSegment, hashSet, 3, 2, rootHash) {
    75  		t.Error("padded segment proof failed")
    76  	}
    77  }
    78  
    79  // TestCachedTree tests the cached tree functions of the package.
    80  func TestCachedTree(t *testing.T) {
    81  	if testing.Short() {
    82  		t.SkipNow()
    83  	}
    84  
    85  	// Build a cached tree out of 4 subtrees, each subtree of height 2 (4
    86  	// elements).
    87  	tree1Bytes, err := RandBytes(SegmentSize * 4)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	tree2Bytes, err := RandBytes(SegmentSize * 4)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	tree3Bytes, err := RandBytes(SegmentSize * 4)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	tree4Bytes, err := RandBytes(SegmentSize * 4)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	tree1Root := MerkleRoot(tree1Bytes)
   104  	tree2Root := MerkleRoot(tree2Bytes)
   105  	tree3Root := MerkleRoot(tree3Bytes)
   106  	tree4Root := MerkleRoot(tree4Bytes)
   107  	fullRoot := MerkleRoot(append(tree1Bytes, append(tree2Bytes, append(tree3Bytes, tree4Bytes...)...)...))
   108  
   109  	// Get a cached proof for index 0.
   110  	base, cachedHashSet := MerkleProof(tree1Bytes, 0)
   111  	if !VerifySegment(base, cachedHashSet, 4, 0, tree1Root) {
   112  		t.Fatal("the proof for the subtree was invalid")
   113  	}
   114  	ct := NewCachedTree(2)
   115  	ct.SetIndex(0)
   116  	ct.Push(tree1Root)
   117  	ct.Push(tree2Root)
   118  	ct.Push(tree3Root)
   119  	ct.Push(tree4Root)
   120  	hashSet := ct.Prove(base, cachedHashSet)
   121  	if !VerifySegment(base, hashSet, 4*4, 0, fullRoot) {
   122  		t.Fatal("cached proof construction appears unsuccessful")
   123  	}
   124  	if ct.Root() != fullRoot {
   125  		t.Fatal("cached Merkle root is not matching the full Merkle root")
   126  	}
   127  
   128  	// Get a cached proof for index 6.
   129  	base, cachedHashSet = MerkleProof(tree2Bytes, 2)
   130  	if !VerifySegment(base, cachedHashSet, 4, 2, tree2Root) {
   131  		t.Fatal("the proof for the subtree was invalid")
   132  	}
   133  	ct = NewCachedTree(2)
   134  	ct.SetIndex(6)
   135  	ct.Push(tree1Root)
   136  	ct.Push(tree2Root)
   137  	ct.Push(tree3Root)
   138  	ct.Push(tree4Root)
   139  	hashSet = ct.Prove(base, cachedHashSet)
   140  	if !VerifySegment(base, hashSet, 4*4, 6, fullRoot) {
   141  		t.Fatal("cached proof construction appears unsuccessful")
   142  	}
   143  	if ct.Root() != fullRoot {
   144  		t.Fatal("cached Merkle root is not matching the full Merkle root")
   145  	}
   146  }
   147  
   148  // TestMerkleTreeOddDataSize checks that MerkleRoot and MerkleProof still
   149  // function correctly if you provide data which does not have a size evenly
   150  // divisible by SegmentSize.
   151  func TestOddDataSize(t *testing.T) {
   152  	if testing.Short() {
   153  		t.SkipNow()
   154  	}
   155  
   156  	// Create some random data that's not evenly padded.
   157  	for i := 0; i < 25; i++ {
   158  		randFullSegments, err := RandIntn(65)
   159  		if err != nil {
   160  			t.Fatal(err)
   161  		}
   162  		randOverflow, err := RandIntn(63)
   163  		if err != nil {
   164  			t.Fatal(err)
   165  		}
   166  		randOverflow++ // Range is [1, 63] instead of [0, 62]
   167  		randProofIndex, err := RandIntn(randFullSegments + 1)
   168  		if err != nil {
   169  			t.Fatal(err)
   170  		}
   171  		data, err := RandBytes(SegmentSize*randFullSegments + randOverflow)
   172  		if err != nil {
   173  			t.Fatal(err)
   174  		}
   175  		root := MerkleRoot(data)
   176  		base, hashSet := MerkleProof(data, uint64(randProofIndex))
   177  		if !VerifySegment(base, hashSet, uint64(randFullSegments)+1, uint64(randProofIndex), root) {
   178  			t.Error("Padded data proof failed for", randFullSegments, randOverflow, randProofIndex)
   179  		}
   180  	}
   181  }