diff --git a/Gopkg.lock b/Gopkg.lock index 6145e706..cf32c2f0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/Groestlcoin/go-groestl-hash" + packages = ["groestl","hash"] + revision = "790653ac190c4029ee200e82a8f21b5d1afaf7d6" + [[projects]] branch = "master" name = "github.com/beorn7/perks" @@ -89,13 +95,13 @@ branch = "master" name = "github.com/jakm/bchutil" packages = ["."] - revision = "9e4fc13b082c87967b0befbcbad6fe5a5aa5ac1a" + revision = "5a273ca8a96628732c07ff5cfb9f3e7d965241e8" [[projects]] branch = "master" name = "github.com/jakm/btcutil" packages = [".","base58","bech32","chaincfg","txscript"] - revision = "83dfbb3d0b20916f89b36b95c6ca580e3a785856" + revision = "224b76333062172edefdeb502123fdda12205f76" [[projects]] branch = "master" diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index 90e011ff..da2df8b8 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -8,6 +8,7 @@ import ( "blockbook/bchain/coins/dash" "blockbook/bchain/coins/dogecoin" "blockbook/bchain/coins/eth" + "blockbook/bchain/coins/grs" "blockbook/bchain/coins/litecoin" "blockbook/bchain/coins/monacoin" "blockbook/bchain/coins/myriad" @@ -52,6 +53,8 @@ func init() { BlockChainFactories["Monacoin"] = monacoin.NewMonacoinRPC BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC BlockChainFactories["Myriad"] = myriad.NewMyriadRPC + BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC + BlockChainFactories["Groestlcoin Testnet"] = grs.NewGroestlcoinRPC } // GetCoinNameFromConfig gets coin name and coin shortcut from config file diff --git a/bchain/coins/grs/grsparser.go b/bchain/coins/grs/grsparser.go new file mode 100644 index 00000000..460eadc9 --- /dev/null +++ b/bchain/coins/grs/grsparser.go @@ -0,0 +1,88 @@ +package grs + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + + "github.com/btcsuite/btcd/wire" + "github.com/jakm/btcutil/base58" + "github.com/jakm/btcutil/chaincfg" +) + +const ( + MainnetMagic wire.BitcoinNet = 0xd4b4bef9 + TestnetMagic wire.BitcoinNet = 0x0709110b +) + +var ( + MainNetParams chaincfg.Params + TestNetParams chaincfg.Params +) + +func init() { + MainNetParams = chaincfg.MainNetParams + MainNetParams.Net = MainnetMagic + + // Address encoding magics + MainNetParams.PubKeyHashAddrID = []byte{36} + MainNetParams.ScriptHashAddrID = []byte{5} + MainNetParams.Bech32HRPSegwit = "grs" + MainNetParams.Base58CksumHasher = base58.Groestl512D + + TestNetParams = chaincfg.TestNet3Params + TestNetParams.Net = TestnetMagic + + // Address encoding magics + TestNetParams.PubKeyHashAddrID = []byte{111} + TestNetParams.ScriptHashAddrID = []byte{196} + TestNetParams.Bech32HRPSegwit = "tgrs" + TestNetParams.Base58CksumHasher = base58.Groestl512D +} + +// GroestlcoinParser handle +type GroestlcoinParser struct { + *btc.BitcoinParser + baseparser *bchain.BaseParser +} + +// NewGroestlcoinParser returns new GroestlcoinParser instance +func NewGroestlcoinParser(params *chaincfg.Params, c *btc.Configuration) *GroestlcoinParser { + return &GroestlcoinParser{ + BitcoinParser: btc.NewBitcoinParser(params, c), + baseparser: &bchain.BaseParser{}, + } +} + +// GetChainParams contains network parameters for the main Groestlcoin network, +// the regression test Groestlcoin network, the test Groestlcoin network and +// the simulation test Groestlcoin network, in this order +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) + } + } + var params *chaincfg.Params + switch chain { + case "test": + return &TestNetParams + default: + return &MainNetParams + } + + return params +} + +// PackTx packs transaction to byte array using protobuf +func (p *GroestlcoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) { + return p.baseparser.PackTx(tx, height, blockTime) +} + +// UnpackTx unpacks transaction from protobuf byte array +func (p *GroestlcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { + return p.baseparser.UnpackTx(buf) +} diff --git a/bchain/coins/grs/grsparser_test.go b/bchain/coins/grs/grsparser_test.go new file mode 100644 index 00000000..5b40ec38 --- /dev/null +++ b/bchain/coins/grs/grsparser_test.go @@ -0,0 +1,248 @@ +// +build unittest + +package grs + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "bytes" + "encoding/hex" + "math/big" + "os" + "reflect" + "testing" + + "github.com/jakm/btcutil/chaincfg" +) + +var ( + testTx1, testTx2 bchain.Tx + + testTxPacked1 = "0a20f56521b17b828897f72b30dd21b0192fd942342e89acbb06abf1d446282c30f512bf0101000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac0000000018ffff87da05200028a6f383013298010a001220cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a1800226a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e6728ffffffff0f3a460a030333a010001a1976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac222246744d347a416e39615659674867786d616d5742675750795a7362365268766b4139" + testTxPacked2 = "0a209b5c4859a8a31e69788cb4402812bb28f14ad71cbd8c60b09903478bc56f79a312e00101000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed090018caa384da0520d9db2728dadb27322c0a0012204f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1180028feffffff0f3a450a034c4b4010001a17a9147a55d61848e77ca266e79a39bfc85c580a6426c9872223324e345135466855323439374272794666556762716b414a453837614b4476335633653a4d0a036f38a810011a160014cc8067093f6f843d6d3e22004a4290cd0c0f336b222c746772733171656a7178777a666c64377a72366d663779677179357335736535787137766d74396c6b643537" +) + +func init() { + testTx1 = bchain.Tx{ + Hex: "01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000", + Blocktime: 1531052031, + Time: 1531052031, + Txid: "f56521b17b828897f72b30dd21b0192fd942342e89acbb06abf1d446282c30f5", + LockTime: 0, + Vin: []bchain.Vin{ + { + ScriptSig: bchain.ScriptSig{ + Hex: "47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67", + }, + Txid: "cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a", + Vout: 0, + Sequence: 4294967295, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(209824), + N: 0, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "76a914fe40329c95c5598ac60752a5310b320cb52d18e688ac", + Addresses: []string{ + "FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9", + }, + }, + }, + }, + } + + testTx2 = bchain.Tx{ + Hex: "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900", + Blocktime: 1530991050, + Time: 1530991050, + Txid: "9b5c4859a8a31e69788cb4402812bb28f14ad71cbd8c60b09903478bc56f79a3", + LockTime: 650713, + Vin: []bchain.Vin{ + { + ScriptSig: bchain.ScriptSig{ + Hex: "", + }, + Txid: "4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1", + Vout: 0, + Sequence: 4294967294, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(5000000), + N: 0, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "a9147a55d61848e77ca266e79a39bfc85c580a6426c987", + Addresses: []string{ + "2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e", + }, + }, + }, + { + ValueSat: *big.NewInt(7289000), + N: 1, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "0014cc8067093f6f843d6d3e22004a4290cd0c0f336b", + Addresses: []string{ + "tgrs1qejqxwzfld7zr6mf7ygqy5s5se5xq7vmt9lkd57", + }, + }, + }, + }, + } +} + +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 *GroestlcoinParser + } + tests := []struct { + name string + args args + }{ + { + name: "grs-1", + args: args{ + tx: testTx1, + parser: NewGroestlcoinParser(GetChainParams("main"), &btc.Configuration{}), + }, + }, + { + name: "grs-2", + args: args{ + tx: testTx2, + parser: NewGroestlcoinParser(GetChainParams("test"), &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 + } + 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 TestPackTx(t *testing.T) { + type args struct { + tx bchain.Tx + height uint32 + blockTime int64 + parser *GroestlcoinParser + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "grs-1", + args: args{ + tx: testTx1, + height: 2161062, + blockTime: 1531052031, + parser: NewGroestlcoinParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: testTxPacked1, + wantErr: false, + }, + { + name: "grs-2", + args: args{ + tx: testTx2, + height: 650714, + blockTime: 1530991050, + parser: NewGroestlcoinParser(GetChainParams("test"), &btc.Configuration{}), + }, + want: testTxPacked2, + 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 TestUnpackTx(t *testing.T) { + type args struct { + packedTx string + parser *GroestlcoinParser + } + tests := []struct { + name string + args args + want *bchain.Tx + want1 uint32 + wantErr bool + }{ + { + name: "grs-1", + args: args{ + packedTx: testTxPacked1, + parser: NewGroestlcoinParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: &testTx1, + want1: 2161062, + wantErr: false, + }, + { + name: "grs-2", + args: args{ + packedTx: testTxPacked2, + parser: NewGroestlcoinParser(GetChainParams("test"), &btc.Configuration{}), + }, + want: &testTx2, + want1: 650714, + 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/grs/grsrpc.go b/bchain/coins/grs/grsrpc.go new file mode 100644 index 00000000..f7adebd0 --- /dev/null +++ b/bchain/coins/grs/grsrpc.go @@ -0,0 +1,115 @@ +package grs + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/json" + + "github.com/golang/glog" + "github.com/juju/errors" +) + +type GroestlcoinRPC struct { + *btc.BitcoinRPC +} + +func NewGroestlcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { + b, err := btc.NewBitcoinRPC(config, pushHandler) + if err != nil { + return nil, err + } + g := &GroestlcoinRPC{ + BitcoinRPC: b.(*btc.BitcoinRPC), + } + g.RPCMarshaler = btc.JSONMarshalerV1{} + return g, nil +} + +// Initialize initializes GroestlcoinRPC instance. +func (g *GroestlcoinRPC) Initialize() error { + chainName, err := g.GetChainInfoAndInitializeMempool(g) + if err != nil { + return err + } + + params := GetChainParams(chainName) + + g.Parser = NewGroestlcoinParser(params, g.ChainConfig) + + // parameters for getInfo request + if params.Net == MainnetMagic { + g.Testnet = false + g.Network = "livenet" + } else { + g.Testnet = true + g.Network = "testnet" + } + + glog.Info("rpc: block chain ", params.Name) + + return nil +} + +// GetBlock returns block with given hash. +func (g *GroestlcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { + var err error + if hash == "" && height > 0 { + hash, err = g.GetBlockHash(height) + if err != nil { + return nil, err + } + } + + glog.V(1).Info("rpc: getblock (verbosity=1) ", hash) + + res := btc.ResGetBlockThin{} + req := btc.CmdGetBlock{Method: "getblock"} + req.Params.BlockHash = hash + req.Params.Verbosity = 1 + err = g.Call(&req, &res) + + if err != nil { + return nil, errors.Annotatef(err, "hash %v", hash) + } + if res.Error != nil { + return nil, errors.Annotatef(res.Error, "hash %v", hash) + } + + txs := make([]bchain.Tx, 0, len(res.Result.Txids)) + for _, txid := range res.Result.Txids { + tx, err := g.GetTransaction(txid) + if err != nil { + if isInvalidTx(err) { + glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err) + continue + } + return nil, err + } + txs = append(txs, *tx) + } + block := &bchain.Block{ + BlockHeader: res.Result.BlockHeader, + Txs: txs, + } + return block, nil +} + +func isInvalidTx(err error) bool { + switch e1 := err.(type) { + case *errors.Err: + switch e2 := e1.Cause().(type) { + case *bchain.RPCError: + if e2.Code == -5 { // "No information available about transaction" + return true + } + } + } + + return false +} + +// GetTransactionForMempool returns a transaction by the transaction ID. +// It could be optimized for mempool, i.e. without block time and confirmations +func (g *GroestlcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { + return g.GetTransaction(txid) +} diff --git a/configs/coins/groestlcoin.json b/configs/coins/groestlcoin.json new file mode 100644 index 00000000..760799da --- /dev/null +++ b/configs/coins/groestlcoin.json @@ -0,0 +1,66 @@ +{ + "coin": { + "name": "Groestlcoin", + "shortcut": "GRS", + "label": "Groestlcoin", + "alias": "groestlcoin" + }, + "ports": { + "backend_rpc": 8045, + "backend_message_queue": 38345, + "blockbook_internal": 9045, + "blockbook_public": 9145 + }, + "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-groestlcoin", + "package_revision": "satoshilabs-1", + "system_user": "groestlcoin", + "version": "2.16.3", + "binary_url": "https://github.com/Groestlcoin/groestlcoin/releases/download/v2.16.3/groestlcoin-2.16.3-x86_64-linux-gnu.tar.gz", + "verification_type": "sha256", + "verification_source": "f15bd5e38b25a103821f1563cd0e1b2cf7146ec9f9835493a30bd57313d3b86f", + "extract_command": "mkdir -p backend/bin; tar -C backend/bin -xf", + "exclude_files": [ + "bin/groestlcoin-qt" + ], + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/groestlcoind -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": { + "deprecatedrpc": "estimatefee", + "whitelist": "127.0.0.1" + } + }, + "blockbook": { + "package_name": "blockbook-groestlcoin", + "system_user": "blockbook-groestlcoin", + "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": "Groestlcoin team", + "package_maintainer_email": "support@groestlcoin.org" + } +} diff --git a/configs/coins/groestlcoin_testnet.json b/configs/coins/groestlcoin_testnet.json new file mode 100644 index 00000000..46bc3248 --- /dev/null +++ b/configs/coins/groestlcoin_testnet.json @@ -0,0 +1,66 @@ +{ + "coin": { + "name": "Groestlcoin Testnet", + "shortcut": "tGRS", + "label": "Groestlcoin Testnet", + "alias": "groestlcoin_testnet" + }, + "ports": { + "backend_rpc": 18045, + "backend_message_queue": 48345, + "blockbook_internal": 19045, + "blockbook_public": 19145 + }, + "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-groestlcoin-testnet", + "package_revision": "satoshilabs-1", + "system_user": "groestlcoin", + "version": "2.16.3", + "binary_url": "https://github.com/Groestlcoin/groestlcoin/releases/download/v2.16.3/groestlcoin-2.16.3-x86_64-linux-gnu.tar.gz", + "verification_type": "sha256", + "verification_source": "f15bd5e38b25a103821f1563cd0e1b2cf7146ec9f9835493a30bd57313d3b86f", + "extract_command": "mkdir -p backend/bin; tar -C backend/bin -xf", + "exclude_files": [ + "bin/groestlcoin-qt" + ], + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/groestlcoind -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/testnet3/*.log", + "postinst_script_template": "", + "service_type": "forking", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": false, + "server_config_file": "bitcoin_like.conf", + "client_config_file": "bitcoin_like_client.conf", + "additional_params": { + "deprecatedrpc": "estimatefee", + "whitelist": "127.0.0.1" + } + }, + "blockbook": { + "package_name": "blockbook-groestlcoin-testnet", + "system_user": "blockbook-groestlcoin", + "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": "Groestlcoin team", + "package_maintainer_email": "support@groestlcoin.org" + } +} diff --git a/tests/rpc/testdata/groestlcoin.json b/tests/rpc/testdata/groestlcoin.json new file mode 100644 index 00000000..b3204694 --- /dev/null +++ b/tests/rpc/testdata/groestlcoin.json @@ -0,0 +1,57 @@ +{ + "blockHeight": 2294439, + "blockHash": "0000000000003e6b31abe139b028a97f4fe4dea10fd52a04c404cc85b4d7f773", + "blockTime": 1539462668, + "blockTxs": [ + "986e0848c7e0b438ad3816875ed6dc867393897a0e893e6006efefec0197f90d", + "dce355dd367e757ead8bbf4480d96885108d9f248d1e74e493ff4693f97cc11c", + "4b5f5892a385f75bcd8c5584cea2765f25976b38c450e98bc6d22e342f805ae1", + "dfa2ae8837705ee9c5b05ffc652d54dc1b5d38dd836d8b30c5b16c655db8a75b", + "0b41b9325d3366a3bba0bf2cf76218ea23ec74aca19c0ce37dc55b5cbcaa8b84", + "91a2a72dacf0774c7d4f37e0c9b011a3f747518c20ea6f44ee47d8d35aed4f1a", + "f13366400b6ee643f48aa40592382dbf3085c3e31f42e0283b0efd970533c55d", + "062f4f5eab8ef188922c197b8becf94ab292f6f1efff57173617b27380a55616" + ], + "txDetails": { + "4b5f5892a385f75bcd8c5584cea2765f25976b38c450e98bc6d22e342f805ae1": { + "hex": "020000000001011cc17cf99346ff93e4741e8d249f8d108568d98044bf8bad7e757e36dd55e3dc01000000171600142e9f7a9a16b2fcb817752f1f44c7518c83886cdefeffffff02fa76e3e50200000017a914b996e79692d2212707e59235f0a00f2f951c1ba487004d4466170000001976a914fcad3abf614562d224c6cc8b0e00d2fa9016404388ac0247304402206794af78bbfc6f39fa86788bdaff9959af9b519af133e696e2b1226a3df2c0830220254855ae4270af92a6add130efe41222cf150033f5a55225308cd0a39b7b73ee01210352b1a67fef7a34042ff4ed75cd375f22d2f5ea24353d3e6be363f967d9deb612a6022300", + "txid": "4b5f5892a385f75bcd8c5584cea2765f25976b38c450e98bc6d22e342f805ae1", + "blocktime": 1539462668, + "time": 1539462668, + "locktime": 2294438, + "version": 2, + "vin": [ + { + "txid": "dce355dd367e757ead8bbf4480d96885108d9f248d1e74e493ff4693f97cc11c", + "vout": 1, + "scriptSig": { + "hex": "1600142e9f7a9a16b2fcb817752f1f44c7518c83886cde" + }, + "sequence": 4294967294 + } + ], + "vout": [ + { + "value": 124.46824186, + "n": 0, + "scriptPubKey": { + "hex": "a914b996e79692d2212707e59235f0a00f2f951c1ba487", + "addresses": [ + "3JcKi541GubsiCdpdZqvsSy3rfA6R11tg7" + ] + } + }, + { + "value": 1005.00000000, + "n": 1, + "scriptPubKey": { + "hex": "76a914fcad3abf614562d224c6cc8b0e00d2fa9016404388ac", + "addresses": [ + "FtCkFSrwrgiJzjQzGRZvjHzrmHp4HJeGYm" + ] + } + } + ] + } + } +} diff --git a/tests/sync/testdata/groestlcoin.json b/tests/sync/testdata/groestlcoin.json new file mode 100644 index 00000000..ff475382 --- /dev/null +++ b/tests/sync/testdata/groestlcoin.json @@ -0,0 +1,68 @@ +{ + "connectBlocks": { + "syncRanges": [ + {"lower": 2200724, "upper": 2200744} + ], + "blocks": { + "2200744": { + "height": 2200744, + "hash": "000000000000239eef9c547395bdedb12c05377479a00a6e85cc2eac2ba33e18", + "noTxs": 1, + "txDetails": [ + { + "hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2003a8942104fb2e685b0837ff5e928d0000000d2f6e6f64655374726174756d2f00000000020000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90065cd1d000000001976a9147a2dd8d03f7ae3c1acc88d51213aaf7de20e62d088ac0120000000000000000000000000000000000000000000000000000000000000000000000000", + "txid": "d12a3d710831f88c02caaf66a6662b211ec05adfa94392ddc2c57edbb006b299", + "version": 1, + "vin": [ + { + "coinbase": "03a8942104fb2e685b0837ff5e928d0000000d2f6e6f64655374726174756d2f", + "sequence": 0 + } + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "hex": "6a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9" + } + }, + { + "value": 5.00000000, + "n": 1, + "scriptPubKey": { + "hex": "76a9147a2dd8d03f7ae3c1acc88d51213aaf7de20e62d088ac" + } + } + ] + } + ] + } + } + }, + "handleFork": { + "syncRanges": [ + {"lower": 2200724, "upper": 2200744} + ], + "fakeBlocks": { + "2200744": { + "height": 2200744, + "hash": "00000000000091c2f138f8e97dfda7256f8aee2d4ee4ad52cefbad837ca50a99" + }, + "2200743": { + "height": 2200743, + "hash": "000000000001596f4fd5ba68aa7a7e09d1a28096ea520940080fb1c128ca13a4" + } + }, + "realBlocks": { + "2200744": { + "height": 2200744, + "hash": "000000000000239eef9c547395bdedb12c05377479a00a6e85cc2eac2ba33e18" + }, + "2200743": { + "height": 2200743, + "hash": "000000000000b75b5efad34254aef25060f695a532589f993cf07f77986629df" + } + } + } +} diff --git a/tests/tests.json b/tests/tests.json index edf7d24b..f567aba7 100644 --- a/tests/tests.json +++ b/tests/tests.json @@ -40,6 +40,11 @@ "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"] }, + "groestlcoin": { + "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", + "EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"], + "sync": ["ConnectBlocksParallel", "ConnectBlocks", "HandleFork"] + }, "litecoin": { "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "EstimateSmartFee", "EstimateFee"],