Groestlcoin (GRS) support (#33)

This commit is contained in:
Yura Pakhuchiy 2018-10-18 23:08:19 +07:00 committed by Martin
parent ee3d145ca5
commit 11520bd18f
10 changed files with 724 additions and 2 deletions

10
Gopkg.lock generated
View File

@ -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"

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}
})
}
}

115
bchain/coins/grs/grsrpc.go Normal file
View File

@ -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)
}

View File

@ -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"
}
}

View File

@ -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"
}
}

57
tests/rpc/testdata/groestlcoin.json vendored Normal file
View File

@ -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"
]
}
}
]
}
}
}

68
tests/sync/testdata/groestlcoin.json vendored Normal file
View File

@ -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"
}
}
}
}

View File

@ -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"],