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  }