github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/firo/firoparser_test.go (about) 1 //go:build unittest 2 3 package firo 4 5 import ( 6 "bytes" 7 "encoding/hex" 8 "encoding/json" 9 "io/ioutil" 10 "math/big" 11 "os" 12 "reflect" 13 "strings" 14 "testing" 15 16 "github.com/martinboehm/btcd/wire" 17 "github.com/martinboehm/btcutil/chaincfg" 18 "github.com/trezor/blockbook/bchain" 19 "github.com/trezor/blockbook/bchain/coins/btc" 20 ) 21 22 var ( 23 testTx1, testTx2, testTx3, testTx4, testTx5, testTx6 bchain.Tx 24 rawTestTx1, rawTestTx2, rawTestTx3, rawTestTx4, rawTestTx5, rawTestTx6 string 25 testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4, testTxPacked5, testTxPacked6 string 26 rawBlock1, rawBlock2, rawBlock3 string 27 jsonTx json.RawMessage 28 ) 29 30 func readHexs(path string) []string { 31 raw, err := ioutil.ReadFile(path) 32 if err != nil { 33 panic(err) 34 } 35 rawStr := string(raw) 36 raws := strings.Split(rawStr, "\n") 37 return raws 38 } 39 40 func init() { 41 rawBlocks := readHexs("./testdata/rawblock.hex") 42 rawBlock1 = rawBlocks[0] 43 rawBlock2 = rawBlocks[1] 44 rawBlock3 = rawBlocks[2] 45 46 hextxs := readHexs("./testdata/txs.hex") 47 rawTestTx1 = hextxs[0] 48 rawTestTx2 = hextxs[1] 49 rawTestTx3 = hextxs[2] 50 rawTestTx4 = hextxs[3] 51 rawTestTx5 = hextxs[4] 52 rawTestTx6 = hextxs[5] 53 54 rawSpendHex := readHexs("./testdata/rawspend.hex")[0] 55 56 rawSpendTx, err := ioutil.ReadFile("./testdata/spendtx.json") 57 if err != nil { 58 panic(err) 59 } 60 jsonTx = json.RawMessage(rawSpendTx) 61 62 testTxPackeds := readHexs("./testdata/packedtxs.hex") 63 testTxPacked1 = testTxPackeds[0] 64 testTxPacked2 = testTxPackeds[1] 65 testTxPacked3 = testTxPackeds[2] 66 testTxPacked4 = testTxPackeds[3] 67 testTxPacked5 = testTxPackeds[4] 68 testTxPacked6 = testTxPackeds[5] 69 70 testTx1 = bchain.Tx{ 71 Hex: rawTestTx1, 72 Blocktime: 1533980594, 73 Time: 1533980594, 74 Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23", 75 LockTime: 99688, 76 Vin: []bchain.Vin{ 77 { 78 ScriptSig: bchain.ScriptSig{ 79 Hex: "47304402205b7d9c9aae790b69017651e10134735928df3b4a4a2feacc9568eb4fa133ed5902203f21a399385ce29dd79831ea34aa535612aa4314c5bd0b002bbbc9bcd2de1436012102b8d462740c99032a00083ac7028879acec244849e54ad0a04ea87f632f54b1d2", 80 }, 81 Txid: "463a2d66b04636a014da35724909425f3403d9d786dd4f79780de50d47b18716", 82 Vout: 1, 83 Sequence: 4294967294, 84 }, 85 }, 86 Vout: []bchain.Vout{ 87 { 88 ValueSat: *big.NewInt(100000000), 89 N: 0, 90 ScriptPubKey: bchain.ScriptPubKey{ 91 Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28", 92 }, 93 }, 94 { 95 ValueSat: *big.NewInt(871824000), 96 N: 1, 97 ScriptPubKey: bchain.ScriptPubKey{ 98 Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac", 99 Addresses: []string{ 100 "aK5KKi8qqDbspcXFfDjx8UBGMouhYbYZVp", 101 }, 102 }, 103 }, 104 }, 105 } 106 107 testTx2 = bchain.Tx{ 108 Hex: rawTestTx2, 109 Blocktime: 1481277009, 110 Time: 1481277009, 111 Txid: "3d721fdce2855e2b4a54b74a26edd58a7262e1f195b5acaaae7832be6e0b3d32", 112 LockTime: 0, 113 Vin: []bchain.Vin{ 114 { 115 Coinbase: rawSpendHex, 116 Txid: "0000000000000000000000000000000000000000000000000000000000000000", 117 Vout: 4294967295, 118 Sequence: 2, 119 }, 120 }, 121 Vout: []bchain.Vout{ 122 { 123 ValueSat: *big.NewInt(5000000000), 124 N: 0, 125 ScriptPubKey: bchain.ScriptPubKey{ 126 Hex: "76a914b9e262e30df03e88ccea312652bc83ca7290c8fc88ac", 127 Addresses: []string{ 128 "aHfKwzFZMiSxDuNL4jts819nh57t2yJG1h", 129 }, 130 }, 131 }, 132 }, 133 } 134 135 testTx3 = bchain.Tx{ 136 Hex: rawTestTx3, 137 Blocktime: 1547091829, 138 Time: 1547091829, 139 Txid: "96ae951083651f141d1fb2719c76d47e5a3ad421b81905f679c0edb60f2de0ff", 140 LockTime: 126200, 141 Vin: []bchain.Vin{ 142 { 143 ScriptSig: bchain.ScriptSig{ 144 Hex: "483045022100bdc6b51c114617e29e28390dc9b3ad95b833ca3d1f0429ba667c58a667f9124702204ca2ed362dd9ef723ddbdcf4185b47c28b127a36f46bc4717662be863309b3e601210387e7ff08b953e3736955408fc6ebcd8aa84a04cc4b45758ea29cc2cfe1820535", 145 }, 146 Txid: "448ccfd9c3f375be8701b86aff355a230dbe240334233f2ed476fcae6abd295d", 147 Vout: 1, 148 Sequence: 4294967294, 149 }, 150 }, 151 Vout: []bchain.Vout{ 152 { 153 ValueSat: *big.NewInt(42000000000), 154 N: 0, 155 ScriptPubKey: bchain.ScriptPubKey{ 156 Hex: "76a91429bef7962c5c65a2f0f4f7d9ec791866c54f851688ac", 157 Addresses: []string{ 158 "a4XCDQ7AnRH9opZ4h6LcG3g7ocSV2SbBmS", 159 }, 160 }, 161 }, 162 { 163 ValueSat: *big.NewInt(107300000000), 164 N: 1, 165 ScriptPubKey: bchain.ScriptPubKey{ 166 Hex: "76a914e2cee7b71c3a4637dbdfe613f19f4b4f2d070d7f88ac", 167 Addresses: []string{ 168 "aMPiKHB3E1AGPi8kKLknx6j1L4JnKCGkLw", 169 }, 170 }, 171 }, 172 }, 173 } 174 175 testTx4 = bchain.Tx{ 176 Hex: rawTestTx4, 177 Blocktime: 1533977563, 178 Time: 1533977563, 179 Txid: "914ccbdb72f593e5def15978cf5891e1384a1b85e89374fc1c440c074c6dd286", 180 LockTime: 0, 181 Vin: []bchain.Vin{ 182 { 183 Coinbase: "03a1860104dba36e5b082a00077c00000000052f6d70682f", 184 Sequence: 0, 185 }, 186 }, 187 Vout: []bchain.Vout{ 188 { 189 ValueSat: *big.NewInt(2800200000), 190 N: 0, 191 ScriptPubKey: bchain.ScriptPubKey{ 192 Hex: "76a91436e086acf6561a68ba64196e7b92b606d0b8516688ac", 193 Addresses: []string{ 194 "a5idCcHN8WYxvFCeBXSXvMPrZHuBkZmqEJ", 195 }, 196 }, 197 }, 198 { 199 ValueSat: *big.NewInt(1500000000), 200 N: 1, 201 ScriptPubKey: bchain.ScriptPubKey{ 202 Hex: "76a914381a5dd1a279e8e63e67cde39ecfa61a99dd2ba288ac", 203 Addresses: []string{ 204 "a5q7Ad4okSFFVh5adyqx5DT21RTxJykpUM", 205 }, 206 }, 207 }, 208 { 209 ValueSat: *big.NewInt(100000000), 210 N: 2, 211 ScriptPubKey: bchain.ScriptPubKey{ 212 Hex: "76a9147d9ed014fc4e603fca7c2e3f9097fb7d0fb487fc88ac", 213 Addresses: []string{ 214 "aCAgTPgtYcA4EysU4UKC86EQd5cTtHtCcr", 215 }, 216 }, 217 }, 218 { 219 ValueSat: *big.NewInt(100000000), 220 N: 3, 221 ScriptPubKey: bchain.ScriptPubKey{ 222 Hex: "76a914bc7e5a5234db3ab82d74c396ad2b2af419b7517488ac", 223 Addresses: []string{ 224 "aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD", 225 }, 226 }, 227 }, 228 { 229 ValueSat: *big.NewInt(100000000), 230 N: 4, 231 ScriptPubKey: bchain.ScriptPubKey{ 232 Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac", 233 Addresses: []string{ 234 "aQ18FBVFtnueucZKeVg4srhmzbpAeb1KoN", 235 }, 236 }, 237 }, 238 { 239 ValueSat: *big.NewInt(300000000), 240 N: 5, 241 ScriptPubKey: bchain.ScriptPubKey{ 242 Hex: "76a9140654dd9b856f2ece1d56cb4ee5043cd9398d962c88ac", 243 Addresses: []string{ 244 "a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3", 245 }, 246 }, 247 }, 248 { 249 ValueSat: *big.NewInt(100000000), 250 N: 6, 251 ScriptPubKey: bchain.ScriptPubKey{ 252 Hex: "76a9140b4bfb256ef4bfa360e3b9e66e53a0bd84d196bc88ac", 253 Addresses: []string{ 254 "a1kCCGddf5pMXSipLVD9hBG2MGGVNaJ15U", 255 }, 256 }, 257 }, 258 // TODO: test segwit 259 }, 260 } 261 262 testTx5 = bchain.Tx{ 263 Hex: rawTestTx5, 264 Blocktime: 1591752749, 265 Time: 1591752749, 266 Txid: "8d1f32f35c32d2c127a7400dc1ec52049fbf0b8bcdf284cfaa3da59b6169a22d", 267 LockTime: 0, 268 Vin: []bchain.Vin{}, 269 Vout: []bchain.Vout{}, 270 } 271 272 testTx6 = bchain.Tx{ 273 Hex: rawTestTx6, 274 Blocktime: 1591762049, 275 Time: 1591762049, 276 Txid: "e5767d3606230a65f150837a6f28b4f0e4c2702a683045df3883d57702739c61", 277 LockTime: 0, 278 Vin: []bchain.Vin{ 279 { 280 Coinbase: "02b4140101", 281 Sequence: 4294967295, 282 }, 283 }, 284 Vout: []bchain.Vout{ 285 { 286 ValueSat: *big.NewInt(1400000000), 287 N: 0, 288 ScriptPubKey: bchain.ScriptPubKey{ 289 Hex: "2103fb09a216761d5e7f248294970c2370f7f84ce1ad564b8e7096b1e19116af1d52ac", 290 Addresses: []string{ 291 "TAn9Ghkp31myXRgejCj11wWVHT14Lsj349", 292 }, 293 }, 294 }, 295 { 296 ValueSat: *big.NewInt(50000000), 297 N: 1, 298 ScriptPubKey: bchain.ScriptPubKey{ 299 Hex: "76a914296134d2415bf1f2b518b3f673816d7e603b160088ac", 300 Addresses: []string{ 301 "TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo", 302 }, 303 }, 304 }, 305 { 306 ValueSat: *big.NewInt(50000000), 307 N: 2, 308 ScriptPubKey: bchain.ScriptPubKey{ 309 Hex: "76a914e1e1dc06a889c1b6d3eb00eef7a96f6a7cfb884888ac", 310 Addresses: []string{ 311 "TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5", 312 }, 313 }, 314 }, 315 { 316 ValueSat: *big.NewInt(50000000), 317 N: 3, 318 ScriptPubKey: bchain.ScriptPubKey{ 319 Hex: "76a914ab03ecfddee6330497be894d16c29ae341c123aa88ac", 320 Addresses: []string{ 321 "TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT", 322 }, 323 }, 324 }, 325 { 326 ValueSat: *big.NewInt(150000000), 327 N: 4, 328 ScriptPubKey: bchain.ScriptPubKey{ 329 Hex: "76a9144281a58a1d5b2d3285e00cb45a8492debbdad4c588ac", 330 Addresses: []string{ 331 "TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve", 332 }, 333 }, 334 }, 335 { 336 ValueSat: *big.NewInt(50000000), 337 N: 5, 338 ScriptPubKey: bchain.ScriptPubKey{ 339 Hex: "76a9141fd264c0bb53bd9fef18e2248ddf1383d6e811ae88ac", 340 Addresses: []string{ 341 "TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS", 342 }, 343 }, 344 }, 345 { 346 ValueSat: *big.NewInt(750000000), 347 N: 6, 348 ScriptPubKey: bchain.ScriptPubKey{ 349 Hex: "76a91471a3892d164ffa3829078bf9ad5f114a3908ce5588ac", 350 Addresses: []string{ 351 "TLL5GQULX4uBfz7yXL6VcZyvzdKVv1RGxm", 352 }, 353 }, 354 }, 355 }, 356 } 357 } 358 359 func TestMain(m *testing.M) { 360 c := m.Run() 361 chaincfg.ResetParams() 362 os.Exit(c) 363 } 364 365 func TestGetAddrDesc(t *testing.T) { 366 type args struct { 367 tx bchain.Tx 368 parser *FiroParser 369 } 370 tests := []struct { 371 name string 372 args args 373 }{ 374 { 375 name: "firo-1", 376 args: args{ 377 tx: testTx1, 378 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 379 }, 380 }, 381 // FIXME: work around handle zerocoin spend as coinbase 382 // { 383 // name: "firo-2", 384 // args: args{ 385 // tx: testTx2, 386 // parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 387 // }, 388 // }, 389 { 390 name: "firo-3", 391 args: args{ 392 tx: testTx3, 393 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 394 }, 395 }, 396 } 397 for _, tt := range tests { 398 t.Run(tt.name, func(t *testing.T) { 399 for n, vout := range tt.args.tx.Vout { 400 got1, err := tt.args.parser.GetAddrDescFromVout(&vout) 401 if err != nil { 402 t.Errorf("getAddrDescFromVout() error = %v, vout = %d", err, n) 403 return 404 } 405 406 // normal vout 407 if len(vout.ScriptPubKey.Addresses) >= 1 { 408 got2, err := tt.args.parser.GetAddrDescFromAddress(vout.ScriptPubKey.Addresses[0]) 409 if err != nil { 410 t.Errorf("getAddrDescFromAddress() error = %v, vout = %d", err, n) 411 return 412 } 413 if !bytes.Equal(got1, got2) { 414 t.Errorf("Address descriptors mismatch: got1 = %v, got2 = %v", got1, got2) 415 } 416 } 417 } 418 }) 419 } 420 } 421 422 func TestGetAddrDescFromVoutForMint(t *testing.T) { 423 type args struct { 424 vout bchain.Vout 425 } 426 tests := []struct { 427 name string 428 args args 429 want string 430 wantErr bool 431 }{ 432 { 433 name: "OP_RETURN", 434 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "6a072020f1686f6a20"}}}, 435 want: "6a072020f1686f6a20", 436 wantErr: false, 437 }, 438 { 439 name: "OP_ZEROCOINMINT", 440 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"}}}, 441 want: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28", 442 wantErr: false, 443 }, 444 { 445 name: "OP_SIGMAMINT", 446 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"}}}, 447 want: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000", 448 wantErr: false, 449 }, 450 } 451 parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{}) 452 453 for _, tt := range tests { 454 t.Run(tt.name, func(t *testing.T) { 455 got, err := parser.GetAddrDescFromVout(&tt.args.vout) 456 if (err != nil) != tt.wantErr { 457 t.Errorf("GetAddrDescFromVout() error = %v, wantErr %v", err, tt.wantErr) 458 return 459 } 460 h := hex.EncodeToString(got) 461 if !reflect.DeepEqual(h, tt.want) { 462 t.Errorf("GetAddrDescFromVout() = %v, want %v", h, tt.want) 463 } 464 }) 465 } 466 } 467 468 func TestGetAddressesFromAddrDescForMint(t *testing.T) { 469 type args struct { 470 script string 471 } 472 tests := []struct { 473 name string 474 args args 475 want []string 476 want2 bool 477 wantErr bool 478 }{ 479 { 480 name: "OP_RETURN hex", 481 args: args{script: "6a072020f1686f6a20"}, 482 want: []string{"OP_RETURN 2020f1686f6a20"}, 483 want2: false, 484 wantErr: false, 485 }, 486 { 487 name: "OP_ZEROCOINMINT size hex", 488 args: args{script: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"}, 489 want: []string{"Zeromint"}, 490 want2: false, 491 wantErr: false, 492 }, 493 { 494 name: "OP_SIGMAMINT size hex", 495 args: args{script: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"}, 496 want: []string{"Sigmamint"}, 497 want2: false, 498 wantErr: false, 499 }, 500 } 501 parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{}) 502 503 for _, tt := range tests { 504 t.Run(tt.name, func(t *testing.T) { 505 b, _ := hex.DecodeString(tt.args.script) 506 got, got2, err := parser.GetAddressesFromAddrDesc(b) 507 if (err != nil) != tt.wantErr { 508 t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr) 509 return 510 } 511 if !reflect.DeepEqual(got, tt.want) { 512 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want) 513 } 514 if !reflect.DeepEqual(got2, tt.want2) { 515 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2) 516 } 517 }) 518 } 519 } 520 521 func TestPackTx(t *testing.T) { 522 type args struct { 523 tx bchain.Tx 524 height uint32 525 blockTime int64 526 parser *FiroParser 527 } 528 tests := []struct { 529 name string 530 args args 531 want string 532 wantErr bool 533 }{ 534 { 535 name: "firo-1", 536 args: args{ 537 tx: testTx1, 538 height: 100002, 539 blockTime: 1533980594, 540 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 541 }, 542 want: testTxPacked1, 543 wantErr: false, 544 }, 545 // FIXME: work around handle zerocoin spend as coinbase 546 // { 547 // name: "firo-2", 548 // args: args{ 549 // tx: testTx2, 550 // height: 11002, 551 // blockTime: 1481277009, 552 // parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 553 // }, 554 // want: testTxPacked2, 555 // wantErr: true, 556 // }, 557 { 558 name: "firo-3", 559 args: args{ 560 tx: testTx3, 561 height: 126202, 562 blockTime: 1547091829, 563 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 564 }, 565 want: testTxPacked3, 566 wantErr: false, 567 }, 568 { 569 name: "firo-coinbase", 570 args: args{ 571 tx: testTx4, 572 height: 100001, 573 blockTime: 1533977563, 574 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 575 }, 576 want: testTxPacked4, 577 wantErr: false, 578 }, 579 { 580 name: "firo-quorum-commitment-tx", 581 args: args{ 582 tx: testTx5, 583 height: 5268, 584 blockTime: 1591752749, 585 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 586 }, 587 want: testTxPacked5, 588 wantErr: false, 589 }, 590 { 591 name: "firo-special-coinbase-tx", 592 args: args{ 593 tx: testTx6, 594 height: 5300, 595 blockTime: 1591762049, 596 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 597 }, 598 want: testTxPacked6, 599 wantErr: false, 600 }, 601 } 602 for _, tt := range tests { 603 t.Run(tt.name, func(t *testing.T) { 604 got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime) 605 if (err != nil) != tt.wantErr { 606 t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr) 607 return 608 } 609 if !tt.wantErr { 610 h := hex.EncodeToString(got) 611 if !reflect.DeepEqual(h, tt.want) { 612 t.Errorf("packTx() = %v, want %v", h, tt.want) 613 } 614 } 615 }) 616 } 617 } 618 619 func TestUnpackTx(t *testing.T) { 620 type args struct { 621 packedTx string 622 parser *FiroParser 623 } 624 tests := []struct { 625 name string 626 args args 627 want *bchain.Tx 628 want1 uint32 629 wantErr bool 630 }{ 631 { 632 name: "firo-1", 633 args: args{ 634 packedTx: testTxPacked1, 635 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 636 }, 637 want: &testTx1, 638 want1: 100002, 639 wantErr: false, 640 }, 641 // FIXME: work around handle zerocoin spend as coinbase 642 // { 643 // name: "firo-2", 644 // args: args{ 645 // packedTx: testTxPacked2, 646 // parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 647 // }, 648 // want: &testTx2, 649 // want1: 11002, 650 // wantErr: true, 651 // }, 652 { 653 name: "firo-3", 654 args: args{ 655 packedTx: testTxPacked3, 656 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 657 }, 658 want: &testTx3, 659 want1: 126202, 660 wantErr: false, 661 }, 662 { 663 name: "firo-coinbase", 664 args: args{ 665 packedTx: testTxPacked4, 666 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 667 }, 668 want: &testTx4, 669 want1: 100001, 670 wantErr: false, 671 }, 672 { 673 name: "firo-special-tx", 674 args: args{ 675 packedTx: testTxPacked5, 676 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 677 }, 678 want: &testTx5, 679 want1: 5268, 680 wantErr: false, 681 }, 682 { 683 name: "firo-special-coinbase-tx", 684 args: args{ 685 packedTx: testTxPacked6, 686 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 687 }, 688 want: &testTx6, 689 want1: 5300, 690 wantErr: false, 691 }, 692 } 693 for _, tt := range tests { 694 t.Run(tt.name, func(t *testing.T) { 695 b, _ := hex.DecodeString(tt.args.packedTx) 696 got, got1, err := tt.args.parser.UnpackTx(b) 697 if (err != nil) != tt.wantErr { 698 t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr) 699 return 700 } 701 702 if !tt.wantErr { 703 if !reflect.DeepEqual(got, tt.want) { 704 t.Errorf("unpackTx() got = %v, want %v", got, tt.want) 705 } 706 if got1 != tt.want1 { 707 t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1) 708 } 709 } 710 }) 711 } 712 } 713 714 func TestParseBlock(t *testing.T) { 715 type args struct { 716 rawBlock string 717 parser *FiroParser 718 } 719 tests := []struct { 720 name string 721 args args 722 want *bchain.Block 723 wantTxs int 724 wantErr bool 725 }{ 726 { 727 name: "normal-block", 728 args: args{ 729 rawBlock: rawBlock1, 730 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 731 }, 732 want: &bchain.Block{ 733 BlockHeader: bchain.BlockHeader{ 734 Size: 200286, 735 Time: 1547120622, 736 }, 737 }, 738 wantTxs: 3, 739 wantErr: false, 740 }, 741 { 742 name: "spend-block", 743 args: args{ 744 rawBlock: rawBlock2, 745 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 746 }, 747 want: &bchain.Block{ 748 BlockHeader: bchain.BlockHeader{ 749 Size: 25298, 750 Time: 1482107572, 751 }, 752 }, 753 wantTxs: 4, 754 wantErr: false, 755 }, 756 { 757 name: "special-tx-block", 758 args: args{ 759 rawBlock: rawBlock3, 760 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 761 }, 762 want: &bchain.Block{ 763 BlockHeader: bchain.BlockHeader{ 764 Size: 200062, 765 Time: 1591752749, 766 }, 767 }, 768 wantTxs: 3, 769 wantErr: false, 770 }, 771 } 772 773 for _, tt := range tests { 774 t.Run(tt.name, func(t *testing.T) { 775 b, _ := hex.DecodeString(tt.args.rawBlock) 776 got, err := tt.args.parser.ParseBlock(b) 777 if (err != nil) != tt.wantErr { 778 t.Errorf("parseBlock() error = %+v", err) 779 } 780 781 if got != nil { 782 783 if !reflect.DeepEqual(got.BlockHeader, tt.want.BlockHeader) { 784 t.Errorf("parseBlock() got = %v, want %v", got.BlockHeader, tt.want.BlockHeader) 785 } 786 787 if len(got.Txs) != tt.wantTxs { 788 t.Errorf("parseBlock() txs length got = %d, want %d", len(got.Txs), tt.wantTxs) 789 } 790 } 791 }) 792 } 793 } 794 795 func TestDecodeTransaction(t *testing.T) { 796 type args struct { 797 enc wire.MessageEncoding 798 rawTransaction string 799 parser *FiroParser 800 privacyType byte // 0 as non privacy 801 } 802 tests := []struct { 803 name string 804 args args 805 want bchain.Tx 806 wantErr bool 807 }{ 808 { 809 name: "normal-transaction", 810 args: args{ 811 enc: wire.WitnessEncoding, 812 rawTransaction: rawTestTx1, 813 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 814 }, 815 want: testTx1, 816 }, 817 { 818 name: "coinbase-firospend", 819 args: args{ 820 enc: wire.WitnessEncoding, 821 rawTransaction: rawTestTx2, 822 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 823 privacyType: OpSigmaSpend, 824 }, 825 want: testTx2, 826 }, 827 { 828 name: "normal-transaction-2", 829 args: args{ 830 enc: wire.WitnessEncoding, 831 rawTransaction: rawTestTx3, 832 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 833 }, 834 want: testTx3, 835 }, 836 { 837 name: "coinbase-transaction", 838 args: args{ 839 enc: wire.WitnessEncoding, 840 rawTransaction: rawTestTx4, 841 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 842 }, 843 want: testTx4, 844 }, 845 { 846 name: "quorum-commitment-transaction", 847 args: args{ 848 enc: wire.BaseEncoding, 849 rawTransaction: rawTestTx5, 850 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 851 }, 852 want: testTx5, 853 }, 854 { 855 name: "quorum-commitment-transaction-witness", 856 args: args{ 857 enc: wire.WitnessEncoding, 858 rawTransaction: rawTestTx5, 859 parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}), 860 }, 861 wantErr: true, 862 }, 863 { 864 name: "special-coinbase", 865 args: args{ 866 enc: wire.WitnessEncoding, 867 rawTransaction: rawTestTx6, 868 parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}), 869 }, 870 want: testTx6, 871 }, 872 } 873 874 for _, tt := range tests { 875 t.Run(tt.name, func(t *testing.T) { 876 b, _ := hex.DecodeString(tt.args.rawTransaction) 877 r := bytes.NewReader(b) 878 879 msg := FiroMsgTx{} 880 err := msg.FiroDecode(r, 0, tt.args.enc) 881 882 if tt.wantErr { 883 if err == nil { 884 t.Errorf("Want error") 885 } 886 887 return 888 } 889 890 if err != nil { 891 t.Fatal(err) 892 } 893 894 got := tt.args.parser.TxFromFiroMsgTx(&msg, true) 895 if pErr := tt.args.parser.parseFiroTx(&got); pErr != nil { 896 t.Fatal(pErr) 897 } 898 899 if r.Len() != 0 { 900 t.Errorf("Expected EOF but there are remaining %d bytes to read", r.Len()) 901 } 902 903 if len(got.Vin) != len(tt.want.Vin) { 904 t.Errorf("Check vin size, got %v, want %v", len(got.Vin), len(tt.want.Vin)) 905 } 906 907 for i := 0; i != len(got.Vin); i++ { 908 if !reflect.DeepEqual(got.Vin[i].Addresses, tt.want.Vin[i].Addresses) { 909 t.Errorf("Check Addresses at input %d, got %v, want %v", 910 i, got.Vin[i].Addresses, tt.want.Vin[i].Addresses) 911 } 912 913 if !reflect.DeepEqual(got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase) { 914 t.Errorf("Check Coinbase at input %d, got %v, want %v", 915 i, got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase) 916 } 917 918 if !reflect.DeepEqual(got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig) { 919 t.Errorf("Check ScriptSig at input %d, got %v, want %v", 920 i, got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig) 921 } 922 923 if !reflect.DeepEqual(got.Vin[i].Sequence, tt.want.Vin[i].Sequence) { 924 t.Errorf("Check Sequence at input %d, got %v, want %v", 925 i, got.Vin[i].Sequence, tt.want.Vin[i].Sequence) 926 } 927 928 if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Txid, tt.want.Vin[i].Txid) { 929 t.Errorf("Check Txid at input %d, got %v, want %v", 930 i, got.Vin[i].Txid, tt.want.Vin[i].Txid) 931 } 932 933 if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Vout, tt.want.Vin[i].Vout) { 934 t.Errorf("Check Vout at input %d, got %v, want %v", 935 i, got.Vin[i].Vout, tt.want.Vin[i].Vout) 936 } 937 } 938 939 if len(got.Vout) != len(tt.want.Vout) { 940 t.Errorf("Check vout size, got %v, want %v", len(got.Vout), len(tt.want.Vout)) 941 } 942 943 for i := 0; i != len(got.Vout); i++ { 944 if !reflect.DeepEqual(got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue) { 945 t.Errorf("Check JsonValue at output %d, got %v, want %v", 946 i, got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue) 947 } 948 949 if !reflect.DeepEqual(got.Vout[i].N, tt.want.Vout[i].N) { 950 t.Errorf("Check N at output %d, got %v, want %v", 951 i, got.Vout[i].N, tt.want.Vout[i].N) 952 } 953 954 // empty addresses and null should be the same 955 if !((len(got.Vout[i].ScriptPubKey.Addresses) == 0 && len(got.Vout[i].ScriptPubKey.Addresses) == len(tt.want.Vout[i].ScriptPubKey.Addresses)) || 956 reflect.DeepEqual(got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)) { 957 t.Errorf("Check ScriptPubKey.Addresses at output %d, got %v, want %v", 958 i, got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses) 959 } 960 961 if !reflect.DeepEqual(got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex) { 962 t.Errorf("Check ScriptPubKey.Hex at output %d, got %v, want %v", 963 i, got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex) 964 } 965 966 if !reflect.DeepEqual(got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat) { 967 t.Errorf("Check ValueSat at output %d, got %v, want %v", 968 i, got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat) 969 } 970 } 971 972 if got.LockTime != tt.want.LockTime { 973 t.Errorf("Check LockTime, got %v, want %v", got.LockTime, tt.want.LockTime) 974 } 975 976 if got.Txid != tt.want.Txid { 977 t.Errorf("Check TxId, got %v, want %v", got.Txid, tt.want.Txid) 978 } 979 }) 980 } 981 }