github.com/decred/dcrlnd@v0.7.6/shachain/element_test.go (about) 1 package shachain 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/go-errors/errors" 8 ) 9 10 // bitsToIndex is a helper function which takes 'n' last bits as input and 11 // create shachain index. 12 // Example: 13 // 14 // Input: 0,1,1,0,0 15 // Output: 0b000000000000000000000000000000000000000[01100] == 12 16 func bitsToIndex(bs ...uint64) (index, error) { 17 if len(bs) > 64 { 18 return 0, errors.New("number of elements should be lower then" + 19 " 64") 20 } 21 22 var res uint64 23 for i, e := range bs { 24 if e != 1 && e != 0 { 25 return 0, errors.New("wrong element, should be '0' or" + 26 " '1'") 27 } 28 29 res += e * 1 << uint(len(bs)-i-1) 30 } 31 32 return index(res), nil 33 } 34 35 type deriveTest struct { 36 name string 37 from index 38 to index 39 position []uint8 40 shouldFail bool 41 } 42 43 func generateTests(t *testing.T) []deriveTest { 44 var ( 45 tests []deriveTest 46 from index 47 to index 48 err error 49 ) 50 51 from, err = bitsToIndex(0) 52 if err != nil { 53 t.Fatalf("can't generate from index: %v", err) 54 } 55 to, err = bitsToIndex(0) 56 if err != nil { 57 t.Fatalf("can't generate from index: %v", err) 58 } 59 tests = append(tests, deriveTest{ 60 name: "zero 'from' 'to'", 61 from: from, 62 to: to, 63 position: nil, 64 shouldFail: false, 65 }) 66 67 from, err = bitsToIndex(0, 1, 0, 0) 68 if err != nil { 69 t.Fatalf("can't generate from index: %v", err) 70 } 71 to, err = bitsToIndex(0, 1, 0, 0) 72 if err != nil { 73 t.Fatalf("can't generate from index: %v", err) 74 } 75 tests = append(tests, deriveTest{ 76 name: "same indexes #1", 77 from: from, 78 to: to, 79 position: nil, 80 shouldFail: false, 81 }) 82 83 from, err = bitsToIndex(1) 84 if err != nil { 85 t.Fatalf("can't generate from index: %v", err) 86 } 87 to, err = bitsToIndex(0) 88 if err != nil { 89 t.Fatalf("can't generate from index: %v", err) 90 } 91 tests = append(tests, deriveTest{ 92 name: "same indexes #2", 93 from: from, 94 to: to, 95 shouldFail: true, 96 }) 97 98 from, err = bitsToIndex(0, 0, 0, 0) 99 if err != nil { 100 t.Fatalf("can't generate from index: %v", err) 101 } 102 to, err = bitsToIndex(0, 0, 1, 0) 103 if err != nil { 104 t.Fatalf("can't generate from index: %v", err) 105 } 106 tests = append(tests, deriveTest{ 107 name: "test seed 'from'", 108 from: from, 109 to: to, 110 position: []uint8{1}, 111 shouldFail: false, 112 }) 113 114 from, err = bitsToIndex(1, 1, 0, 0) 115 if err != nil { 116 t.Fatalf("can't generate from index: %v", err) 117 } 118 to, err = bitsToIndex(0, 1, 0, 0) 119 if err != nil { 120 t.Fatalf("can't generate from index: %v", err) 121 } 122 tests = append(tests, deriveTest{ 123 name: "not the same indexes", 124 from: from, 125 to: to, 126 shouldFail: true, 127 }) 128 129 from, err = bitsToIndex(1, 0, 1, 0) 130 if err != nil { 131 t.Fatalf("can't generate from index: %v", err) 132 } 133 to, err = bitsToIndex(1, 0, 0, 0) 134 if err != nil { 135 t.Fatalf("can't generate from index: %v", err) 136 } 137 tests = append(tests, deriveTest{ 138 name: "'from' index greater then 'to' index", 139 from: from, 140 to: to, 141 shouldFail: true, 142 }) 143 144 from, err = bitsToIndex(1) 145 if err != nil { 146 t.Fatalf("can't generate from index: %v", err) 147 } 148 to, err = bitsToIndex(1) 149 if err != nil { 150 t.Fatalf("can't generate from index: %v", err) 151 } 152 tests = append(tests, deriveTest{ 153 name: "zero number trailing zeros", 154 from: from, 155 to: to, 156 position: nil, 157 shouldFail: false, 158 }) 159 160 return tests 161 } 162 163 // TestDeriveIndex check the correctness of index derive function by testing 164 // the index corner cases. 165 func TestDeriveIndex(t *testing.T) { 166 t.Parallel() 167 168 for _, test := range generateTests(t) { 169 pos, err := test.from.deriveBitTransformations(test.to) 170 if err != nil { 171 if !test.shouldFail { 172 t.Fatalf("Failed (%v): %v", test.name, err) 173 } 174 } else { 175 if test.shouldFail { 176 t.Fatalf("Failed (%v): test should failed "+ 177 "but it's not", test.name) 178 } 179 180 if !reflect.DeepEqual(pos, test.position) { 181 t.Fatalf("Failed(%v): position is wrong real:"+ 182 "%v expected:%v", test.name, pos, test.position) 183 } 184 } 185 186 t.Logf("Passed: %v", test.name) 187 188 } 189 } 190 191 // deriveElementTests encodes the test vectors specified in BOLT-03, 192 // Appendix D, Generation Tests. 193 var deriveElementTests = []struct { 194 name string 195 index index 196 output string 197 seed string 198 shouldFail bool 199 }{ 200 { 201 name: "generate_from_seed 0 final node", 202 seed: "0000000000000000000000000000000000000000000000000000000000000000", 203 index: 0xffffffffffff, 204 output: "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", 205 shouldFail: false, 206 }, 207 { 208 name: "generate_from_seed FF final node", 209 seed: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 210 index: 0xffffffffffff, 211 output: "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", 212 shouldFail: false, 213 }, 214 { 215 name: "generate_from_seed FF alternate bits 1", 216 index: 0xaaaaaaaaaaa, 217 output: "56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528", 218 seed: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 219 shouldFail: false, 220 }, 221 { 222 name: "generate_from_seed FF alternate bits 2", 223 index: 0x555555555555, 224 output: "9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31", 225 seed: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 226 shouldFail: false, 227 }, 228 { 229 name: "generate_from_seed 01 last nontrivial node", 230 index: 1, 231 output: "915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c", 232 seed: "0101010101010101010101010101010101010101010101010101010101010101", 233 shouldFail: false, 234 }, 235 } 236 237 // TestSpecificationDeriveElement is used to check the consistency with 238 // specification hash derivation function. 239 func TestSpecificationDeriveElement(t *testing.T) { 240 t.Parallel() 241 242 for _, test := range deriveElementTests { 243 // Generate seed element. 244 element, err := newElementFromStr(test.seed, rootIndex) 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 // Derive element by index. 250 result, err := element.derive(test.index) 251 if err != nil { 252 if !test.shouldFail { 253 t.Fatalf("Failed (%v): %v", test.name, err) 254 } 255 } else { 256 if test.shouldFail { 257 t.Fatalf("Failed (%v): test should failed "+ 258 "but it's not", test.name) 259 } 260 261 // Generate element which we should get after derivation. 262 output, err := newElementFromStr(test.output, test.index) 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 // Check that they are equal. 268 if !result.isEqual(output) { 269 t.Fatalf("Failed (%v): hash is wrong, real:"+ 270 "%x expected:%x", test.name, 271 result.hash, output.hash) 272 } 273 } 274 275 t.Logf("Passed (%v)", test.name) 276 } 277 }