github.com/bchainhub/blockbook@v0.3.2/bchain/coins/btc/bitcoinparser_test.go (about) 1 // +build unittest 2 3 package btc 4 5 import ( 6 "blockbook/bchain" 7 "encoding/hex" 8 "math/big" 9 "os" 10 "reflect" 11 "testing" 12 13 "github.com/martinboehm/btcutil/chaincfg" 14 ) 15 16 func TestMain(m *testing.M) { 17 c := m.Run() 18 chaincfg.ResetParams() 19 os.Exit(c) 20 } 21 22 func TestGetAddrDescFromAddress(t *testing.T) { 23 type args struct { 24 address string 25 } 26 tests := []struct { 27 name string 28 args args 29 want string 30 wantErr bool 31 }{ 32 { 33 name: "P2PKH", 34 args: args{address: "1JKgN43B9SyLuZH19H5ECvr4KcfrbVHzZ6"}, 35 want: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac", 36 wantErr: false, 37 }, 38 { 39 name: "P2PKH from P2PK", 40 args: args{address: "1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE"}, 41 want: "76a914b563933904dceba5c234e978bea0e9eb8b7e721b88ac", 42 wantErr: false, 43 }, 44 { 45 name: "P2SH", 46 args: args{address: "321x69Cb9HZLWwAWGiUBT1U81r1zPLnEjL"}, 47 want: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87", 48 wantErr: false, 49 }, 50 { 51 name: "P2WPKH", 52 args: args{address: "bc1qrsf2l34jvqnq0lduyz0j5pfu2nkd93nnq0qggn"}, 53 want: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673", 54 wantErr: false, 55 }, 56 { 57 name: "P2WSH", 58 args: args{address: "bc1qqwtn5s8vjnqdzrm0du885c46ypzt05vakmljhasx28shlv5a355sw5exgr"}, 59 want: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29", 60 wantErr: false, 61 }, 62 } 63 parser := NewBitcoinParser(GetChainParams("main"), &Configuration{}) 64 65 for _, tt := range tests { 66 t.Run(tt.name, func(t *testing.T) { 67 got, err := parser.GetAddrDescFromAddress(tt.args.address) 68 if (err != nil) != tt.wantErr { 69 t.Errorf("GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr) 70 return 71 } 72 h := hex.EncodeToString(got) 73 if !reflect.DeepEqual(h, tt.want) { 74 t.Errorf("GetAddrDescFromAddress() = %v, want %v", h, tt.want) 75 } 76 }) 77 } 78 } 79 80 func TestGetAddrDescFromVout(t *testing.T) { 81 type args struct { 82 vout bchain.Vout 83 } 84 tests := []struct { 85 name string 86 args args 87 want string 88 wantErr bool 89 }{ 90 { 91 name: "P2PKH", 92 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac"}}}, 93 want: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac", 94 wantErr: false, 95 }, 96 { 97 name: "P2PK compressed 1P3rU1Nk1pmc2BiWC8dEy9bZa1ZbMp5jfg", 98 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "21020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac"}}}, 99 want: "76a914f1dce4182fce875748c4986b240ff7d7bc3fffb088ac", 100 wantErr: false, 101 }, 102 { 103 name: "P2PK uncompressed 1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE", 104 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "41041057356b91bfd3efeff5fc0fa8b865faafafb67bd653c5da2cd16ce15c7b86db0e622c8e1e135f68918a23601eb49208c1ac72c7b64a4ee99c396cf788da16ccac"}}}, 105 want: "76a914b563933904dceba5c234e978bea0e9eb8b7e721b88ac", 106 wantErr: false, 107 }, 108 { 109 name: "P2SH", 110 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87"}}}, 111 want: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87", 112 wantErr: false, 113 }, 114 { 115 name: "P2WPKH", 116 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673"}}}, 117 want: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673", 118 wantErr: false, 119 }, 120 { 121 name: "P2WSH", 122 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29"}}}, 123 want: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29", 124 wantErr: false, 125 }, 126 } 127 parser := NewBitcoinParser(GetChainParams("main"), &Configuration{}) 128 129 for _, tt := range tests { 130 t.Run(tt.name, func(t *testing.T) { 131 got, err := parser.GetAddrDescFromVout(&tt.args.vout) 132 if (err != nil) != tt.wantErr { 133 t.Errorf("GetAddrDescFromVout() error = %v, wantErr %v", err, tt.wantErr) 134 return 135 } 136 h := hex.EncodeToString(got) 137 if !reflect.DeepEqual(h, tt.want) { 138 t.Errorf("GetAddrDescFromVout() = %v, want %v", h, tt.want) 139 } 140 }) 141 } 142 } 143 144 func TestGetAddressesFromAddrDesc(t *testing.T) { 145 type args struct { 146 script string 147 } 148 tests := []struct { 149 name string 150 args args 151 want []string 152 want2 bool 153 wantErr bool 154 }{ 155 { 156 name: "P2PKH", 157 args: args{script: "76a914be027bf3eac907bd4ac8cb9c5293b6f37662722088ac"}, 158 want: []string{"1JKgN43B9SyLuZH19H5ECvr4KcfrbVHzZ6"}, 159 want2: true, 160 wantErr: false, 161 }, 162 { 163 name: "P2PK compressed", 164 args: args{script: "21020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac"}, 165 want: []string{"1P3rU1Nk1pmc2BiWC8dEy9bZa1ZbMp5jfg"}, 166 want2: false, 167 wantErr: false, 168 }, 169 { 170 name: "P2PK uncompressed", 171 args: args{script: "41041057356b91bfd3efeff5fc0fa8b865faafafb67bd653c5da2cd16ce15c7b86db0e622c8e1e135f68918a23601eb49208c1ac72c7b64a4ee99c396cf788da16ccac"}, 172 want: []string{"1HY6bKYhFH7HF3F48ikvziPHLrEWPGwXcE"}, 173 want2: false, 174 wantErr: false, 175 }, 176 { 177 name: "P2SH", 178 args: args{script: "a9140394b3cf9a44782c10105b93962daa8dba304d7f87"}, 179 want: []string{"321x69Cb9HZLWwAWGiUBT1U81r1zPLnEjL"}, 180 want2: true, 181 wantErr: false, 182 }, 183 { 184 name: "P2WPKH", 185 args: args{script: "00141c12afc6b2602607fdbc209f2a053c54ecd2c673"}, 186 want: []string{"bc1qrsf2l34jvqnq0lduyz0j5pfu2nkd93nnq0qggn"}, 187 want2: true, 188 wantErr: false, 189 }, 190 { 191 name: "P2WSH", 192 args: args{script: "002003973a40ec94c0d10f6f6f0e7a62ba2044b7d19db6ff2bf60651e17fb29d8d29"}, 193 want: []string{"bc1qqwtn5s8vjnqdzrm0du885c46ypzt05vakmljhasx28shlv5a355sw5exgr"}, 194 want2: true, 195 wantErr: false, 196 }, 197 { 198 name: "OP_RETURN ascii", 199 args: args{script: "6a0461686f6a"}, 200 want: []string{"OP_RETURN (ahoj)"}, 201 want2: false, 202 wantErr: false, 203 }, 204 { 205 name: "OP_RETURN OP_PUSHDATA1 ascii", 206 args: args{script: "6a4c0b446c6f7568792074657874"}, 207 want: []string{"OP_RETURN (Dlouhy text)"}, 208 want2: false, 209 wantErr: false, 210 }, 211 { 212 name: "OP_RETURN hex", 213 args: args{script: "6a072020f1686f6a20"}, 214 want: []string{"OP_RETURN 2020f1686f6a20"}, 215 want2: false, 216 wantErr: false, 217 }, 218 { 219 name: "OP_RETURN omni simple send tether", 220 args: args{script: "6a146f6d6e69000000000000001f00000709bb647351"}, 221 want: []string{"OMNI Simple Send: 77383.80022609 TetherUS (#31)"}, 222 want2: false, 223 wantErr: false, 224 }, 225 { 226 name: "OP_RETURN omni simple send not supported coin", 227 args: args{script: "6a146f6d6e69000000000000000300000709bb647351"}, 228 want: []string{"OP_RETURN 6f6d6e69000000000000000300000709bb647351"}, 229 want2: false, 230 wantErr: false, 231 }, 232 { 233 name: "OP_RETURN omni not supported version", 234 args: args{script: "6a146f6d6e69010000000000000300000709bb647351"}, 235 want: []string{"OP_RETURN 6f6d6e69010000000000000300000709bb647351"}, 236 want2: false, 237 wantErr: false, 238 }, 239 } 240 241 parser := NewBitcoinParser(GetChainParams("main"), &Configuration{}) 242 243 for _, tt := range tests { 244 t.Run(tt.name, func(t *testing.T) { 245 b, _ := hex.DecodeString(tt.args.script) 246 got, got2, err := parser.GetAddressesFromAddrDesc(b) 247 if (err != nil) != tt.wantErr { 248 t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr) 249 return 250 } 251 if !reflect.DeepEqual(got, tt.want) { 252 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want) 253 } 254 if !reflect.DeepEqual(got2, tt.want2) { 255 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2) 256 } 257 }) 258 } 259 } 260 261 var ( 262 testTx1, testTx2 bchain.Tx 263 264 testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700" 265 testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000" 266 ) 267 268 func init() { 269 testTx1 = bchain.Tx{ 270 Hex: "01000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700", 271 Blocktime: 1519053802, 272 Txid: "056e3d82e5ffd0e915fb9b62797d76263508c34fe3e5dbed30dd3e943930f204", 273 LockTime: 512115, 274 Version: 1, 275 Vin: []bchain.Vin{ 276 { 277 ScriptSig: bchain.ScriptSig{ 278 Hex: "4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80", 279 }, 280 Txid: "425fed43ba74e9205875eb934d5bcf7bf338f146f70d4002d94bf5cbc9229a7f", 281 Vout: 4, 282 Sequence: 4294967294, 283 }, 284 }, 285 Vout: []bchain.Vout{ 286 { 287 ValueSat: *big.NewInt(38812), 288 N: 0, 289 ScriptPubKey: bchain.ScriptPubKey{ 290 Hex: "a9146144d57c8aff48492c9dfb914e120b20bad72d6f87", 291 Addresses: []string{ 292 "3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", 293 }, 294 }, 295 }, 296 }, 297 } 298 299 testTx2 = bchain.Tx{ 300 Hex: "010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000", 301 Blocktime: 1235678901, 302 Txid: "474e6795760ebe81cb4023dc227e5a0efe340e1771c89a0035276361ed733de7", 303 LockTime: 0, 304 Version: 1, 305 Vin: []bchain.Vin{ 306 { 307 ScriptSig: bchain.ScriptSig{ 308 Hex: "160014550da1f5d25a9dae2eafd6902b4194c4c6500af6", 309 }, 310 Txid: "c13e32a4428e31f85d7aee4ec7344504b12e72aaffcbde0160200d2ac7f0649d", 311 Vout: 0, 312 Sequence: 4294967295, 313 }, 314 }, 315 Vout: []bchain.Vout{ 316 { 317 ValueSat: *big.NewInt(10000000), 318 N: 0, 319 ScriptPubKey: bchain.ScriptPubKey{ 320 Hex: "a914cd668d781ece600efa4b2404dc91fd26b8b8aed887", 321 Addresses: []string{ 322 "2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", 323 }, 324 }, 325 }, 326 { 327 ValueSat: *big.NewInt(920081157), 328 N: 1, 329 ScriptPubKey: bchain.ScriptPubKey{ 330 Hex: "a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a87", 331 Addresses: []string{ 332 "2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", 333 }, 334 }, 335 }, 336 }, 337 } 338 } 339 340 func TestPackTx(t *testing.T) { 341 type args struct { 342 tx bchain.Tx 343 height uint32 344 blockTime int64 345 parser *BitcoinParser 346 } 347 tests := []struct { 348 name string 349 args args 350 want string 351 wantErr bool 352 }{ 353 { 354 name: "btc-1", 355 args: args{ 356 tx: testTx1, 357 height: 123456, 358 blockTime: 1519053802, 359 parser: NewBitcoinParser(GetChainParams("main"), &Configuration{}), 360 }, 361 want: testTxPacked1, 362 wantErr: false, 363 }, 364 { 365 name: "testnet-1", 366 args: args{ 367 tx: testTx2, 368 height: 510234, 369 blockTime: 1235678901, 370 parser: NewBitcoinParser(GetChainParams("test"), &Configuration{}), 371 }, 372 want: testTxPacked2, 373 wantErr: false, 374 }, 375 } 376 for _, tt := range tests { 377 t.Run(tt.name, func(t *testing.T) { 378 got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime) 379 if (err != nil) != tt.wantErr { 380 t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr) 381 return 382 } 383 h := hex.EncodeToString(got) 384 if !reflect.DeepEqual(h, tt.want) { 385 t.Errorf("packTx() = %v, want %v", h, tt.want) 386 } 387 }) 388 } 389 } 390 391 func TestUnpackTx(t *testing.T) { 392 type args struct { 393 packedTx string 394 parser *BitcoinParser 395 } 396 tests := []struct { 397 name string 398 args args 399 want *bchain.Tx 400 want1 uint32 401 wantErr bool 402 }{ 403 { 404 name: "btc-1", 405 args: args{ 406 packedTx: testTxPacked1, 407 parser: NewBitcoinParser(GetChainParams("main"), &Configuration{}), 408 }, 409 want: &testTx1, 410 want1: 123456, 411 wantErr: false, 412 }, 413 { 414 name: "testnet-1", 415 args: args{ 416 packedTx: testTxPacked2, 417 parser: NewBitcoinParser(GetChainParams("test"), &Configuration{}), 418 }, 419 want: &testTx2, 420 want1: 510234, 421 wantErr: false, 422 }, 423 } 424 for _, tt := range tests { 425 t.Run(tt.name, func(t *testing.T) { 426 b, _ := hex.DecodeString(tt.args.packedTx) 427 got, got1, err := tt.args.parser.UnpackTx(b) 428 if (err != nil) != tt.wantErr { 429 t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr) 430 return 431 } 432 if !reflect.DeepEqual(got, tt.want) { 433 t.Errorf("unpackTx() got = %v, want %v", got, tt.want) 434 } 435 if got1 != tt.want1 { 436 t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1) 437 } 438 }) 439 } 440 } 441 442 func TestDeriveAddressDescriptors(t *testing.T) { 443 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518}) 444 type args struct { 445 xpub string 446 change uint32 447 indexes []uint32 448 parser *BitcoinParser 449 } 450 tests := []struct { 451 name string 452 args args 453 want []string 454 wantErr bool 455 }{ 456 { 457 name: "m/44'/0'/0'", 458 args: args{ 459 xpub: "xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj", 460 change: 0, 461 indexes: []uint32{0, 1234}, 462 parser: btcMainParser, 463 }, 464 want: []string{"1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA", "1P9w11dXAmG3QBjKLAvCsek8izs1iR2iFi"}, 465 }, 466 { 467 name: "m/49'/0'/0'", 468 args: args{ 469 xpub: "ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP", 470 change: 0, 471 indexes: []uint32{0, 1234}, 472 parser: btcMainParser, 473 }, 474 want: []string{"37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", "367meFzJ9KqDLm9PX6U8Z8RdmkSNBuxX8T"}, 475 }, 476 { 477 name: "m/84'/0'/0'", 478 args: args{ 479 xpub: "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 480 change: 0, 481 indexes: []uint32{0, 1234}, 482 parser: btcMainParser, 483 }, 484 want: []string{"bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", "bc1q4nm6g46ujzyjaeusralaz2nfv2rf04jjfyamkw"}, 485 }, 486 } 487 for _, tt := range tests { 488 t.Run(tt.name, func(t *testing.T) { 489 got, err := tt.args.parser.DeriveAddressDescriptors(tt.args.xpub, tt.args.change, tt.args.indexes) 490 if (err != nil) != tt.wantErr { 491 t.Errorf("DeriveAddressDescriptorsFromTo() error = %v, wantErr %v", err, tt.wantErr) 492 return 493 } 494 gotAddresses := make([]string, len(got)) 495 for i, ad := range got { 496 aa, _, err := tt.args.parser.GetAddressesFromAddrDesc(ad) 497 if err != nil || len(aa) != 1 { 498 t.Errorf("DeriveAddressDescriptorsFromTo() got incorrect address descriptor %v, error %v", ad, err) 499 return 500 } 501 gotAddresses[i] = aa[0] 502 } 503 if !reflect.DeepEqual(gotAddresses, tt.want) { 504 t.Errorf("DeriveAddressDescriptorsFromTo() = %v, want %v", gotAddresses, tt.want) 505 } 506 }) 507 } 508 } 509 510 func TestDeriveAddressDescriptorsFromTo(t *testing.T) { 511 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518}) 512 btcTestnetsParser := NewBitcoinParser(GetChainParams("test"), &Configuration{XPubMagic: 70617039, XPubMagicSegwitP2sh: 71979618, XPubMagicSegwitNative: 73342198}) 513 type args struct { 514 xpub string 515 change uint32 516 fromIndex uint32 517 toIndex uint32 518 parser *BitcoinParser 519 } 520 tests := []struct { 521 name string 522 args args 523 want []string 524 wantErr bool 525 }{ 526 { 527 name: "m/44'/0'/0'", 528 args: args{ 529 xpub: "xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj", 530 change: 0, 531 fromIndex: 0, 532 toIndex: 1, 533 parser: btcMainParser, 534 }, 535 want: []string{"1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA"}, 536 }, 537 { 538 name: "m/49'/0'/0'", 539 args: args{ 540 xpub: "ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP", 541 change: 0, 542 fromIndex: 0, 543 toIndex: 1, 544 parser: btcMainParser, 545 }, 546 want: []string{"37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"}, 547 }, 548 { 549 name: "m/84'/0'/0'", 550 args: args{ 551 xpub: "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 552 change: 0, 553 fromIndex: 0, 554 toIndex: 1, 555 parser: btcMainParser, 556 }, 557 want: []string{"bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu"}, 558 }, 559 { 560 name: "m/49'/1'/0'", 561 args: args{ 562 xpub: "upub5DR1Mg5nykixzYjFXWW5GghAU7dDqoPVJ2jrqFbL8sJ7Hs7jn69MP7KBnnmxn88GeZtnH8PRKV9w5MMSFX8AdEAoXY8Qd8BJPoXtpMeHMxJ", 563 change: 0, 564 fromIndex: 0, 565 toIndex: 10, 566 parser: btcTestnetsParser, 567 }, 568 want: []string{"2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", "2Mt7P2BAfE922zmfXrdcYTLyR7GUvbwSEns", "2N6aUMgQk8y1zvoq6FeWFyotyj75WY9BGsu", "2NA7tbZWM9BcRwBuebKSQe2xbhhF1paJwBM", "2N8RZMzvrUUnpLmvACX9ysmJ2MX3GK5jcQM", "2MvUUSiQZDSqyeSdofKX9KrSCio1nANPDTe", "2NBXaWu1HazjoUVgrXgcKNoBLhtkkD9Gmet", "2N791Ttf89tMVw2maj86E1Y3VgxD9Mc7PU7", "2NCJmwEq8GJm8t8GWWyBXAfpw7F2qZEVP5Y", "2NEgW71hWKer2XCSA8ZCC2VnWpB77L6bk68"}, 569 }, 570 } 571 for _, tt := range tests { 572 t.Run(tt.name, func(t *testing.T) { 573 got, err := tt.args.parser.DeriveAddressDescriptorsFromTo(tt.args.xpub, tt.args.change, tt.args.fromIndex, tt.args.toIndex) 574 if (err != nil) != tt.wantErr { 575 t.Errorf("DeriveAddressDescriptorsFromTo() error = %v, wantErr %v", err, tt.wantErr) 576 return 577 } 578 gotAddresses := make([]string, len(got)) 579 for i, ad := range got { 580 aa, _, err := tt.args.parser.GetAddressesFromAddrDesc(ad) 581 if err != nil || len(aa) != 1 { 582 t.Errorf("DeriveAddressDescriptorsFromTo() got incorrect address descriptor %v, error %v", ad, err) 583 return 584 } 585 gotAddresses[i] = aa[0] 586 } 587 if !reflect.DeepEqual(gotAddresses, tt.want) { 588 t.Errorf("DeriveAddressDescriptorsFromTo() = %v, want %v", gotAddresses, tt.want) 589 } 590 }) 591 } 592 } 593 594 func BenchmarkDeriveAddressDescriptorsFromToXpub(b *testing.B) { 595 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518}) 596 for i := 0; i < b.N; i++ { 597 btcMainParser.DeriveAddressDescriptorsFromTo("xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj", 1, 0, 100) 598 } 599 } 600 601 func BenchmarkDeriveAddressDescriptorsFromToYpub(b *testing.B) { 602 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518}) 603 for i := 0; i < b.N; i++ { 604 btcMainParser.DeriveAddressDescriptorsFromTo("ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP", 1, 0, 100) 605 } 606 } 607 608 func BenchmarkDeriveAddressDescriptorsFromToZpub(b *testing.B) { 609 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518}) 610 for i := 0; i < b.N; i++ { 611 btcMainParser.DeriveAddressDescriptorsFromTo("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 1, 0, 100) 612 } 613 } 614 615 func TestBitcoinParser_DerivationBasePath(t *testing.T) { 616 btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518, Slip44: 0}) 617 btcTestnetsParser := NewBitcoinParser(GetChainParams("test"), &Configuration{XPubMagic: 70617039, XPubMagicSegwitP2sh: 71979618, XPubMagicSegwitNative: 73342198, Slip44: 1}) 618 zecMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, Slip44: 133}) 619 type args struct { 620 xpub string 621 parser *BitcoinParser 622 } 623 tests := []struct { 624 name string 625 args args 626 want string 627 wantErr bool 628 }{ 629 { 630 name: "m/84'/0'/0'", 631 args: args{ 632 xpub: "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 633 parser: btcMainParser, 634 }, 635 want: "m/84'/0'/0'", 636 }, 637 { 638 name: "m/49'/0'/55 - not hardened account", 639 args: args{ 640 xpub: "ypub6XKbB5DJRAbW4TRJLp4uXQXG3ob5BtByXsNZFBjq9qcbzrczjVXfCz5cEo1SFDexmeWRnbCMDaRgaW4m9d2nBaa8FvUQCu3n9G1UBR8WhbT", 641 parser: btcMainParser, 642 }, 643 want: "m/49'/0'/55", 644 }, 645 { 646 name: "m/49'/0' - incomplete path, without account", 647 args: args{ 648 xpub: "ypub6UzM8PUqxcSoqC9gumfoiFhE8Qt84HbGpCD4eVJfJAojXTVtBxeddvTWJGJhGoaVBNJLmEgMdLXHgaLVJa4xEvk2tcokkdZhFdkxMLUE9sB", 649 parser: btcMainParser, 650 }, 651 want: "unknown/0'", 652 }, 653 { 654 name: "m/49'/1'/0'", 655 args: args{ 656 xpub: "upub5DR1Mg5nykixzYjFXWW5GghAU7dDqoPVJ2jrqFbL8sJ7Hs7jn69MP7KBnnmxn88GeZtnH8PRKV9w5MMSFX8AdEAoXY8Qd8BJPoXtpMeHMxJ", 657 parser: btcTestnetsParser, 658 }, 659 want: "m/49'/1'/0'", 660 }, 661 { 662 name: "m/44'/133'/12'", 663 args: args{ 664 xpub: "xpub6CQdEahwhKRTLYpP6cyb7ZaGb3r4tVdyPX6dC1PfrNuByrCkWDgUkmpD28UdV9QccKgY1ZiAbGv1Fakcg2LxdFVSTNKHcjdRjqhjPK8Trkb", 665 parser: zecMainParser, 666 }, 667 want: "m/44'/133'/12'", 668 }, 669 } 670 for _, tt := range tests { 671 t.Run(tt.name, func(t *testing.T) { 672 got, err := tt.args.parser.DerivationBasePath(tt.args.xpub) 673 if (err != nil) != tt.wantErr { 674 t.Errorf("BitcoinParser.DerivationBasePath() error = %v, wantErr %v", err, tt.wantErr) 675 return 676 } 677 if got != tt.want { 678 t.Errorf("BitcoinParser.DerivationBasePath() = %v, want %v", got, tt.want) 679 } 680 }) 681 } 682 }