From 3551c9059086c1f3f68b1de4ebdfebe76afe78e2 Mon Sep 17 00:00:00 2001 From: ilmango <43717671+ilmango-doge@users.noreply.github.com> Date: Tue, 5 Mar 2019 06:29:30 +0900 Subject: [PATCH] Add Bellcoin (#116) * Add Bellcoin * Add integration tests * Add bellcoinparser_test * Fix testTxPacked * Add tests files * Fix indentation * Fix indentation * add bellcoin gpg key * fix binary link * Fix verification_type * Fix verification_type * fix username * Fix verification --- bchain/coins/bellcoin/bellcoinparser.go | 62 ++++ bchain/coins/bellcoin/bellcoinparser_test.go | 327 ++++++++++++++++++ bchain/coins/bellcoin/bellcoinrpc.go | 57 +++ bchain/coins/blockchain.go | 2 + .../docker/deb/gpg-keys/bellcoin-releases.asc | 55 +++ configs/coins/bellcoin.json | 65 ++++ docs/ports.md | 1 + tests/rpc/testdata/bellcoin.json | 80 +++++ tests/sync/testdata/bellcoin.json | 233 +++++++++++++ tests/tests.json | 5 + 10 files changed, 887 insertions(+) create mode 100644 bchain/coins/bellcoin/bellcoinparser.go create mode 100644 bchain/coins/bellcoin/bellcoinparser_test.go create mode 100644 bchain/coins/bellcoin/bellcoinrpc.go create mode 100644 build/docker/deb/gpg-keys/bellcoin-releases.asc create mode 100644 configs/coins/bellcoin.json create mode 100644 tests/rpc/testdata/bellcoin.json create mode 100644 tests/sync/testdata/bellcoin.json diff --git a/bchain/coins/bellcoin/bellcoinparser.go b/bchain/coins/bellcoin/bellcoinparser.go new file mode 100644 index 00000000..a7e86174 --- /dev/null +++ b/bchain/coins/bellcoin/bellcoinparser.go @@ -0,0 +1,62 @@ +package bellcoin + +import ( + "blockbook/bchain/coins/btc" + + "github.com/martinboehm/btcd/wire" + "github.com/martinboehm/btcutil/chaincfg" +) + +const ( + MainnetMagic wire.BitcoinNet = 0xbebacefa + TestnetMagic wire.BitcoinNet = 0x0709110b +) + +var ( + MainNetParams chaincfg.Params + TestNetParams chaincfg.Params +) + +func init() { + MainNetParams = chaincfg.MainNetParams + MainNetParams.Net = MainnetMagic + MainNetParams.PubKeyHashAddrID = []byte{25} + MainNetParams.ScriptHashAddrID = []byte{85} + MainNetParams.Bech32HRPSegwit = "bm" + + TestNetParams = chaincfg.TestNet3Params + TestNetParams.Net = TestnetMagic + TestNetParams.PubKeyHashAddrID = []byte{111} + TestNetParams.ScriptHashAddrID = []byte{196} + TestNetParams.Bech32HRPSegwit = "bt" +} + +// BellcoinParser handle +type BellcoinParser struct { + *btc.BitcoinParser +} + +// NewBellcoinParser returns new BellcoinParser instance +func NewBellcoinParser(params *chaincfg.Params, c *btc.Configuration) *BellcoinParser { + return &BellcoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} +} + +// GetChainParams contains network parameters for the main Bellcoin network, +// and the test Bellcoin network +func GetChainParams(chain string) *chaincfg.Params { + if !chaincfg.IsRegistered(&MainNetParams) { + err := chaincfg.Register(&MainNetParams) + if err == nil { + err = chaincfg.Register(&TestNetParams) + } + if err != nil { + panic(err) + } + } + switch chain { + case "test": + return &TestNetParams + default: + return &MainNetParams + } +} diff --git a/bchain/coins/bellcoin/bellcoinparser_test.go b/bchain/coins/bellcoin/bellcoinparser_test.go new file mode 100644 index 00000000..fb90a9ab --- /dev/null +++ b/bchain/coins/bellcoin/bellcoinparser_test.go @@ -0,0 +1,327 @@ +// +build unittest + +package bellcoin + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/hex" + "math/big" + "os" + "reflect" + "testing" + + "github.com/martinboehm/btcutil/chaincfg" +) + +func TestMain(m *testing.M) { + c := m.Run() + chaincfg.ResetParams() + os.Exit(c) +} + +func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) { + type args struct { + address string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "P2PKH1", + args: args{address: "BSQmMGWpjwP5Lu8feSypSaPFiTTrC3EdEx"}, + want: "76a914f0e2aff6730b53b9986a5db8ca17c59426134a0988ac", + wantErr: false, + }, + { + name: "P2PKH2", + args: args{address: "BLpETLYW1vs8csYSoYeCvPwsiCSTJUjx6T"}, + want: "76a914b3822026c7f758b43a0882d7f2cbfa954702e45688ac", + wantErr: false, + }, + { + name: "P2SH1", + args: args{address: "bNn9Y9YfgNUHXopXJEesS9M8noJzzrWTmP"}, + want: "a9146e3c881d51d62a668362a5bba28be438f9c548e287", + wantErr: false, + }, + { + name: "P2SH2", + args: args{address: "bXCT73hNPSwCeVbpvo3wJJU3erRjawUGSu"}, + want: "a914ca962f788569443b33ec673208ccdcfaac6873b487", + wantErr: false, + }, + { + name: "witness_v0_keyhash", + args: args{address: "bm1q3msdh3npg5ufvwm2sxltxcet6hll9tjzkzxzqt"}, + want: "00148ee0dbc6614538963b6a81beb3632bd5fff2ae42", + wantErr: false, + }, + { + name: "witness_v0_scripthashx", + args: args{address: "bm1q0uvgqxwqt0u4esawwcff7652jreqye30kmp4sj5dtydee50pze0sjx6wn5"}, + want: "00207f188019c05bf95cc3ae76129f6a8a90f202662fb6c3584a8d591b9cd1e1165f", + wantErr: false, + }, + } + parser := NewBellcoinParser(GetChainParams("main"), &btc.Configuration{}) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parser.GetAddrDescFromAddress(tt.args.address) + if (err != nil) != tt.wantErr { + t.Errorf("GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr) + return + } + h := hex.EncodeToString(got) + if !reflect.DeepEqual(h, tt.want) { + t.Errorf("GetAddrDescFromAddress() = %v, want %v", h, tt.want) + } + }) + } +} + +func Test_GetAddressesFromAddrDesc(t *testing.T) { + type args struct { + script string + } + tests := []struct { + name string + args args + want []string + want2 bool + wantErr bool + }{ + { + name: "P2PKH", + args: args{script: "76a914f0e2aff6730b53b9986a5db8ca17c59426134a0988ac"}, + want: []string{"BSQmMGWpjwP5Lu8feSypSaPFiTTrC3EdEx"}, + want2: true, + wantErr: false, + }, + { + name: "P2SH", + args: args{script: "a9146e3c881d51d62a668362a5bba28be438f9c548e287"}, + want: []string{"bNn9Y9YfgNUHXopXJEesS9M8noJzzrWTmP"}, + want2: true, + wantErr: false, + }, + { + name: "P2WPKH", + args: args{script: "00148ee0dbc6614538963b6a81beb3632bd5fff2ae42"}, + want: []string{"bm1q3msdh3npg5ufvwm2sxltxcet6hll9tjzkzxzqt"}, + want2: true, + wantErr: false, + }, + { + name: "P2WSH", + args: args{script: "00207f188019c05bf95cc3ae76129f6a8a90f202662fb6c3584a8d591b9cd1e1165f"}, + want: []string{"bm1q0uvgqxwqt0u4esawwcff7652jreqye30kmp4sj5dtydee50pze0sjx6wn5"}, + want2: true, + wantErr: false, + }, + { + name: "OP_RETURN ascii", + args: args{script: "6a0461686f6a"}, + want: []string{"OP_RETURN (ahoj)"}, + want2: false, + wantErr: false, + }, + { + name: "OP_RETURN hex", + args: args{script: "6a072020f1686f6a20"}, + want: []string{"OP_RETURN 2020f1686f6a20"}, + want2: false, + wantErr: false, + }, + } + + parser := NewBellcoinParser(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("outputScriptToAddresses() 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) + } + }) + } +} + +var ( + testTx1 bchain.Tx + + testTxPacked1 = "0003238c8bc5aac144020000000001026f3631c4db09d48354d12cd2e780b2aa0f92198fca7d044a6b073e9a06b4135d0200000017160014dfc67c36c26ea8036042c56b8ce5d5027d1fb81ffeffffffac13cfbe663797aced3134006adec863e5b3f9480ab65a4dda112de875f8dd6e010000006a473044022066e4d5f99fec12f076d7d912d1e530e4b950d23cc3de2b8127f98109f510c9d502207a74f2e7a753262fdd29756193493d47ead7880871cbc6c55cc6d20e229c0c1201210294fc5b3928335caddc7f4c536e0db85c736cbc7c164de0319976da90b65d288ffeffffff05f4c16020000000001976a91416e20046e69c396aed18c6663ddcbbf1dde9082f88ac0aa47113000000001976a91426fa5e6c4e579058d3f4d1dd83d99e291d4dc0c588acbcb11a00000000001976a9145a53bd436b5c19a42b1518ef18443e8403bcaeed88ac0c04693b0000000017a9140576053f982117afcff024013ed61270189c4fbc87358bad07000000001976a914e00ec357dfee124ac68b3c10dcf82e2ed0993ccc88ac02483045022100ed4b0e9b140850951ffbc10349e3ac56a18b80c600a77b95cfac274e10228eb602207c876b9b134e63b8a01ba28720dc4c1c2c67bb7e547fb71d31440cd365c674260121027aa4243e82c73c9c15d544a0b61a828eed1128464952bfbdc9235d4380f2767d008a230300" +) + +func init() { + testTx1 = bchain.Tx{ + Hex: "020000000001026f3631c4db09d48354d12cd2e780b2aa0f92198fca7d044a6b073e9a06b4135d0200000017160014dfc67c36c26ea8036042c56b8ce5d5027d1fb81ffeffffffac13cfbe663797aced3134006adec863e5b3f9480ab65a4dda112de875f8dd6e010000006a473044022066e4d5f99fec12f076d7d912d1e530e4b950d23cc3de2b8127f98109f510c9d502207a74f2e7a753262fdd29756193493d47ead7880871cbc6c55cc6d20e229c0c1201210294fc5b3928335caddc7f4c536e0db85c736cbc7c164de0319976da90b65d288ffeffffff05f4c16020000000001976a91416e20046e69c396aed18c6663ddcbbf1dde9082f88ac0aa47113000000001976a91426fa5e6c4e579058d3f4d1dd83d99e291d4dc0c588acbcb11a00000000001976a9145a53bd436b5c19a42b1518ef18443e8403bcaeed88ac0c04693b0000000017a9140576053f982117afcff024013ed61270189c4fbc87358bad07000000001976a914e00ec357dfee124ac68b3c10dcf82e2ed0993ccc88ac02483045022100ed4b0e9b140850951ffbc10349e3ac56a18b80c600a77b95cfac274e10228eb602207c876b9b134e63b8a01ba28720dc4c1c2c67bb7e547fb71d31440cd365c674260121027aa4243e82c73c9c15d544a0b61a828eed1128464952bfbdc9235d4380f2767d008a230300", + Blocktime: 1549095010, + Txid: "e7ef52bbf3d9cb1ca5dfdb02eabf108e2b0b7757b009d1cfb24a06e4126e67f2", + LockTime: 205706, + Version: 2, + Vin: []bchain.Vin{ + { + ScriptSig: bchain.ScriptSig{ + Hex: "160014dfc67c36c26ea8036042c56b8ce5d5027d1fb81f", + }, + Txid: "5d13b4069a3e076b4a047dca8f19920faab280e7d22cd15483d409dbc431366f", + Vout: 2, + Sequence: 4294967294, + }, + { + ScriptSig: bchain.ScriptSig{ + Hex: "473044022066e4d5f99fec12f076d7d912d1e530e4b950d23cc3de2b8127f98109f510c9d502207a74f2e7a753262fdd29756193493d47ead7880871cbc6c55cc6d20e229c0c1201210294fc5b3928335caddc7f4c536e0db85c736cbc7c164de0319976da90b65d288f", + }, + Txid: "6eddf875e82d11da4d5ab60a48f9b3e563c8de6a003431edac973766becf13ac", + Vout: 1, + Sequence: 4294967294, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(543212020), + N: 0, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "76a91416e20046e69c396aed18c6663ddcbbf1dde9082f88ac", + Addresses: []string{ + "B6Y5DmPr1LPUP95YDEnX6FbJHERVipkRcg", + }, + }, + }, + { + ValueSat: *big.NewInt(326214666), + N: 1, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "76a91426fa5e6c4e579058d3f4d1dd83d99e291d4dc0c588ac", + Addresses: []string{ + "B81BDwJTasemPgnHBxQ67wX2WV48b2XmEc", + }, + }, + }, + { + ValueSat: *big.NewInt(1749436), + N: 2, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "76a9145a53bd436b5c19a42b1518ef18443e8403bcaeed88ac", + Addresses: []string{ + "BCggkHk8ZTVd9T4yseNmURj6w56XY47EUG", + }, + }, + }, + { + ValueSat: *big.NewInt(996738060), + N: 3, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "a9140576053f982117afcff024013ed61270189c4fbc87", + Addresses: []string{ + "bDE9TQ3W5zF4ej8hLwYVdK5w8n5zhd9Qxj", + }, + }, + }, + { + ValueSat: *big.NewInt(128813877), + N: 4, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "76a914e00ec357dfee124ac68b3c10dcf82e2ed0993ccc88ac", + Addresses: []string{ + "BQsnfSXNonZZMs1G6ndrVLbUJAK5tFG2bN", + }, + }, + }, + }, + } +} + +func Test_PackTx(t *testing.T) { + type args struct { + tx bchain.Tx + height uint32 + blockTime int64 + parser *BellcoinParser + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Bellcoin-1", + args: args{ + tx: testTx1, + height: 205708, + blockTime: 1549095010, + parser: NewBellcoinParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: testTxPacked1, + 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 + } + h := hex.EncodeToString(got) + if !reflect.DeepEqual(h, tt.want) { + t.Errorf("packTx() = %v, want %v", h, tt.want) + } + }) + } +} + +func Test_UnpackTx(t *testing.T) { + type args struct { + packedTx string + parser *BellcoinParser + } + tests := []struct { + name string + args args + want *bchain.Tx + want1 uint32 + wantErr bool + }{ + { + name: "Bellcoin-1", + args: args{ + packedTx: testTxPacked1, + parser: NewBellcoinParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: &testTx1, + want1: 205708, + 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 !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) + } + }) + } +} diff --git a/bchain/coins/bellcoin/bellcoinrpc.go b/bchain/coins/bellcoin/bellcoinrpc.go new file mode 100644 index 00000000..bd359fd2 --- /dev/null +++ b/bchain/coins/bellcoin/bellcoinrpc.go @@ -0,0 +1,57 @@ +package bellcoin + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/json" + + "github.com/golang/glog" +) + +// BellcoinRPC is an interface to JSON-RPC bitcoind service. +type BellcoinRPC struct { + *btc.BitcoinRPC +} + +// NewBellcoinRPC returns new BellcoinRPC instance. +func NewBellcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { + b, err := btc.NewBitcoinRPC(config, pushHandler) + if err != nil { + return nil, err + } + + s := &BellcoinRPC{ + b.(*btc.BitcoinRPC), + } + s.RPCMarshaler = btc.JSONMarshalerV2{} + s.ChainConfig.SupportsEstimateFee = false + + return s, nil +} + +// Initialize initializes BellcoinRPC instance. +func (b *BellcoinRPC) Initialize() error { + chainName, err := b.GetChainInfoAndInitializeMempool(b) + if err != nil { + return err + } + + glog.Info("Chain name ", chainName) + params := GetChainParams(chainName) + + // always create parser + b.Parser = NewBellcoinParser(params, b.ChainConfig) + + // parameters for getInfo request + if params.Net == MainnetMagic { + b.Testnet = false + b.Network = "livenet" + } else { + b.Testnet = true + b.Network = "testnet" + } + + glog.Info("rpc: block chain ", params.Name) + + return nil +} diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index 42074792..5ae93b0d 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -3,6 +3,7 @@ package coins import ( "blockbook/bchain" "blockbook/bchain/coins/bch" + "blockbook/bchain/coins/bellcoin" "blockbook/bchain/coins/btc" "blockbook/bchain/coins/btg" "blockbook/bchain/coins/dash" @@ -74,6 +75,7 @@ func init() { BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC BlockChainFactories["Flo"] = flo.NewFloRPC + BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC } // GetCoinNameFromConfig gets coin name and coin shortcut from config file diff --git a/build/docker/deb/gpg-keys/bellcoin-releases.asc b/build/docker/deb/gpg-keys/bellcoin-releases.asc new file mode 100644 index 00000000..fba83d1b --- /dev/null +++ b/build/docker/deb/gpg-keys/bellcoin-releases.asc @@ -0,0 +1,55 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +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 +XiqzrjeWScdNunn68L6hKIi+5h+FDfR+Bg8= +=U3MK +-----END PGP PUBLIC KEY BLOCK----- diff --git a/configs/coins/bellcoin.json b/configs/coins/bellcoin.json new file mode 100644 index 00000000..b2cfb432 --- /dev/null +++ b/configs/coins/bellcoin.json @@ -0,0 +1,65 @@ +{ + "coin": { + "name": "Bellcoin", + "shortcut": "BELL", + "label": "Bellcoin", + "alias": "bellcoin" + }, + "ports": { + "backend_rpc": 8052, + "backend_message_queue": 38352, + "blockbook_internal": 9052, + "blockbook_public": 9152 + }, + "ipc": { + "rpc_url_template": "http://127.0.0.1:{{.Ports.BackendRPC}}", + "rpc_user": "rpc", + "rpc_pass": "rpc", + "rpc_timeout": 25, + "message_queue_binding_template": "tcp://127.0.0.1:{{.Ports.BackendMessageQueue}}" + }, + "backend": { + "package_name": "backend-bellcoin", + "package_revision": "satoshilabs-1", + "system_user": "bellcoin", + "version": "1.0.2", + "binary_url": "https://github.com/y-chan/bellcoin/releases/download/1.0.2/bellcoin-1.0.2-x86_64-linux-gnu.tar.gz", + "verification_type": "sha256", + "verification_source": "e959d7e9977ee50d99de2bc50a6d662626816794d3b6721d03f945e589bf8bfd", + "extract_command": "tar -C backend --strip 1 -xf", + "exclude_files": [ + "bellcoin-qt" + ], + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bellcoind -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", + "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log", + "postinst_script_template": "", + "service_type": "forking", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": true, + "server_config_file": "bitcoin_like.conf", + "client_config_file": "bitcoin_like_client.conf", + "additional_params": { + "whitelist": "127.0.0.1" + } + }, + "blockbook": { + "package_name": "blockbook-bellcoin", + "system_user": "blockbook-bellcoin", + "internal_binding_template": ":{{.Ports.BlockbookInternal}}", + "public_binding_template": ":{{.Ports.BlockbookPublic}}", + "explorer_url": "", + "additional_params": "", + "block_chain": { + "parse": true, + "mempool_workers": 8, + "mempool_sub_workers": 2, + "block_addresses_to_keep": 300, + "additional_params": {} + } + }, + "meta": { + "package_maintainer": "ilmango-doge", + "package_maintainer_email": "ilmango.doge@gmail.com" + } + } diff --git a/docs/ports.md b/docs/ports.md index 7ed0863a..569a3169 100644 --- a/docs/ports.md +++ b/docs/ports.md @@ -24,6 +24,7 @@ | PIVX | 9049 | 9149 | 8049 | 38349 | | Zcoin | 9050 | 9150 | 8050 | 38350 | | Koto | 9051 | 9151 | 8051 | 38351 | +| Bellcoin | 9052 | 9152 | 8052 | 38352 | | Flo | 9066 | 9166 | 8066 | 38366 | | Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 | | Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 | diff --git a/tests/rpc/testdata/bellcoin.json b/tests/rpc/testdata/bellcoin.json new file mode 100644 index 00000000..4f774002 --- /dev/null +++ b/tests/rpc/testdata/bellcoin.json @@ -0,0 +1,80 @@ +{ + "blockHeight": 195604, + "blockHash": "00000124fd5a9c1225a5964675c833f6e67b7c94e1414ad43c006ac0e5f47961", + "blockTime": 1548485163, + "blockTxs": [ + "0a0c091619bff958253300ca0f0bd40528a429010aef35c63f01cc7a59cf4c7a", + "96853036083e2ef6e06cd55e0fdd971a41987157952d01a40d4755ddd6880ee1" + ], + "txDetails": { + "96853036083e2ef6e06cd55e0fdd971a41987157952d01a40d4755ddd6880ee1": { + "hex": "020000000190ab97bb210cc3573fd619813abdfd5c74fd64f48cd5b6deb528ffc0ac2025d2010000006b483045022100b357154a034a8b2775f188da68a00bb282743bbf138038be66f66623082dec830220143aa4786f7a28b4f47333562964033aeb822e3dc48589cf80217244f0cb7e05012102d89a3fb18e04f9e4e91437d008e6f323e5a1308bf312066a09bb83c15739dfb2feffffff07ec235e08000000001976a91441ca8a78aab59c02ebd17d25dc196da34b2cafe788acf0870b060000000017a914bb073b44334b112793b1d9db0709ea7f02a22039876fc061070000000017a914ffea83b42b127b8b5a1bc984ae9d45ec08c92b84877dbaf311000000001976a9143acb8a0091a159337c53e40c3bf5b38d56f4e55588ac70e07b0b000000001976a9141a85678940ac58b5c84231b7e230a99dcc10247388ace84108020000000017a9140191d42d0433b7721c76332a2f1ab6e7f809fc8f87072857060000000017a9147ec3793cafc0b2380a410578b1b5c4d79b090d598713fc0200", + "txid": "96853036083e2ef6e06cd55e0fdd971a41987157952d01a40d4755ddd6880ee1", + "blocktime": 1548485163, + "time": 1548485163, + "locktime": 195603, + "version": 2, + "vin": [ + { + "txid": "d22520acc0ff28b5deb6d58cf464fd745cfdbd3a8119d63f57c30c21bb97ab90", + "vout": 1, + "scriptSig": { + "hex": "483045022100b357154a034a8b2775f188da68a00bb282743bbf138038be66f66623082dec830220143aa4786f7a28b4f47333562964033aeb822e3dc48589cf80217244f0cb7e05012102d89a3fb18e04f9e4e91437d008e6f323e5a1308bf312066a09bb83c15739dfb2" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 1.40387308, + "n": 0, + "scriptPubKey": { + "hex": "76a91441ca8a78aab59c02ebd17d25dc196da34b2cafe788ac" + } + }, + { + "value": 1.01418992, + "n": 1, + "scriptPubKey": { + "hex": "a914bb073b44334b112793b1d9db0709ea7f02a2203987" + } + }, + { + "value": 1.23846767, + "n": 2, + "scriptPubKey": { + "hex": "a914ffea83b42b127b8b5a1bc984ae9d45ec08c92b8487" + } + }, + { + "value": 3.01185661, + "n": 3, + "scriptPubKey": { + "hex": "76a9143acb8a0091a159337c53e40c3bf5b38d56f4e55588ac" + } + }, + { + "value": 1.92667760, + "n": 4, + "scriptPubKey": { + "hex": "76a9141a85678940ac58b5c84231b7e230a99dcc10247388ac" + } + }, + { + "value": 0.34095592, + "n": 5, + "scriptPubKey": { + "hex": "a9140191d42d0433b7721c76332a2f1ab6e7f809fc8f87" + } + }, + { + "value": 1.06375175, + "n": 6, + "scriptPubKey": { + "hex": "a9147ec3793cafc0b2380a410578b1b5c4d79b090d5987" + } + } + ] + } + } +} \ No newline at end of file diff --git a/tests/sync/testdata/bellcoin.json b/tests/sync/testdata/bellcoin.json new file mode 100644 index 00000000..130160ae --- /dev/null +++ b/tests/sync/testdata/bellcoin.json @@ -0,0 +1,233 @@ +{ + "connectBlocks": { + "syncRanges": [ + {"lower": 214679, "upper": 214699} + ], + "blocks": { + "214699": { + "height": 214699, + "hash": "00000143884495d2d259cfe9ef7643c56481d30fbf7d78f0d90a35ebe79f49ef", + "noTxs": 2, + "txDetails": [ + { + "hex": "0200000000010445e8550a734be971457dc77f227fb181b2ba106443343c446d1af812e746106a0a000000171600149be313ed4306437cd38cf1431e483fe1734f1e1efeffffff7d4f15c461234023ed35bf6540051168344c7f603370f3a1cf7d38b09a36f510010000006b483045022100fd414150a693e58456314b350c10df5e1be8d11a7f05e4cfea70185d25e5022c022071c8ccbab7c07e867e18fa6a68466aac7ed26f81a0e27c40c97e29c8b5b90d2a0121027ba3f5396db721177d18587cd20e332179c31b8536acf8c918366de6e765fac9feffffffa3c52614b84afbcd6e9436e0e63b5ec342258a685566f77560267bba643190b10000000017160014e1231b0c00e8b4cfd7c2ca7d60cd33163a969b6afeffffffaeb6794fca576d87fa39e13ab72f536546cb8303020187baa238d670bfa4ed2d010000006a473044022043944c7a03b599d7d27e7d72a71e3508256fc49180f7a587b3e36c9f30ce3a81022045d994ad4f1d8da96d4541d3d0b8fcc64f0f3bf79e383dc37c2c20fae6ef74ef0121027ba3f5396db721177d18587cd20e332179c31b8536acf8c918366de6e765fac9feffffff131cd66701000000001976a9140bf90017ae9670c23373bc13d9c539610551ad9388ac98cfe104000000001976a914df0eb8e4d33c5fa97f1269db1022b6c73196788888ac9ef415080000000017a914fe888a5fe791c9ac76bdc675a7b596cf92678c38879fca2304000000001976a9149dc61afcf11e9cd2e30198a5f6e81f9fce9f02bd88aca3a8cd01000000001976a9141e7dc59501a484067e683066263494231efa7fab88ac2c966804000000001976a914bbeb8aa44faee468d64d29da3affc45264abe73588ac5b07fd03000000001976a9143045c8fa77215ecf0262477b3da7bc9ceb135a6f88ac0570d401000000001976a914c06b3778af739b0ad06298e5aa3b2b61d305140488ac79598805000000001976a914b431a9e3464c894ecd9d16e297afc7a260a3192f88ac50190f000000000017a914bb23b90eaf1f375b5928c31b4256d03bc16e70fd87f17fa20b000000001976a91413feccf8c11c1fec911f0cdc33ac97b80b9eeb9888acc99b14040000000017a914dde3bc4a869a78b391d813be25367905638f56a587895f2d03000000001976a9147327f5ee39c2e4f62d8a9fa422ab6df62d97edc488ac0e730302000000001976a91426fa5e6c4e579058d3f4d1dd83d99e291d4dc0c588ac63fa8c02000000001976a91404aa8d712fef8d37a7ec1036b15862da8ed4428088ac636f3b03000000001976a914e23f809d9cd6a7ad2932f9bdd87585489e7100d488ac9a168728000000001976a914d1341de4b95ee1f654c0e080e9d2a6de2d990aa088aceb4a1c0a000000001976a9143acb8a0091a159337c53e40c3bf5b38d56f4e55588ac8cbf2206000000001976a9140c06edeb8f33d0f40c7ac6770b4390f3216f5b3388ac02483045022100c9724d13b28d392859a9739d164ba5784aada6562d177b7bb7a68123bf3fbab002206c553f18aa6f01b3c2bf0a8aea5f658036cb0bd05e4e71830717a45b2ffe96ac012102af81513167ae25311d49ca9a8da65a562b28422e7ceead23f52bf335b40eef93000247304402205e947316259732b3c5b667f84fcb87f34b7c2104c5b6154061780531d620604f02205bd50167abaccb9eb6c0127b84b0f32071ce3e15678b8e9ae7057eea3d24e7d20121028aac04d910b30df3901ff6f9d5550380ef1ce4b448df4fc80ff962464ac3465c00aa460300", + "txid": "8f187d65e24d3ec98f00db06812506d0f87844e627d5e3b4f0be51079de8aea4", + "version": 2, + "vin": [ + { + "txid": "6a1046e712f81a6d443c34436410bab281b17f227fc77d4571e94b730a55e845", + "vout": 10, + "sequence": 4294967294, + "scriptSig": { + "hex": "1600149be313ed4306437cd38cf1431e483fe1734f1e1e" + } + }, + { + "txid": "10f5369ab0387dcfa1f37033607f4c346811054065bf35ed23402361c4154f7d", + "vout": 1, + "sequence": 4294967294, + "scriptSig": { + "hex": "483045022100fd414150a693e58456314b350c10df5e1be8d11a7f05e4cfea70185d25e5022c022071c8ccbab7c07e867e18fa6a68466aac7ed26f81a0e27c40c97e29c8b5b90d2a0121027ba3f5396db721177d18587cd20e332179c31b8536acf8c918366de6e765fac9" + } + }, + { + "txid": "b1903164ba7b266075f76655688a2542c35e3be6e036946ecdfb4ab81426c5a3", + "vout": 0, + "sequence": 4294967294, + "scriptSig": { + "hex": "160014e1231b0c00e8b4cfd7c2ca7d60cd33163a969b6a" + } + }, + { + "txid": "2deda4bf70d638a2ba8701020383cb4665532fb73ae139fa876d57ca4f79b6ae", + "vout": 1, + "sequence": 4294967294, + "scriptSig": { + "hex": "473044022043944c7a03b599d7d27e7d72a71e3508256fc49180f7a587b3e36c9f30ce3a81022045d994ad4f1d8da96d4541d3d0b8fcc64f0f3bf79e383dc37c2c20fae6ef74ef0121027ba3f5396db721177d18587cd20e332179c31b8536acf8c918366de6e765fac9" + } + } + ], + "vout": [ + { + "value": 0.23582236, + "n": 0, + "scriptPubKey": { + "hex": "76a9140bf90017ae9670c23373bc13d9c539610551ad9388ac" + } + }, + { + "value": 0.81907608, + "n": 1, + "scriptPubKey": { + "hex": "76a914df0eb8e4d33c5fa97f1269db1022b6c73196788888ac" + } + }, + { + "value": 1.35656606, + "n": 2, + "scriptPubKey": { + "hex": "a914fe888a5fe791c9ac76bdc675a7b596cf92678c3887" + } + }, + { + "value": 0.69454495, + "n": 3, + "scriptPubKey": { + "hex": "76a9149dc61afcf11e9cd2e30198a5f6e81f9fce9f02bd88ac" + } + }, + { + "value": 0.30255267, + "n": 4, + "scriptPubKey": { + "hex": "76a9141e7dc59501a484067e683066263494231efa7fab88ac" + } + }, + { + "value": 0.73963052, + "n": 5, + "scriptPubKey": { + "hex": "76a914bbeb8aa44faee468d64d29da3affc45264abe73588ac" + } + }, + { + "value": 0.66914139, + "n": 6, + "scriptPubKey": { + "hex": "76a9143045c8fa77215ecf0262477b3da7bc9ceb135a6f88ac" + } + }, + { + "value": 0.30699525, + "n": 7, + "scriptPubKey": { + "hex": "76a914c06b3778af739b0ad06298e5aa3b2b61d305140488ac" + } + }, + { + "value": 0.92821881, + "n": 8, + "scriptPubKey": { + "hex": "76a914b431a9e3464c894ecd9d16e297afc7a260a3192f88ac" + } + }, + { + "value": 0.0098952, + "n": 9, + "scriptPubKey": { + "hex": "a914bb23b90eaf1f375b5928c31b4256d03bc16e70fd87" + } + }, + { + "value": 1.95198961, + "n": 10, + "scriptPubKey": { + "hex": "76a91413feccf8c11c1fec911f0cdc33ac97b80b9eeb9888ac" + } + }, + { + "value": 0.68459465, + "n": 11, + "scriptPubKey": { + "hex": "a914dde3bc4a869a78b391d813be25367905638f56a587" + } + }, + { + "value": 0.53305225, + "n": 12, + "scriptPubKey": { + "hex": "76a9147327f5ee39c2e4f62d8a9fa422ab6df62d97edc488ac" + } + }, + { + "value": 0.33780494, + "n": 13, + "scriptPubKey": { + "hex": "76a91426fa5e6c4e579058d3f4d1dd83d99e291d4dc0c588ac" + } + }, + { + "value": 0.42793571, + "n": 14, + "scriptPubKey": { + "hex": "76a91404aa8d712fef8d37a7ec1036b15862da8ed4428088ac" + } + }, + { + "value": 0.54226787, + "n": 15, + "scriptPubKey": { + "hex": "76a914e23f809d9cd6a7ad2932f9bdd87585489e7100d488ac" + } + }, + { + "value": 6.79941786, + "n": 16, + "scriptPubKey": { + "hex": "76a914d1341de4b95ee1f654c0e080e9d2a6de2d990aa088ac" + } + }, + { + "value": 1.69626347, + "n": 17, + "scriptPubKey": { + "hex": "76a9143acb8a0091a159337c53e40c3bf5b38d56f4e55588ac" + } + }, + { + "value": 1.02940556, + "n": 18, + "scriptPubKey": { + "hex": "76a9140c06edeb8f33d0f40c7ac6770b4390f3216f5b3388ac" + } + } + ], + "time": 1538761583, + "blocktime": 1538761583 + } + ] + } + } + }, + "handleFork": { + "syncRanges": [ + {"lower": 214679, "upper": 214699} + ], + "fakeBlocks": { + "425196": { + "height": 214696, + "hash": "000002039e62e10c48d8ff44ba63b4f8276cab2f5ba80da5f7347af862b83443" + }, + "425197": { + "height": 214697, + "hash": "0000007f1cc433237f2d82113b25617cea914622ac3f8d0b092cb0d550f4d197" + }, + "425198": { + "height": 214698, + "hash": "000002d1704bc129b8bf3c5031e8a62c2f2a786b94899bed4e1d38c56aa5bb87" + }, + "214699": { + "height": 214699, + "hash": "0000018f8a049fb215e6894bc7294ec7998467db750113bda372e4210f80ca91" + } + }, + "realBlocks": { + "425196": { + "height": 214696, + "hash": "000002bce2787e6b919df505e1f80a174d82c2084c00c27489991a0365710d00" + }, + "425197": { + "height": 214697, + "hash": "000002a81151dc44e8530765fb97f95bdfb1ebe1a2f6638c442d0174e086a35b" + }, + "425198": { + "height": 214698, + "hash": "00000295acd630d1425755ecf481ffe7ba334360e87702aac027da31ed168404" + }, + "214699": { + "height": 214699, + "hash": "00000143884495d2d259cfe9ef7643c56481d30fbf7d78f0d90a35ebe79f49ef" + } + } + } +} diff --git a/tests/tests.json b/tests/tests.json index f7a71b43..6de78578 100644 --- a/tests/tests.json +++ b/tests/tests.json @@ -9,6 +9,11 @@ "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"], "sync": ["ConnectBlocksParallel", "ConnectBlocks", "HandleFork"] }, + "bellcoin": { + "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", + "EstimateSmartFee", "EstimateFee"], + "sync": ["ConnectBlocksParallel", "ConnectBlocks", "HandleFork"] + }, "bgold": { "sync": ["ConnectBlocksParallel", "ConnectBlocks", "HandleFork"] },