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