982 lines
26 KiB
Go
982 lines
26 KiB
Go
// +build unittest
|
|
|
|
package firo
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"math/big"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/martinboehm/btcd/wire"
|
|
"github.com/martinboehm/btcutil/chaincfg"
|
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
|
)
|
|
|
|
var (
|
|
testTx1, testTx2, testTx3, testTx4, testTx5, testTx6 bchain.Tx
|
|
rawTestTx1, rawTestTx2, rawTestTx3, rawTestTx4, rawTestTx5, rawTestTx6 string
|
|
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4, testTxPacked5, testTxPacked6 string
|
|
rawBlock1, rawBlock2, rawBlock3 string
|
|
jsonTx json.RawMessage
|
|
)
|
|
|
|
func readHexs(path string) []string {
|
|
raw, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
rawStr := string(raw)
|
|
raws := strings.Split(rawStr, "\n")
|
|
return raws
|
|
}
|
|
|
|
func init() {
|
|
rawBlocks := readHexs("./testdata/rawblock.hex")
|
|
rawBlock1 = rawBlocks[0]
|
|
rawBlock2 = rawBlocks[1]
|
|
rawBlock3 = rawBlocks[2]
|
|
|
|
hextxs := readHexs("./testdata/txs.hex")
|
|
rawTestTx1 = hextxs[0]
|
|
rawTestTx2 = hextxs[1]
|
|
rawTestTx3 = hextxs[2]
|
|
rawTestTx4 = hextxs[3]
|
|
rawTestTx5 = hextxs[4]
|
|
rawTestTx6 = hextxs[5]
|
|
|
|
rawSpendHex := readHexs("./testdata/rawspend.hex")[0]
|
|
|
|
rawSpendTx, err := ioutil.ReadFile("./testdata/spendtx.json")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
jsonTx = json.RawMessage(rawSpendTx)
|
|
|
|
testTxPackeds := readHexs("./testdata/packedtxs.hex")
|
|
testTxPacked1 = testTxPackeds[0]
|
|
testTxPacked2 = testTxPackeds[1]
|
|
testTxPacked3 = testTxPackeds[2]
|
|
testTxPacked4 = testTxPackeds[3]
|
|
testTxPacked5 = testTxPackeds[4]
|
|
testTxPacked6 = testTxPackeds[5]
|
|
|
|
testTx1 = bchain.Tx{
|
|
Hex: rawTestTx1,
|
|
Blocktime: 1533980594,
|
|
Time: 1533980594,
|
|
Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23",
|
|
LockTime: 99688,
|
|
Vin: []bchain.Vin{
|
|
{
|
|
ScriptSig: bchain.ScriptSig{
|
|
Hex: "47304402205b7d9c9aae790b69017651e10134735928df3b4a4a2feacc9568eb4fa133ed5902203f21a399385ce29dd79831ea34aa535612aa4314c5bd0b002bbbc9bcd2de1436012102b8d462740c99032a00083ac7028879acec244849e54ad0a04ea87f632f54b1d2",
|
|
},
|
|
Txid: "463a2d66b04636a014da35724909425f3403d9d786dd4f79780de50d47b18716",
|
|
Vout: 1,
|
|
Sequence: 4294967294,
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(100000000),
|
|
N: 0,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(871824000),
|
|
N: 1,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac",
|
|
Addresses: []string{
|
|
"aK5KKi8qqDbspcXFfDjx8UBGMouhYbYZVp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx2 = bchain.Tx{
|
|
Hex: rawTestTx2,
|
|
Blocktime: 1481277009,
|
|
Time: 1481277009,
|
|
Txid: "3d721fdce2855e2b4a54b74a26edd58a7262e1f195b5acaaae7832be6e0b3d32",
|
|
LockTime: 0,
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Coinbase: rawSpendHex,
|
|
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
|
|
Vout: 4294967295,
|
|
Sequence: 2,
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(5000000000),
|
|
N: 0,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914b9e262e30df03e88ccea312652bc83ca7290c8fc88ac",
|
|
Addresses: []string{
|
|
"aHfKwzFZMiSxDuNL4jts819nh57t2yJG1h",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx3 = bchain.Tx{
|
|
Hex: rawTestTx3,
|
|
Blocktime: 1547091829,
|
|
Time: 1547091829,
|
|
Txid: "96ae951083651f141d1fb2719c76d47e5a3ad421b81905f679c0edb60f2de0ff",
|
|
LockTime: 126200,
|
|
Vin: []bchain.Vin{
|
|
{
|
|
ScriptSig: bchain.ScriptSig{
|
|
Hex: "483045022100bdc6b51c114617e29e28390dc9b3ad95b833ca3d1f0429ba667c58a667f9124702204ca2ed362dd9ef723ddbdcf4185b47c28b127a36f46bc4717662be863309b3e601210387e7ff08b953e3736955408fc6ebcd8aa84a04cc4b45758ea29cc2cfe1820535",
|
|
},
|
|
Txid: "448ccfd9c3f375be8701b86aff355a230dbe240334233f2ed476fcae6abd295d",
|
|
Vout: 1,
|
|
Sequence: 4294967294,
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(42000000000),
|
|
N: 0,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a91429bef7962c5c65a2f0f4f7d9ec791866c54f851688ac",
|
|
Addresses: []string{
|
|
"a4XCDQ7AnRH9opZ4h6LcG3g7ocSV2SbBmS",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(107300000000),
|
|
N: 1,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914e2cee7b71c3a4637dbdfe613f19f4b4f2d070d7f88ac",
|
|
Addresses: []string{
|
|
"aMPiKHB3E1AGPi8kKLknx6j1L4JnKCGkLw",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
testTx4 = bchain.Tx{
|
|
Hex: rawTestTx4,
|
|
Blocktime: 1533977563,
|
|
Time: 1533977563,
|
|
Txid: "914ccbdb72f593e5def15978cf5891e1384a1b85e89374fc1c440c074c6dd286",
|
|
LockTime: 0,
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Coinbase: "03a1860104dba36e5b082a00077c00000000052f6d70682f",
|
|
Sequence: 0,
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(2800200000),
|
|
N: 0,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a91436e086acf6561a68ba64196e7b92b606d0b8516688ac",
|
|
Addresses: []string{
|
|
"a5idCcHN8WYxvFCeBXSXvMPrZHuBkZmqEJ",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(1500000000),
|
|
N: 1,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914381a5dd1a279e8e63e67cde39ecfa61a99dd2ba288ac",
|
|
Addresses: []string{
|
|
"a5q7Ad4okSFFVh5adyqx5DT21RTxJykpUM",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(100000000),
|
|
N: 2,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a9147d9ed014fc4e603fca7c2e3f9097fb7d0fb487fc88ac",
|
|
Addresses: []string{
|
|
"aCAgTPgtYcA4EysU4UKC86EQd5cTtHtCcr",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(100000000),
|
|
N: 3,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914bc7e5a5234db3ab82d74c396ad2b2af419b7517488ac",
|
|
Addresses: []string{
|
|
"aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(100000000),
|
|
N: 4,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac",
|
|
Addresses: []string{
|
|
"aQ18FBVFtnueucZKeVg4srhmzbpAeb1KoN",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(300000000),
|
|
N: 5,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a9140654dd9b856f2ece1d56cb4ee5043cd9398d962c88ac",
|
|
Addresses: []string{
|
|
"a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(100000000),
|
|
N: 6,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a9140b4bfb256ef4bfa360e3b9e66e53a0bd84d196bc88ac",
|
|
Addresses: []string{
|
|
"a1kCCGddf5pMXSipLVD9hBG2MGGVNaJ15U",
|
|
},
|
|
},
|
|
},
|
|
// TODO: test segwit
|
|
},
|
|
}
|
|
|
|
testTx5 = bchain.Tx{
|
|
Hex: rawTestTx5,
|
|
Blocktime: 1591752749,
|
|
Time: 1591752749,
|
|
Txid: "8d1f32f35c32d2c127a7400dc1ec52049fbf0b8bcdf284cfaa3da59b6169a22d",
|
|
LockTime: 0,
|
|
Vin: []bchain.Vin{},
|
|
Vout: []bchain.Vout{},
|
|
}
|
|
|
|
testTx6 = bchain.Tx{
|
|
Hex: rawTestTx6,
|
|
Blocktime: 1591762049,
|
|
Time: 1591762049,
|
|
Txid: "e5767d3606230a65f150837a6f28b4f0e4c2702a683045df3883d57702739c61",
|
|
LockTime: 0,
|
|
Vin: []bchain.Vin{
|
|
{
|
|
Coinbase: "02b4140101",
|
|
Sequence: 4294967295,
|
|
},
|
|
},
|
|
Vout: []bchain.Vout{
|
|
{
|
|
ValueSat: *big.NewInt(1400000000),
|
|
N: 0,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "2103fb09a216761d5e7f248294970c2370f7f84ce1ad564b8e7096b1e19116af1d52ac",
|
|
Addresses: []string{
|
|
"TAn9Ghkp31myXRgejCj11wWVHT14Lsj349",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(50000000),
|
|
N: 1,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914296134d2415bf1f2b518b3f673816d7e603b160088ac",
|
|
Addresses: []string{
|
|
"TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(50000000),
|
|
N: 2,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914e1e1dc06a889c1b6d3eb00eef7a96f6a7cfb884888ac",
|
|
Addresses: []string{
|
|
"TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(50000000),
|
|
N: 3,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a914ab03ecfddee6330497be894d16c29ae341c123aa88ac",
|
|
Addresses: []string{
|
|
"TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(150000000),
|
|
N: 4,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a9144281a58a1d5b2d3285e00cb45a8492debbdad4c588ac",
|
|
Addresses: []string{
|
|
"TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(50000000),
|
|
N: 5,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a9141fd264c0bb53bd9fef18e2248ddf1383d6e811ae88ac",
|
|
Addresses: []string{
|
|
"TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ValueSat: *big.NewInt(750000000),
|
|
N: 6,
|
|
ScriptPubKey: bchain.ScriptPubKey{
|
|
Hex: "76a91471a3892d164ffa3829078bf9ad5f114a3908ce5588ac",
|
|
Addresses: []string{
|
|
"TLL5GQULX4uBfz7yXL6VcZyvzdKVv1RGxm",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
c := m.Run()
|
|
chaincfg.ResetParams()
|
|
os.Exit(c)
|
|
}
|
|
|
|
func TestGetAddrDesc(t *testing.T) {
|
|
type args struct {
|
|
tx bchain.Tx
|
|
parser *FiroParser
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
}{
|
|
{
|
|
name: "firo-1",
|
|
args: args{
|
|
tx: testTx1,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
},
|
|
// FIXME: work around handle zerocoin spend as coinbase
|
|
// {
|
|
// name: "firo-2",
|
|
// args: args{
|
|
// tx: testTx2,
|
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
// },
|
|
// },
|
|
{
|
|
name: "firo-3",
|
|
args: args{
|
|
tx: testTx3,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
for n, vout := range tt.args.tx.Vout {
|
|
got1, err := tt.args.parser.GetAddrDescFromVout(&vout)
|
|
if err != nil {
|
|
t.Errorf("getAddrDescFromVout() error = %v, vout = %d", err, n)
|
|
return
|
|
}
|
|
|
|
// normal vout
|
|
if len(vout.ScriptPubKey.Addresses) >= 1 {
|
|
got2, err := tt.args.parser.GetAddrDescFromAddress(vout.ScriptPubKey.Addresses[0])
|
|
if err != nil {
|
|
t.Errorf("getAddrDescFromAddress() error = %v, vout = %d", err, n)
|
|
return
|
|
}
|
|
if !bytes.Equal(got1, got2) {
|
|
t.Errorf("Address descriptors mismatch: got1 = %v, got2 = %v", got1, got2)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetAddrDescFromVoutForMint(t *testing.T) {
|
|
type args struct {
|
|
vout bchain.Vout
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "OP_RETURN",
|
|
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "6a072020f1686f6a20"}}},
|
|
want: "6a072020f1686f6a20",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OP_ZEROCOINMINT",
|
|
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"}}},
|
|
want: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OP_SIGMAMINT",
|
|
args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"}}},
|
|
want: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := parser.GetAddrDescFromVout(&tt.args.vout)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetAddrDescFromVout() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
h := hex.EncodeToString(got)
|
|
if !reflect.DeepEqual(h, tt.want) {
|
|
t.Errorf("GetAddrDescFromVout() = %v, want %v", h, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetAddressesFromAddrDescForMint(t *testing.T) {
|
|
type args struct {
|
|
script string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []string
|
|
want2 bool
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "OP_RETURN hex",
|
|
args: args{script: "6a072020f1686f6a20"},
|
|
want: []string{"OP_RETURN 2020f1686f6a20"},
|
|
want2: false,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OP_ZEROCOINMINT size hex",
|
|
args: args{script: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"},
|
|
want: []string{"Zeromint"},
|
|
want2: false,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OP_SIGMAMINT size hex",
|
|
args: args{script: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"},
|
|
want: []string{"Sigmamint"},
|
|
want2: false,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
b, _ := hex.DecodeString(tt.args.script)
|
|
got, got2, err := parser.GetAddressesFromAddrDesc(b)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want)
|
|
}
|
|
if !reflect.DeepEqual(got2, tt.want2) {
|
|
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPackTx(t *testing.T) {
|
|
type args struct {
|
|
tx bchain.Tx
|
|
height uint32
|
|
blockTime int64
|
|
parser *FiroParser
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "firo-1",
|
|
args: args{
|
|
tx: testTx1,
|
|
height: 100002,
|
|
blockTime: 1533980594,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTxPacked1,
|
|
wantErr: false,
|
|
},
|
|
// FIXME: work around handle zerocoin spend as coinbase
|
|
// {
|
|
// name: "firo-2",
|
|
// args: args{
|
|
// tx: testTx2,
|
|
// height: 11002,
|
|
// blockTime: 1481277009,
|
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
// },
|
|
// want: testTxPacked2,
|
|
// wantErr: true,
|
|
// },
|
|
{
|
|
name: "firo-3",
|
|
args: args{
|
|
tx: testTx3,
|
|
height: 126202,
|
|
blockTime: 1547091829,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTxPacked3,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-coinbase",
|
|
args: args{
|
|
tx: testTx4,
|
|
height: 100001,
|
|
blockTime: 1533977563,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTxPacked4,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-quorum-commitment-tx",
|
|
args: args{
|
|
tx: testTx5,
|
|
height: 5268,
|
|
blockTime: 1591752749,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: testTxPacked5,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-special-coinbase-tx",
|
|
args: args{
|
|
tx: testTx6,
|
|
height: 5300,
|
|
blockTime: 1591762049,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: testTxPacked6,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !tt.wantErr {
|
|
h := hex.EncodeToString(got)
|
|
if !reflect.DeepEqual(h, tt.want) {
|
|
t.Errorf("packTx() = %v, want %v", h, tt.want)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnpackTx(t *testing.T) {
|
|
type args struct {
|
|
packedTx string
|
|
parser *FiroParser
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *bchain.Tx
|
|
want1 uint32
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "firo-1",
|
|
args: args{
|
|
packedTx: testTxPacked1,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: &testTx1,
|
|
want1: 100002,
|
|
wantErr: false,
|
|
},
|
|
// FIXME: work around handle zerocoin spend as coinbase
|
|
// {
|
|
// name: "firo-2",
|
|
// args: args{
|
|
// packedTx: testTxPacked2,
|
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
// },
|
|
// want: &testTx2,
|
|
// want1: 11002,
|
|
// wantErr: true,
|
|
// },
|
|
{
|
|
name: "firo-3",
|
|
args: args{
|
|
packedTx: testTxPacked3,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: &testTx3,
|
|
want1: 126202,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-coinbase",
|
|
args: args{
|
|
packedTx: testTxPacked4,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: &testTx4,
|
|
want1: 100001,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-special-tx",
|
|
args: args{
|
|
packedTx: testTxPacked5,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: &testTx5,
|
|
want1: 5268,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "firo-special-coinbase-tx",
|
|
args: args{
|
|
packedTx: testTxPacked6,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: &testTx6,
|
|
want1: 5300,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
b, _ := hex.DecodeString(tt.args.packedTx)
|
|
got, got1, err := tt.args.parser.UnpackTx(b)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
if !tt.wantErr {
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("unpackTx() got = %v, want %v", got, tt.want)
|
|
}
|
|
if got1 != tt.want1 {
|
|
t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseBlock(t *testing.T) {
|
|
type args struct {
|
|
rawBlock string
|
|
parser *FiroParser
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *bchain.Block
|
|
wantTxs int
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "normal-block",
|
|
args: args{
|
|
rawBlock: rawBlock1,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: &bchain.Block{
|
|
BlockHeader: bchain.BlockHeader{
|
|
Size: 200286,
|
|
Time: 1547120622,
|
|
},
|
|
},
|
|
wantTxs: 3,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "spend-block",
|
|
args: args{
|
|
rawBlock: rawBlock2,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: &bchain.Block{
|
|
BlockHeader: bchain.BlockHeader{
|
|
Size: 25298,
|
|
Time: 1482107572,
|
|
},
|
|
},
|
|
wantTxs: 4,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "special-tx-block",
|
|
args: args{
|
|
rawBlock: rawBlock3,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: &bchain.Block{
|
|
BlockHeader: bchain.BlockHeader{
|
|
Size: 200062,
|
|
Time: 1591752749,
|
|
},
|
|
},
|
|
wantTxs: 3,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
b, _ := hex.DecodeString(tt.args.rawBlock)
|
|
got, err := tt.args.parser.ParseBlock(b)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("parseBlock() error = %+v", err)
|
|
}
|
|
|
|
if got != nil {
|
|
|
|
if !reflect.DeepEqual(got.BlockHeader, tt.want.BlockHeader) {
|
|
t.Errorf("parseBlock() got = %v, want %v", got.BlockHeader, tt.want.BlockHeader)
|
|
}
|
|
|
|
if len(got.Txs) != tt.wantTxs {
|
|
t.Errorf("parseBlock() txs length got = %d, want %d", len(got.Txs), tt.wantTxs)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecodeTransaction(t *testing.T) {
|
|
type args struct {
|
|
enc wire.MessageEncoding
|
|
rawTransaction string
|
|
parser *FiroParser
|
|
privacyType byte // 0 as non privacy
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want bchain.Tx
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "normal-transaction",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx1,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTx1,
|
|
},
|
|
{
|
|
name: "coinbase-firospend",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx2,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
privacyType: OpSigmaSpend,
|
|
},
|
|
want: testTx2,
|
|
},
|
|
{
|
|
name: "normal-transaction-2",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx3,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTx3,
|
|
},
|
|
{
|
|
name: "coinbase-transaction",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx4,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTx4,
|
|
},
|
|
{
|
|
name: "quorum-commitment-transaction",
|
|
args: args{
|
|
enc: wire.BaseEncoding,
|
|
rawTransaction: rawTestTx5,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
want: testTx5,
|
|
},
|
|
{
|
|
name: "quorum-commitment-transaction-witness",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx5,
|
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "special-coinbase",
|
|
args: args{
|
|
enc: wire.WitnessEncoding,
|
|
rawTransaction: rawTestTx6,
|
|
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
|
},
|
|
want: testTx6,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
b, _ := hex.DecodeString(tt.args.rawTransaction)
|
|
r := bytes.NewReader(b)
|
|
|
|
msg := FiroMsgTx{}
|
|
err := msg.FiroDecode(r, 0, tt.args.enc)
|
|
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("Want error")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
got := tt.args.parser.TxFromFiroMsgTx(&msg, true)
|
|
if pErr := tt.args.parser.parseFiroTx(&got); pErr != nil {
|
|
t.Fatal(pErr)
|
|
}
|
|
|
|
if r.Len() != 0 {
|
|
t.Errorf("Expected EOF but there are remaining %d bytes to read", r.Len())
|
|
}
|
|
|
|
if len(got.Vin) != len(tt.want.Vin) {
|
|
t.Errorf("Check vin size, got %v, want %v", len(got.Vin), len(tt.want.Vin))
|
|
}
|
|
|
|
for i := 0; i != len(got.Vin); i++ {
|
|
if !reflect.DeepEqual(got.Vin[i].Addresses, tt.want.Vin[i].Addresses) {
|
|
t.Errorf("Check Addresses at input %d, got %v, want %v",
|
|
i, got.Vin[i].Addresses, tt.want.Vin[i].Addresses)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase) {
|
|
t.Errorf("Check Coinbase at input %d, got %v, want %v",
|
|
i, got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig) {
|
|
t.Errorf("Check ScriptSig at input %d, got %v, want %v",
|
|
i, got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vin[i].Sequence, tt.want.Vin[i].Sequence) {
|
|
t.Errorf("Check Sequence at input %d, got %v, want %v",
|
|
i, got.Vin[i].Sequence, tt.want.Vin[i].Sequence)
|
|
}
|
|
|
|
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Txid, tt.want.Vin[i].Txid) {
|
|
t.Errorf("Check Txid at input %d, got %v, want %v",
|
|
i, got.Vin[i].Txid, tt.want.Vin[i].Txid)
|
|
}
|
|
|
|
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Vout, tt.want.Vin[i].Vout) {
|
|
t.Errorf("Check Vout at input %d, got %v, want %v",
|
|
i, got.Vin[i].Vout, tt.want.Vin[i].Vout)
|
|
}
|
|
}
|
|
|
|
if len(got.Vout) != len(tt.want.Vout) {
|
|
t.Errorf("Check vout size, got %v, want %v", len(got.Vout), len(tt.want.Vout))
|
|
}
|
|
|
|
for i := 0; i != len(got.Vout); i++ {
|
|
if !reflect.DeepEqual(got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue) {
|
|
t.Errorf("Check JsonValue at output %d, got %v, want %v",
|
|
i, got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vout[i].N, tt.want.Vout[i].N) {
|
|
t.Errorf("Check N at output %d, got %v, want %v",
|
|
i, got.Vout[i].N, tt.want.Vout[i].N)
|
|
}
|
|
|
|
// empty addresses and null should be the same
|
|
if !((len(got.Vout[i].ScriptPubKey.Addresses) == 0 && len(got.Vout[i].ScriptPubKey.Addresses) == len(tt.want.Vout[i].ScriptPubKey.Addresses)) ||
|
|
reflect.DeepEqual(got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)) {
|
|
t.Errorf("Check ScriptPubKey.Addresses at output %d, got %v, want %v",
|
|
i, got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex) {
|
|
t.Errorf("Check ScriptPubKey.Hex at output %d, got %v, want %v",
|
|
i, got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex)
|
|
}
|
|
|
|
if !reflect.DeepEqual(got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat) {
|
|
t.Errorf("Check ValueSat at output %d, got %v, want %v",
|
|
i, got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat)
|
|
}
|
|
}
|
|
|
|
if got.LockTime != tt.want.LockTime {
|
|
t.Errorf("Check LockTime, got %v, want %v", got.LockTime, tt.want.LockTime)
|
|
}
|
|
|
|
if got.Txid != tt.want.Txid {
|
|
t.Errorf("Check TxId, got %v, want %v", got.Txid, tt.want.Txid)
|
|
}
|
|
})
|
|
}
|
|
}
|