github.com/Oyster-zx/tendermint@v0.34.24-fork/crypto/merkle/tree_test.go (about) 1 package merkle 2 3 import ( 4 "encoding/hex" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 10 tmrand "github.com/tendermint/tendermint/libs/rand" 11 . "github.com/tendermint/tendermint/libs/test" 12 13 "github.com/tendermint/tendermint/crypto/tmhash" 14 ) 15 16 type testItem []byte 17 18 func (tI testItem) Hash() []byte { 19 return []byte(tI) 20 } 21 22 func TestHashFromByteSlices(t *testing.T) { 23 testcases := map[string]struct { 24 slices [][]byte 25 expectHash string // in hex format 26 }{ 27 "nil": {nil, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, 28 "empty": {[][]byte{}, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, 29 "single": {[][]byte{{1, 2, 3}}, "054edec1d0211f624fed0cbca9d4f9400b0e491c43742af2c5b0abebf0c990d8"}, 30 "single blank": {[][]byte{{}}, "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"}, 31 "two": {[][]byte{{1, 2, 3}, {4, 5, 6}}, "82e6cfce00453804379b53962939eaa7906b39904be0813fcadd31b100773c4b"}, 32 "many": { 33 [][]byte{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}}, 34 "f326493eceab4f2d9ffbc78c59432a0a005d6ea98392045c74df5d14a113be18", 35 }, 36 } 37 for name, tc := range testcases { 38 tc := tc 39 t.Run(name, func(t *testing.T) { 40 hash := HashFromByteSlices(tc.slices) 41 assert.Equal(t, tc.expectHash, hex.EncodeToString(hash)) 42 }) 43 } 44 } 45 46 func TestProof(t *testing.T) { 47 48 // Try an empty proof first 49 rootHash, proofs := ProofsFromByteSlices([][]byte{}) 50 require.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", hex.EncodeToString(rootHash)) 51 require.Empty(t, proofs) 52 53 total := 100 54 55 items := make([][]byte, total) 56 for i := 0; i < total; i++ { 57 items[i] = testItem(tmrand.Bytes(tmhash.Size)) 58 } 59 60 rootHash = HashFromByteSlices(items) 61 62 rootHash2, proofs := ProofsFromByteSlices(items) 63 64 require.Equal(t, rootHash, rootHash2, "Unmatched root hashes: %X vs %X", rootHash, rootHash2) 65 66 // For each item, check the trail. 67 for i, item := range items { 68 proof := proofs[i] 69 70 // Check total/index 71 require.EqualValues(t, proof.Index, i, "Unmatched indicies: %d vs %d", proof.Index, i) 72 73 require.EqualValues(t, proof.Total, total, "Unmatched totals: %d vs %d", proof.Total, total) 74 75 // Verify success 76 err := proof.Verify(rootHash, item) 77 require.NoError(t, err, "Verification failed: %v.", err) 78 79 // Trail too long should make it fail 80 origAunts := proof.Aunts 81 proof.Aunts = append(proof.Aunts, tmrand.Bytes(32)) 82 err = proof.Verify(rootHash, item) 83 require.Error(t, err, "Expected verification to fail for wrong trail length") 84 85 proof.Aunts = origAunts 86 87 // Trail too short should make it fail 88 proof.Aunts = proof.Aunts[0 : len(proof.Aunts)-1] 89 err = proof.Verify(rootHash, item) 90 require.Error(t, err, "Expected verification to fail for wrong trail length") 91 92 proof.Aunts = origAunts 93 94 // Mutating the itemHash should make it fail. 95 err = proof.Verify(rootHash, MutateByteSlice(item)) 96 require.Error(t, err, "Expected verification to fail for mutated leaf hash") 97 98 // Mutating the rootHash should make it fail. 99 err = proof.Verify(MutateByteSlice(rootHash), item) 100 require.Error(t, err, "Expected verification to fail for mutated root hash") 101 } 102 } 103 104 func TestHashAlternatives(t *testing.T) { 105 106 total := 100 107 108 items := make([][]byte, total) 109 for i := 0; i < total; i++ { 110 items[i] = testItem(tmrand.Bytes(tmhash.Size)) 111 } 112 113 rootHash1 := HashFromByteSlicesIterative(items) 114 rootHash2 := HashFromByteSlices(items) 115 require.Equal(t, rootHash1, rootHash2, "Unmatched root hashes: %X vs %X", rootHash1, rootHash2) 116 } 117 118 func BenchmarkHashAlternatives(b *testing.B) { 119 total := 100 120 121 items := make([][]byte, total) 122 for i := 0; i < total; i++ { 123 items[i] = testItem(tmrand.Bytes(tmhash.Size)) 124 } 125 126 b.ResetTimer() 127 b.Run("recursive", func(b *testing.B) { 128 for i := 0; i < b.N; i++ { 129 _ = HashFromByteSlices(items) 130 } 131 }) 132 133 b.Run("iterative", func(b *testing.B) { 134 for i := 0; i < b.N; i++ { 135 _ = HashFromByteSlicesIterative(items) 136 } 137 }) 138 } 139 140 func Test_getSplitPoint(t *testing.T) { 141 tests := []struct { 142 length int64 143 want int64 144 }{ 145 {1, 0}, 146 {2, 1}, 147 {3, 2}, 148 {4, 2}, 149 {5, 4}, 150 {10, 8}, 151 {20, 16}, 152 {100, 64}, 153 {255, 128}, 154 {256, 128}, 155 {257, 256}, 156 } 157 for _, tt := range tests { 158 got := getSplitPoint(tt.length) 159 require.EqualValues(t, tt.want, got, "getSplitPoint(%d) = %v, want %v", tt.length, got, tt.want) 160 } 161 }