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 }