Merge branch 'rpc-tests'

This commit is contained in:
Jakub Matys 2018-06-18 15:21:27 +02:00
commit 7b19bf7312
30 changed files with 1044 additions and 335 deletions

View File

@ -3,26 +3,27 @@ DEB_IMAGE = blockbook-build-deb
PACKAGER = $(shell id -u):$(shell id -g)
NO_CACHE = false
UPDATE_VENDOR = 1
ARGS ?=
.PHONY: build build-debug test deb
build: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build ARGS="$(ARGS)"
build-debug: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build-debug
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
test: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src $(BIN_IMAGE) make test
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
test-all: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src $(BIN_IMAGE) make test-all
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
deb: .deb-image clean-deb
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE)
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh $(ARGS)
tools:
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make tools
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make tools ARGS="$(ARGS)"
all: build-images deb

View File

@ -8,9 +8,11 @@ import (
"github.com/juju/errors"
)
type AddressFactoryFunc func(string) (Address, error)
// BaseParser implements data parsing/handling functionality base for all other parsers
type BaseParser struct {
AddressFactory func(string) (Address, error)
AddressFactory AddressFactoryFunc
BlockAddressesToKeep int
}
@ -19,6 +21,11 @@ func (p *BaseParser) AddressToOutputScript(address string) ([]byte, error) {
return nil, errors.New("AddressToOutputScript: not implemented")
}
// OutputScriptToAddresses converts ScriptPubKey to addresses - currently not implemented
func (p *BaseParser) OutputScriptToAddresses(script []byte) ([]string, error) {
return nil, errors.New("OutputScriptToAddresses: not implemented")
}
// ParseBlock parses raw block to our Block struct - currently not implemented
func (p *BaseParser) ParseBlock(b []byte) (*Block, error) {
return nil, errors.New("ParseBlock: not implemented")

View File

@ -50,8 +50,8 @@ func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) (*BCashParser
AddressFactory: func(addr string) (bchain.Address, error) { return newBCashAddress(addr, format) },
BlockAddressesToKeep: c.BlockAddressesToKeep,
},
Params: params,
OutputScriptToAddresses: outputScriptToAddresses,
Params: params,
OutputScriptToAddressesFunc: outputScriptToAddresses,
},
AddressFormat: format,
}

View File

@ -1,3 +1,5 @@
// +build unittest
package bch
import (

View File

@ -0,0 +1,45 @@
// +build integration
package bch
import (
"blockbook/bchain"
"blockbook/bchain/tests/rpc"
"encoding/json"
"testing"
)
func getRPCClient(cfg json.RawMessage) (bchain.BlockChain, error) {
c, err := NewBCashRPC(cfg, nil)
if err != nil {
return nil, err
}
cli := c.(*BCashRPC)
cli.Parser, err = NewBCashParser(GetChainParams("test"), cli.ChainConfig)
if err != nil {
return nil, err
}
return cli, nil
}
var rpcTest *rpc.Test
func init() {
t, err := rpc.NewTest("Bcash Testnet", getRPCClient)
if err != nil {
panic(err)
}
rpcTest = t
}
func TestBCashRPC_GetBlockHash(t *testing.T) {
rpcTest.TestGetBlockHash(t)
}
func TestBCashRPC_GetBlock(t *testing.T) {
rpcTest.TestGetBlock(t)
}
func TestBCashRPC_GetTransaction(t *testing.T) {
rpcTest.TestGetTransaction(t)
}

View File

@ -20,8 +20,8 @@ type OutputScriptToAddressesFunc func(script []byte, params *chaincfg.Params) ([
// BitcoinParser handle
type BitcoinParser struct {
*bchain.BaseParser
Params *chaincfg.Params
OutputScriptToAddresses OutputScriptToAddressesFunc
Params *chaincfg.Params
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
}
// NewBitcoinParser returns new BitcoinParser instance
@ -72,6 +72,11 @@ func (p *BitcoinParser) AddressToOutputScript(address string) ([]byte, error) {
return script, nil
}
// OutputScriptToAddresses converts ScriptPubKey to bitcoin addresses
func (p *BitcoinParser) OutputScriptToAddresses(script []byte) ([]string, error) {
return p.OutputScriptToAddressesFunc(script, p.Params)
}
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
func outputScriptToAddresses(script []byte, params *chaincfg.Params) ([]string, error) {
_, addresses, _, err := txscript.ExtractPkScriptAddrs(script, params)
@ -110,7 +115,7 @@ func (p *BitcoinParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.T
for i, out := range t.TxOut {
addrs := []string{}
if parseAddresses {
addrs, _ = p.OutputScriptToAddresses(out.PkScript, p.Params)
addrs, _ = p.OutputScriptToAddresses(out.PkScript)
}
s := bchain.ScriptPubKey{
Hex: hex.EncodeToString(out.PkScript),

View File

@ -1,3 +1,5 @@
// +build unittest
package btc
import (

View File

@ -0,0 +1,45 @@
// +build integration
package btc
import (
"blockbook/bchain"
"blockbook/bchain/tests/rpc"
"encoding/json"
"testing"
)
func getRPCClient(cfg json.RawMessage) (bchain.BlockChain, error) {
c, err := NewBitcoinRPC(cfg, nil)
if err != nil {
return nil, err
}
cli := c.(*BitcoinRPC)
cli.Parser = NewBitcoinParser(GetChainParams("test"), cli.ChainConfig)
if err != nil {
return nil, err
}
return cli, nil
}
var rpcTest *rpc.Test
func init() {
t, err := rpc.NewTest("Bitcoin Testnet", getRPCClient)
if err != nil {
panic(err)
}
rpcTest = t
}
func TestBitcoinRPC_GetBlockHash(t *testing.T) {
rpcTest.TestGetBlockHash(t)
}
func TestBitcoinRPC_GetBlock(t *testing.T) {
rpcTest.TestGetBlock(t)
}
func TestBitcoinRPC_GetTransaction(t *testing.T) {
rpcTest.TestGetTransaction(t)
}

View File

@ -1,3 +1,5 @@
// +build unittest
package btg
import (

View File

@ -0,0 +1,42 @@
// +build integration
package dash
import (
"blockbook/bchain"
"blockbook/bchain/tests/rpc"
"encoding/json"
"testing"
)
func getRPCClient(cfg json.RawMessage) (bchain.BlockChain, error) {
c, err := NewDashRPC(cfg, nil)
if err != nil {
return nil, err
}
cli := c.(*DashRPC)
cli.Parser = NewDashParser(GetChainParams("test"), cli.ChainConfig)
return cli, nil
}
var rpcTest *rpc.Test
func init() {
t, err := rpc.NewTest("Dash Testnet", getRPCClient)
if err != nil {
panic(err)
}
rpcTest = t
}
func TestDashRPC_GetBlockHash(t *testing.T) {
rpcTest.TestGetBlockHash(t)
}
func TestDashRPC_GetBlock(t *testing.T) {
rpcTest.TestGetBlock(t)
}
func TestDashRPC_GetTransaction(t *testing.T) {
rpcTest.TestGetTransaction(t)
}

View File

@ -1,3 +1,5 @@
// +build unittest
package eth
import (

View File

@ -1,44 +1,48 @@
// +build integration
package eth
import (
"blockbook/bchain"
"flag"
"blockbook/bchain/tests/rpc"
"encoding/json"
"reflect"
"testing"
"time"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
)
var rpcURL = flag.String("rpc", "ws://localhost:18036", "URL of geth server")
var ethClient *ethclient.Client
var ethRPCClient *rpc.Client
func getRPCClient(cfg json.RawMessage) (bchain.BlockChain, error) {
c, err := NewEthereumRPC(cfg, nil)
if err != nil {
return nil, err
}
return c, nil
}
func setupEthRPC() *EthereumRPC {
if ethClient == nil {
rc, err := rpc.Dial(*rpcURL)
if err != nil {
panic(err)
}
ec := ethclient.NewClient(rc)
ethRPCClient = rc
ethClient = ec
}
return &EthereumRPC{
client: ethClient,
rpc: ethRPCClient,
timeout: time.Duration(25) * time.Second,
rpcURL: *rpcURL,
Parser: NewEthereumParser(),
var rpcTest *rpc.Test
func init() {
t, err := rpc.NewTest("Ethereum Testnet", getRPCClient)
if err != nil {
panic(err)
}
rpcTest = t
}
func TestEthRPC_GetBlockHash(t *testing.T) {
rpcTest.TestGetBlockHash(t)
}
func TestEthRPC_GetBlock(t *testing.T) {
rpcTest.TestGetBlock(t)
}
func TestEthRPC_GetTransaction(t *testing.T) {
rpcTest.TestGetTransaction(t)
}
func TestEthRPC_getBestHeader(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
@ -51,7 +55,7 @@ func TestEthRPC_getBestHeader(t *testing.T) {
{
name: "1",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
},
}
@ -68,9 +72,6 @@ func TestEthRPC_getBestHeader(t *testing.T) {
}
func TestEthRPC_GetBestBlockHash(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
@ -83,7 +84,7 @@ func TestEthRPC_GetBestBlockHash(t *testing.T) {
{
name: "1",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
want: 66,
},
@ -104,9 +105,6 @@ func TestEthRPC_GetBestBlockHash(t *testing.T) {
}
func TestEthRPC_GetBestBlockHeight(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
@ -119,7 +117,7 @@ func TestEthRPC_GetBestBlockHeight(t *testing.T) {
{
name: "1",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
want: 1000000,
},
@ -138,74 +136,8 @@ func TestEthRPC_GetBestBlockHeight(t *testing.T) {
}
}
func TestEthRPC_GetBlockHash(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
type args struct {
height uint32
}
tests := []struct {
name string
fields fields
args args
want string
wantErr error
}{
{
name: "1000000",
fields: fields{
b: setupEthRPC(),
},
args: args{
height: 1000000,
},
want: "0x6e6b2e771a3026a1981227ab4a4c8d018edb568494f17df46bcddfa427df686e",
},
{
name: "2870000",
fields: fields{
b: setupEthRPC(),
},
args: args{
height: 2870000,
},
want: "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
},
{
name: "ErrBlockNotFound",
fields: fields{
b: setupEthRPC(),
},
args: args{
height: 1 << 31,
},
want: "",
wantErr: bchain.ErrBlockNotFound,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.fields.b.GetBlockHash(tt.args.height)
if err != tt.wantErr {
t.Errorf("EthRPC.GetBlockHash() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("EthRPC.GetBlockHash() = %v, want %v", got, tt.want)
}
})
}
}
func TestEthRPC_GetBlockHeader(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
bh, err := setupEthRPC().getBestHeader()
bh, err := rpcTest.Client.(*EthereumRPC).getBestHeader()
if err != nil {
panic(err)
}
@ -225,7 +157,7 @@ func TestEthRPC_GetBlockHeader(t *testing.T) {
{
name: "2870000",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
args: args{
hash: "eccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
@ -239,7 +171,7 @@ func TestEthRPC_GetBlockHeader(t *testing.T) {
{
name: "ErrBlockNotFound",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
args: args{
hash: "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903896",
@ -261,214 +193,7 @@ func TestEthRPC_GetBlockHeader(t *testing.T) {
}
}
func TestEthRPC_GetBlock(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
bh, err := setupEthRPC().getBestHeader()
if err != nil {
panic(err)
}
type fields struct {
b *EthereumRPC
}
type args struct {
hash string
height uint32
}
tests := []struct {
name string
fields fields
args args
want *bchain.Block
wantTxCount int
wantErr error
}{
{
name: "2870000 by hash",
fields: fields{
b: setupEthRPC(),
},
args: args{
hash: "eccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
},
want: &bchain.Block{
BlockHeader: bchain.BlockHeader{
Hash: "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
Height: 2870000,
Confirmations: int(uint32(bh.Number.Uint64()) - 2870000 + 1),
},
},
wantTxCount: 12,
},
{
name: "2870000 by height",
fields: fields{
b: setupEthRPC(),
},
args: args{
height: 2870000,
},
want: &bchain.Block{
BlockHeader: bchain.BlockHeader{
Hash: "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
Height: 2870000,
Confirmations: int(uint32(bh.Number.Uint64()) - 2870000 + 1),
},
},
wantTxCount: 12,
},
{
name: "ErrBlockNotFound",
fields: fields{
b: setupEthRPC(),
},
args: args{
hash: "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903896",
},
wantErr: bchain.ErrBlockNotFound,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.fields.b.GetBlock(tt.args.hash, tt.args.height)
if err != tt.wantErr {
t.Errorf("EthRPC.GetBlock() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got == nil && tt.want == nil {
return
}
if got.Hash != tt.want.Hash {
t.Errorf("EthRPC.GetBlock().Hash = %v, want %v", got.Hash, tt.want.Hash)
return
}
if got.Height != tt.want.Height {
t.Errorf("EthRPC.GetBlock().Height = %v, want %v", got.Height, tt.want.Height)
return
}
if got.Confirmations != tt.want.Confirmations {
t.Errorf("EthRPC.GetBlock().Confirmations = %v, want %v", got.Confirmations, tt.want.Confirmations)
return
}
if len(got.Txs) != tt.wantTxCount {
t.Errorf("EthRPC.GetBlock().Txs = %v, want %v", len(got.Txs), tt.wantTxCount)
return
}
})
}
}
func TestEthRPC_GetTransaction(t *testing.T) {
var (
addr1, addr2 bchain.Address
err error
)
addr1, err = bchain.NewBaseAddress("0x682b7903a11098cf770c7aef4aa02a85b3f3601a")
if err == nil {
addr2, err = bchain.NewBaseAddress("0x555ee11fbddc0e49a9bab358a8941ad95ffdb48f")
}
if err != nil {
panic(err)
}
if testing.Short() {
t.Skip("skipping test in short mode.")
}
bh, err := setupEthRPC().getBestHeader()
if err != nil {
panic(err)
}
type fields struct {
b *EthereumRPC
}
type args struct {
txid string
}
tests := []struct {
name string
fields fields
args args
want *bchain.Tx
wantErr bool
}{
{
name: "1",
fields: fields{
b: setupEthRPC(),
},
args: args{
txid: "0xe6b168d6bb3d8ed78e03dbf828b6bfd1fb613f6e129cba624964984553724c5d",
},
want: &bchain.Tx{
Blocktime: 1521515026,
Confirmations: uint32(bh.Number.Uint64()) - 2870000 + 1,
Hex: "7b226e6f6e6365223a2230783239666165222c226761735072696365223a223078313261303566323030222c22676173223a2230786462626130222c22746f223a22307836383262373930336131313039386366373730633761656634616130326138356233663336303161222c2276616c7565223a22307830222c22696e707574223a223078663032356361616630303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030323235222c2268617368223a22307865366231363864366262336438656437386530336462663832386236626664316662363133663665313239636261363234393634393834353533373234633564222c22626c6f636b4e756d626572223a223078326263616630222c2266726f6d223a22307864616363396336313735346130633436313666633533323364633934366538396562323732333032222c227472616e73616374696f6e496e646578223a22307831222c2276223a2230783162222c2272223a22307831626434306133313132326330333931386466366431363664373430613661336132326630386132353933346365623136383863363239373736363163383063222c2273223a22307836303766626331356331663739393561343235386635613962636363363362303430333632643139393164356566653133363163353632323265346361383966227d",
Time: 1521515026,
Txid: "0xe6b168d6bb3d8ed78e03dbf828b6bfd1fb613f6e129cba624964984553724c5d",
Vin: []bchain.Vin{
{
Addresses: []string{"0xdacc9c61754a0c4616fc5323dc946e89eb272302"},
},
},
Vout: []bchain.Vout{
{
ScriptPubKey: bchain.ScriptPubKey{
Addresses: []string{"0x682b7903a11098cf770c7aef4aa02a85b3f3601a"},
},
Address: addr1,
},
},
},
},
{
name: "2",
fields: fields{
b: setupEthRPC(),
},
args: args{
txid: "cd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
},
want: &bchain.Tx{
Blocktime: 1521533434,
Confirmations: uint32(bh.Number.Uint64()) - 2871048 + 1,
Hex: "7b226e6f6e6365223a22307862323663222c226761735072696365223a223078343330653233343030222c22676173223a22307835323038222c22746f223a22307835353565653131666264646330653439613962616233353861383934316164393566666462343866222c2276616c7565223a22307831626330313539643533306536303030222c22696e707574223a223078222c2268617368223a22307863643634373135313535326235313332623261656637633962653030646336663733616663353930316464653135376161623133313333356261616138353362222c22626c6f636b4e756d626572223a223078326263663038222c2266726f6d223a22307833653361336436396463363662613130373337663533316564303838393534613965633839643937222c227472616e73616374696f6e496e646578223a22307861222c2276223a2230783239222c2272223a22307866373136316331373064343335373361643963386437303163646166373134666632613534386135363262306463363339323330643137383839666364343035222c2273223a22307833633439373766633930333835613237656661303033326531376234396664353735623238323663623536653364316563663231353234663261393466393135227d",
Time: 1521533434,
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
Vin: []bchain.Vin{
{
Addresses: []string{"0x3e3a3d69dc66ba10737f531ed088954a9ec89d97"},
},
},
Vout: []bchain.Vout{
{
ScriptPubKey: bchain.ScriptPubKey{
Addresses: []string{"0x555ee11fbddc0e49a9bab358a8941ad95ffdb48f"},
},
Address: addr2,
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.fields.b.GetTransaction(tt.args.txid)
if (err != nil) != tt.wantErr {
t.Errorf("EthRPC.GetTransaction() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("EthRPC.GetTransaction() = %v, want %v", got, tt.want)
}
})
}
}
func TestEthRPC_EstimateFee(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
@ -485,7 +210,7 @@ func TestEthRPC_EstimateFee(t *testing.T) {
{
name: "1",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
args: args{
blocks: 10,
@ -508,9 +233,6 @@ func TestEthRPC_EstimateFee(t *testing.T) {
}
func TestEthRPC_GetMempool(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
type fields struct {
b *EthereumRPC
}
@ -523,7 +245,7 @@ func TestEthRPC_GetMempool(t *testing.T) {
{
name: "1",
fields: fields{
b: setupEthRPC(),
b: rpcTest.Client.(*EthereumRPC),
},
},
}

View File

@ -1,3 +1,5 @@
// +build unittest
package litecoin
import (

View File

@ -1,3 +1,5 @@
// +build unittest
package zec
import (

View File

@ -0,0 +1,42 @@
// +build integration
package zec
import (
"blockbook/bchain"
"blockbook/bchain/tests/rpc"
"encoding/json"
"testing"
)
func getRPCClient(cfg json.RawMessage) (bchain.BlockChain, error) {
c, err := NewZCashRPC(cfg, nil)
if err != nil {
return nil, err
}
cli := c.(*ZCashRPC)
cli.Parser = NewZCashParser(cli.ChainConfig)
return cli, nil
}
var rpcTest *rpc.Test
func init() {
t, err := rpc.NewTest("Zcash Testnet", getRPCClient)
if err != nil {
panic(err)
}
rpcTest = t
}
func TestZCashRPC_GetBlockHash(t *testing.T) {
rpcTest.TestGetBlockHash(t)
}
func TestZCashRPC_GetBlock(t *testing.T) {
rpcTest.TestGetBlock(t)
}
func TestZCashRPC_GetTransaction(t *testing.T) {
rpcTest.TestGetTransaction(t)
}

View File

@ -0,0 +1,27 @@
{
"Bcash Testnet": {
"url": "http://localhost:18031",
"user": "rpc",
"pass": "rpc"
},
"Bitcoin Testnet": {
"url": "http://localhost:18030",
"user": "rpc",
"pass": "rpc"
},
"Dash Testnet": {
"url": "http://localhost:18033",
"user": "rpc",
"pass": "rpc"
},
"Ethereum Testnet": {
"url": "ws://localhost:18036",
"user": null,
"pass": null
},
"Zcash Testnet": {
"url": "http://localhost:18032",
"user": "rpc",
"pass": "rpc"
}
}

97
bchain/tests/rpc/data.go Normal file
View File

@ -0,0 +1,97 @@
// +build integration
package rpc
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
)
func joinPathsWithCommonElement(p1, p2 string) (string, bool) {
idx := strings.IndexRune(p2, filepath.Separator)
if idx <= 0 {
return "", false
}
p2root := p2[:idx]
idx = strings.LastIndex(p1, p2root)
if idx < 0 {
return "", false
}
prefix := p1[:idx]
return filepath.Join(prefix, p2), true
}
func readDataFile(dir, relDir, filename string) ([]byte, error) {
var err error
dir, err = filepath.Abs(dir)
if err == nil {
dir, err = filepath.EvalSymlinks(dir)
}
if err != nil {
return nil, err
}
path, ok := joinPathsWithCommonElement(dir, relDir)
if !ok {
return nil, errors.New("Path not found")
}
filename = strings.Replace(filename, " ", "_", -1)
path = filepath.Join(path, filename)
return ioutil.ReadFile(path)
}
var testConfigRegistry map[string]*TestConfig
func LoadTestConfig(coin string) (*TestConfig, error) {
if testConfigRegistry == nil {
b, err := readDataFile(".", "bchain/tests/rpc", "config.json")
if err != nil {
return nil, err
}
var v map[string]*TestConfig
err = json.Unmarshal(b, &v)
if err != nil {
return nil, err
}
testConfigRegistry = v
}
c, found := testConfigRegistry[coin]
if !found {
return nil, errors.New("Test config not found")
}
return c, nil
}
func LoadRPCConfig(coin string) (json.RawMessage, error) {
t := `{
"coin_name": "%s",
"rpcURL": "%s",
"rpcUser": "%s",
"rpcPass": "%s",
"rpcTimeout": 25,
"parse": true
}`
c, err := LoadTestConfig(coin)
if err != nil {
return json.RawMessage{}, err
}
return json.RawMessage(fmt.Sprintf(t, coin, c.URL, c.User, c.Pass)), nil
}
func LoadTestData(coin string) (*TestData, error) {
b, err := readDataFile(".", "bchain/tests/rpc/testdata", coin+".json")
if err != nil {
return nil, err
}
var v TestData
err = json.Unmarshal(b, &v)
if err != nil {
return nil, err
}
return &v, nil
}

126
bchain/tests/rpc/rpc.go Normal file
View File

@ -0,0 +1,126 @@
// +build integration
package rpc
import (
"blockbook/bchain"
"encoding/json"
"reflect"
"testing"
)
type TestConfig struct {
URL string `json:"url"`
User string `json:"user"`
Pass string `json:"pass"`
}
type TestData struct {
BlockHeight uint32 `json:"blockHeight"`
BlockHash string `json:"blockHash"`
BlockHex string `json:"blockHex"`
BlockTxs []string `json:"blockTxs"`
TxDetails map[string]*bchain.Tx `json:"txDetails"`
}
type Test struct {
Client bchain.BlockChain
TestData *TestData
}
type TestChainFactoryFunc func(json.RawMessage) (bchain.BlockChain, error)
func NewTest(coin string, factory TestChainFactoryFunc) (*Test, error) {
cfg, err := LoadRPCConfig(coin)
if err != nil {
return nil, err
}
cli, err := factory(cfg)
if err != nil {
return nil, err
}
td, err := LoadTestData(coin)
if err != nil {
return nil, err
}
if td.TxDetails != nil {
parser := cli.GetChainParser()
for _, tx := range td.TxDetails {
err := setTxAddresses(parser, tx)
if err != nil {
return nil, err
}
}
}
return &Test{Client: cli, TestData: td}, nil
}
func setTxAddresses(parser bchain.BlockChainParser, tx *bchain.Tx) error {
// pack and unpack transaction in order to get addresses decoded - ugly but works
var tmp *bchain.Tx
b, err := parser.PackTx(tx, 0, 0)
if err == nil {
tmp, _, err = parser.UnpackTx(b)
if err == nil {
for i := 0; i < len(tx.Vout); i++ {
tx.Vout[i].ScriptPubKey.Addresses = tmp.Vout[i].ScriptPubKey.Addresses
tx.Vout[i].Address = tmp.Vout[i].Address
}
}
}
return err
}
func (rt *Test) TestGetBlockHash(t *testing.T) {
hash, err := rt.Client.GetBlockHash(rt.TestData.BlockHeight)
if err != nil {
t.Error(err)
return
}
if hash != rt.TestData.BlockHash {
t.Errorf("GetBlockHash() got %q, want %q", hash, rt.TestData.BlockHash)
}
}
func (rt *Test) TestGetBlock(t *testing.T) {
blk, err := rt.Client.GetBlock(rt.TestData.BlockHash, 0)
if err != nil {
t.Error(err)
return
}
if len(blk.Txs) != len(rt.TestData.BlockTxs) {
t.Errorf("GetBlock() number of transactions: got %d, want %d", len(blk.Txs), len(rt.TestData.BlockTxs))
}
for ti, tx := range blk.Txs {
if tx.Txid != rt.TestData.BlockTxs[ti] {
t.Errorf("GetBlock() transaction %d: got %s, want %s", ti, tx.Txid, rt.TestData.BlockTxs[ti])
}
}
}
func (rt *Test) TestGetTransaction(t *testing.T) {
for txid, want := range rt.TestData.TxDetails {
got, err := rt.Client.GetTransaction(txid)
if err != nil {
t.Error(err)
return
}
// Confirmations is variable field, we just check if is set and reset it
if got.Confirmations > 0 {
got.Confirmations = 0
} else {
t.Errorf("GetTransaction() has empty Confirmations field")
continue
}
if !reflect.DeepEqual(got, want) {
t.Errorf("GetTransaction() got %v, want %v", got, want)
}
}
}

View File

@ -0,0 +1,145 @@
{
"blockHeight": 1239639,
"blockHash": "0000000075dd9708c23f5830de27c5d644983bb877c575c52926f19be7d80fe2",
"blockTxs": [
"f12d490ad439ff37c91e9ec5ecd5440c2d4a96653f2668402c5ebacc6d07dcf8",
"0e78e3276bd59dd403306334ab05b2d58167b4cf04dbb94ae76dc189db5bf3df",
"9eeba85181725993afc6a89e2e98c07e12bbd9c732b851af448eb6055d8d8ba7",
"045f898538c5b9a99a4bf21c8e06aa7279caacdf7616994b7d4f0ed39637dff7",
"8614ae1addce0983f8b1bb2e6139fca4e7aa2d4f57f28ce1145bd1103c75a307",
"1d10b63e6d336b19ce7f7a867639b52b42be7e63ea53a86e5c7b101eb8f5bf59",
"1cbb193374d455ad09f1ae4486418dbbd65435ac14b1b8733897976bd776478b",
"722d99abace73265477b42849c86f9a8460a07aef7497187db24cffb4b27c856",
"a856b35655852ec5d698561633f997b945ee03d57a7b60e3c86eaabdd3a90054",
"e82cdbb67f6c23c72d0273bdd976697d5bfc4b2373e637f4eeb5211134b84bd6",
"efd3295c37cd3988f16efc09d083dbbc27f5c0074b9ea0dffd4f8540b36dd02c",
"b955bc3e800aa6d72c1a9eb9ce4a513f409ec923c31e30075f58336c830040a8",
"9730ec3e10e5a3bf358e533a497e75f44aceaf28da8248534326e5d7dac0d048",
"a90df75c045e638a0c00902d35c9c72592d0e76ac0fa34fba6aad749c5aded21",
"0e21dd654596cac9f579e21a549a533d1be7319470fcf8f920a35d64cf020d1f"
],
"txDetails": {
"9eeba85181725993afc6a89e2e98c07e12bbd9c732b851af448eb6055d8d8ba7": {
"hex": "0200000001b2c673aede02a4054a8c23e456e581d684f47dadb54083317d6152949d55d94e010000006b483045022100f31a23984a44f485a570a102899e3a25cdf6d1234259e602dbe61f2c3e77e490022069a6a7b013452bd66ed3c11aba22a64559134cd1af3d283730a9b7fb33631cca412103cb05918b81d36c387c791d2accfaefead287a4a30427387fb1095fc0c363ef8efeffffff0200c2eb0b0000000017a914ac90ed8510c9a7445b104fd1602341dc2f890d15878906e1e1160000001976a9147f7ed17e71afc40beac9b8d0b0fb53731161339c88ac56ea1200",
"txid": "9eeba85181725993afc6a89e2e98c07e12bbd9c732b851af448eb6055d8d8ba7",
"blocktime":1528796166,
"time":1528796166,
"locktime": 1239638,
"vin": [
{
"txid": "4ed9559d9452617d318340b5ad7df484d681e556e4238c4a05a402deae73c6b2",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100f31a23984a44f485a570a102899e3a25cdf6d1234259e602dbe61f2c3e77e490022069a6a7b013452bd66ed3c11aba22a64559134cd1af3d283730a9b7fb33631cca412103cb05918b81d36c387c791d2accfaefead287a4a30427387fb1095fc0c363ef8e"
}
}
],
"vout": [
{
"value": 2.0,
"n": 0,
"scriptPubKey": {
"hex": "a914ac90ed8510c9a7445b104fd1602341dc2f890d1587"
}
},
{
"value": 982.78901385,
"n": 1,
"scriptPubKey": {
"hex": "76a9147f7ed17e71afc40beac9b8d0b0fb53731161339c88ac"
}
}
]
},
"0e21dd654596cac9f579e21a549a533d1be7319470fcf8f920a35d64cf020d1f": {
"hex": "0200000008349c1ef994e931d4da1f545d2e578f898ddf457392c5485dc75378de8f36bef4010000006a4730440220351f1566e3ef02e900942103c60cba5a768cd710d3d1afbc75406099ad2d9e4702206e0f639a9991c7afb2136fb2e437629103ad0989898d1c90078ded5f08f5cb3341210303ae341929bdb242226a9a8c15cdbed5b89fa286842714d8be7e3f16c63abe11feffffff4ae685c8efc7f090e75b80f1b705d7bf5fa6dbbcf88c5f5cf2dc0678a9646fb4000000006b483045022100b8dae1825b0d0ccbe212e8da6767ea049bad9acfc737e5c5ef3dc5eeef6d313c02207e4c669956f871a4a5f71903bf38a8c587b81940943682364b11fb1cd9c078d7412103c9bd0064d2759628c1f6e5ad9d6345a5bce64dc4f4bb0675162f77acd557e4e2feffffff1ac21ded05387165cb7d0d95e2036a82f79a314575f065407e0c32a6b24b2f1d010000006b483045022100ef4a9469a5b3dbc0f03e8d8c5f254ad86f2c1e92e75a5ee737c3b3186b5edd95022076abcdfa976c3c78d2b196fb79699057248fad6d3d5e782524b85d84704394cc412103882df93f092501520bb36206703dadb65b25a3fbd0323c690dc8e72f5ee4a770feffffffea6905abb313a2aa3f6c8a056294abe06774dbf75688b03b96b8a2132aaf0cbf010000006b483045022100e4ab9dd0a75bc76c6c2cf549fb37c5577bad7f58953a7103abe4a77a95b873c10220545aa0c2b2869d444fb99d237549d6ac270c711d60788a6463ef4fee63ebd8fc4121031adea1da6e87b0771ea8c2a4723127d8cc9328b0594d159570ebe97b1e021c9efeffffff8c9a7a668dad3766f953d9779861f9c007b0a06f6ea2afbf8ab30137f34300fa000000006a47304402207253f724d891f5e1e66ec0c8084ade910a52257a1257933c23bd1b4da862e33a0220363df96e31dffa0a599b56c5049519a4d8ed34e96dc1fefecfd2bc31fc6d79d9412103186a4fc8445b3b437587c71f00fc9da7a267c0a38915fcf567528e310a73c0bdfeffffff82445d5b10b84b5256ef028615465e2d139c45584884c06e68bc38930d826e72010000006a47304402204846adc41599336307a087d4fa779a059ffe12c69456c82fa4b03942c901284002203e5f0c5e72b9ded7f48b4d22cbdb39390bea33003d46d8b4652c8ede1f13b3e54121031adea1da6e87b0771ea8c2a4723127d8cc9328b0594d159570ebe97b1e021c9efeffffffb8816c2c3b95aa8126f6d2d04798632b3167e6e2144d5f4e84cfb29e9d6f442d010000006a473044022078b1aff9a4ed3452f782db38341d846edd295f9a907c7373519408fb33eeb3240220578da5e91ec0c82604982b09cbd1f44e28260fcd640bcc55f086ce296ef32ef7412103c9bd0064d2759628c1f6e5ad9d6345a5bce64dc4f4bb0675162f77acd557e4e2feffffff70628ac9b2814f99fe4cd5f67a76047af533774ae90331fa8cb68e4dcbff1cb0010000006b483045022100cd88592589ab3bbd6e23920770a067a37ffbff3a31238167731377f11903676202202cb1c019365870dad3113abb3b0bc68ab9e65d9d60592f3315ffa444dfd88be741210393bd44ad6ed9295bf408e01bcdbdf6e4e8fd4a573ad20f37e54ff6e9b1596028feffffff027f766c02000000001976a9149f96c6e6c3aabf438eef5c589c47fa4b4f96592a88ac1c3d0f00000000001976a914e2ffd7cf2fe9468512878196d1b48fee9e9d003288ac56ea1200",
"txid": "0e21dd654596cac9f579e21a549a533d1be7319470fcf8f920a35d64cf020d1f",
"blocktime":1528796166,
"time":1528796166,
"locktime": 1239638,
"vin": [
{
"txid": "f4be368fde7853c75d48c5927345df8d898f572e5d541fdad431e994f91e9c34",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "4730440220351f1566e3ef02e900942103c60cba5a768cd710d3d1afbc75406099ad2d9e4702206e0f639a9991c7afb2136fb2e437629103ad0989898d1c90078ded5f08f5cb3341210303ae341929bdb242226a9a8c15cdbed5b89fa286842714d8be7e3f16c63abe11"
}
},
{
"txid": "b46f64a97806dcf25c5f8cf8bcdba65fbfd705b7f1805be790f0c7efc885e64a",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100b8dae1825b0d0ccbe212e8da6767ea049bad9acfc737e5c5ef3dc5eeef6d313c02207e4c669956f871a4a5f71903bf38a8c587b81940943682364b11fb1cd9c078d7412103c9bd0064d2759628c1f6e5ad9d6345a5bce64dc4f4bb0675162f77acd557e4e2"
}
},
{
"txid": "1d2f4bb2a6320c7e4065f07545319af7826a03e2950d7dcb65713805ed1dc21a",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100ef4a9469a5b3dbc0f03e8d8c5f254ad86f2c1e92e75a5ee737c3b3186b5edd95022076abcdfa976c3c78d2b196fb79699057248fad6d3d5e782524b85d84704394cc412103882df93f092501520bb36206703dadb65b25a3fbd0323c690dc8e72f5ee4a770"
}
},
{
"txid": "bf0caf2a13a2b8963bb08856f7db7467e0ab9462058a6c3faaa213b3ab0569ea",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100e4ab9dd0a75bc76c6c2cf549fb37c5577bad7f58953a7103abe4a77a95b873c10220545aa0c2b2869d444fb99d237549d6ac270c711d60788a6463ef4fee63ebd8fc4121031adea1da6e87b0771ea8c2a4723127d8cc9328b0594d159570ebe97b1e021c9e"
}
},
{
"txid": "fa0043f33701b38abfafa26e6fa0b007c0f9619877d953f96637ad8d667a9a8c",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "47304402207253f724d891f5e1e66ec0c8084ade910a52257a1257933c23bd1b4da862e33a0220363df96e31dffa0a599b56c5049519a4d8ed34e96dc1fefecfd2bc31fc6d79d9412103186a4fc8445b3b437587c71f00fc9da7a267c0a38915fcf567528e310a73c0bd"
}
},
{
"txid": "726e820d9338bc686ec0844858459c132d5e46158602ef56524bb8105b5d4482",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "47304402204846adc41599336307a087d4fa779a059ffe12c69456c82fa4b03942c901284002203e5f0c5e72b9ded7f48b4d22cbdb39390bea33003d46d8b4652c8ede1f13b3e54121031adea1da6e87b0771ea8c2a4723127d8cc9328b0594d159570ebe97b1e021c9e"
}
},
{
"txid": "2d446f9d9eb2cf844e5f4d14e2e667312b639847d0d2f62681aa953b2c6c81b8",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "473044022078b1aff9a4ed3452f782db38341d846edd295f9a907c7373519408fb33eeb3240220578da5e91ec0c82604982b09cbd1f44e28260fcd640bcc55f086ce296ef32ef7412103c9bd0064d2759628c1f6e5ad9d6345a5bce64dc4f4bb0675162f77acd557e4e2"
}
},
{
"txid": "b01cffcb4d8eb68cfa3103e94a7733f57a04767af6d54cfe994f81b2c98a6270",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100cd88592589ab3bbd6e23920770a067a37ffbff3a31238167731377f11903676202202cb1c019365870dad3113abb3b0bc68ab9e65d9d60592f3315ffa444dfd88be741210393bd44ad6ed9295bf408e01bcdbdf6e4e8fd4a573ad20f37e54ff6e9b1596028"
}
}
],
"vout": [
{
"value": 0.40662655,
"n": 0,
"scriptPubKey": {
"hex": "76a9149f96c6e6c3aabf438eef5c589c47fa4b4f96592a88ac"
}
},
{
"value": 0.00998684,
"n": 1,
"scriptPubKey": {
"hex": "76a914e2ffd7cf2fe9468512878196d1b48fee9e9d003288ac"
}
}
]
}
}
}

View File

@ -0,0 +1,123 @@
{
"blockHeight": 1325168,
"blockHash": "000000000000004ed0834f3de922e66d024ec4da9fcc2da17be61369cb6dc041",
"blockTxs": [
"e1179f205aabbf48dc2ce4ebd9ed255571b0578e4de551f6574a50cb81120007",
"00a5aa2891d41af9eb1dc30c940f142a609ecab8f370eb0874ba7d32252d1b1b",
"1c519d80804dd17258cfc801bf2c875607956fc9f065a664f43e88d53f80af6f",
"b10c1e2f7c8a6b10fddf94260aff0f8a5f56e33c8d0de48c49a72eb8418c3f6e",
"ba85ca543b290deb84cde9c4ca53614dbe557a3dede5d0adb141f803f8e82f34",
"60dfc2c9cc184ae68ca9e540ab4393d9d2179d060e2ac290f29560c6a1360f51",
"3a40bca678653ae8f7f6d2771b571d5ace1a258056b99e3fd361a10f1016bc53",
"4d4e495f3329801d92c7e3dc9874a372576bf3548decf884ede388143980ecab",
"74ba4bee8d559e4d8b4859c086b0ea5f2c36bcabc95d8578e775f065f70943b8",
"32bcc281f081e172dcb40ad137564724bd9486095813b78990d1d986173ac3c6",
"b6e77c59f4a988731d9b8520e0f4971223e622946eb12e28cc2bab72f1e9c2f8",
"0bc8f39da5d5300a2728b45edb18c8219e94a8b27a2e8074f6c5c10a00d99788",
"8329b31d2a490d57980afcf5c7df4574ce57f952aef6f5aecb3b7786f5c9f255",
"e559c2fd0f4e8aebe28fcb6dbb099fc6ee92d726d74fda28522f52bc1490a470",
"3005378ee85fc905a1812bdfae4b2e0e9bb09f5867a53fd73237bb319a1774aa",
"ebea245b9e4d96fab65c938547a9b3ffd03659b92b8ae4fcdfe4ac9bc325c0a2",
"a2d5fe23b50253dda9941dd6c97c04853d58f048acf347acf9ccf549ee215b51",
"017c2ccec866850521db877c1c7f6d095b7df668f891cfaf70a5e14ce39d010c",
"d101d3467a831cc4dfc87bdd19d0ff5d01b8c872e47b2096eeeac3b44c2a258a",
"3884180bab62d0f0498a8ad012b0005aceec778a18a617e5392d99cee5f21869",
"a00200e57bed4fbd193c4cad49549d311282fee9a82956083353a2874f9bfd9f",
"d32ce7a9413111fb2e3578472d520eb1437db701f20256e3afd37b7c0a6d67e6",
"fed1df6d23a40e1a1f26820bbe35febb668aa2240902f1fd17b31a84dde6eb39",
"5bef621ad6d0970939ae36270a3228d3c315f8008fb04eebffab5f7a3589d114",
"411e7f3f4cae4125c8933403809771ebfcaa088f6ef773e5a412ead8639fb515",
"d53858bbbbde4518ea92abda93ac5d01e5122d420a468e6d076244edd99bcea1",
"b5fc4d963805b439d11f06b5d5d89ce3aac225e7145d1673d20d3d37a12c61dd",
"c8d7332377d4bf43c232bc7afc3d7e3aacf13523d1c8488f68f530e58e6cfd88",
"3c21a6b7e3810ca10efac45446cd2b7ef0c9848ac589be7375b61ea5aabbbea4",
"5a25c2b70e2194e05a6208c99343ebe0fad970dd19f3f9cca88aaf77ab9e4658",
"031e3c08ebdcafccf6dc5d7ff1161cd5314424d0a943d2c22a5a2109286e332d",
"4992d16008aa3050b3e2e4aab67e488eb338850ff1c348367ae3d089d8d67a52",
"beb3e71b8da7da7917228f5ce8a88afdc45836c421b053dde24d367865326bd7"
],
"txDetails": {
"e559c2fd0f4e8aebe28fcb6dbb099fc6ee92d726d74fda28522f52bc1490a470": {
"hex": "01000000000102a4b8c14f271cfa77d5ecaed9c3026472a55ea6bca119e2ff7b04975326f5974001000000171600147edbcdda98080eeb6e8a63c63da135498295c3cdffffffffabcdf96b8ba187c24d70f98a2edfbf100821506212637f28b30a08efa970a4eb0100000017160014df7d60680e984aae4052e24bce8f17e4bfdcc532ffffffff0292fe1e00000000001976a914abba3808b854c70b63ff038fcddfbafcb707713988ac13e796110100000017a914c9e67d2b78a38857c786ea9a2fc3e64cb6e775648702483045022100a6910d3a3b64545a44e097a3739b1206095602fa796afc51f81b249d1293ad0a02206cdae51853b59ca52003f4e54ea8ae418b6b4d036cbe1fdd78677efe8eddb318012102b45e239d96f8504ae45a32af7c80f6164f7b9658166e318521ee822192fee3ef0247304402202684a6f59ee255f3f5e9a9209a735bf2aaa818d47add7c3f7a5590623bd2211c0220452bf2fb8d0dc0380862988f0f098c21e861004e02da7bd1fc6bea4e7f33d2dc012103f308867fda821467f77d372791644225174ae16daba86e55754c150a8d5aa40d00000000",
"txid": "e559c2fd0f4e8aebe28fcb6dbb099fc6ee92d726d74fda28522f52bc1490a470",
"blocktime": 1528788394,
"time": 1528788394,
"locktime": 0,
"vin": [
{
"txid": "4097f5265397047bffe219a1bca65ea5726402c3d9aeecd577fa1c274fc1b8a4",
"vout": 1,
"sequence": 4294967295,
"scriptSig": {
"hex": "1600147edbcdda98080eeb6e8a63c63da135498295c3cd"
}
},
{
"txid": "eba470a9ef080ab3287f63126250210810bfdf2e8af9704dc287a18b6bf9cdab",
"vout": 1,
"sequence": 4294967295,
"scriptSig": {
"hex": "160014df7d60680e984aae4052e24bce8f17e4bfdcc532"
}
}
],
"vout": [
{
"value": 0.02031250,
"n": 0,
"scriptPubKey": {
"hex": "76a914abba3808b854c70b63ff038fcddfbafcb707713988ac"
}
},
{
"value": 45.90069523,
"n": 1,
"scriptPubKey": {
"hex": "a914c9e67d2b78a38857c786ea9a2fc3e64cb6e7756487"
}
}
]
},
"5bef621ad6d0970939ae36270a3228d3c315f8008fb04eebffab5f7a3589d114": {
"hex": "01000000025b0551bd0fffcf55881e285e15b364ab9a831d2494d2eb7a163a4bbd6f551151000000006b483045022100dff500e8c060a9c8810483d4ada8f91c0b844e92778cc762300040870109c0be02207029fa781ec37ddeb0ffbfa7160e625afdd126f30ec11fb9bc25f4d2164933bb0121023c6017ab9f471a69157180c5e30b9aef2ff73ea2a1a774c53a975e2557536314ffffffffd49a58913818610b0aa065d4f32995863d216c44040a49d454f6b7eeb65c9adc010000006b483045022100dce24b819b70f920d0bb60fa1241fa14f2500412a60aceeaae2610e1593b5e3c022041fdc5a02dc26af043bea27713f1245340b98bd47aa283e23b96ecc4aae157a4012102d18a88bcf5f65d937de7d9bc24d2f492a55216087262bf4683d0055dd0521a56feffffff02da869800000000001976a914b4f1349ec3e7c751c6720e2c0783e3449e21e36888ac80fe210a000000001976a914b4f1349ec3e7c751c6720e2c0783e3449e21e36888ac00000000",
"txid": "5bef621ad6d0970939ae36270a3228d3c315f8008fb04eebffab5f7a3589d114",
"blocktime": 1528788394,
"time": 1528788394,
"locktime": 0,
"vin": [
{
"txid": "5111556fbd4b3a167aebd294241d839aab64b3155e281e8855cfff0fbd51055b",
"vout": 0,
"sequence": 4294967295,
"scriptSig": {
"hex": "483045022100dff500e8c060a9c8810483d4ada8f91c0b844e92778cc762300040870109c0be02207029fa781ec37ddeb0ffbfa7160e625afdd126f30ec11fb9bc25f4d2164933bb0121023c6017ab9f471a69157180c5e30b9aef2ff73ea2a1a774c53a975e2557536314"
}
},
{
"txid": "dc9a5cb6eeb7f654d4490a04446c213d869529f3d465a00a0b61183891589ad4",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100dce24b819b70f920d0bb60fa1241fa14f2500412a60aceeaae2610e1593b5e3c022041fdc5a02dc26af043bea27713f1245340b98bd47aa283e23b96ecc4aae157a4012102d18a88bcf5f65d937de7d9bc24d2f492a55216087262bf4683d0055dd0521a56"
}
}
],
"vout": [
{
"value": 0.09995994,
"n": 0,
"scriptPubKey": {
"hex": "76a914b4f1349ec3e7c751c6720e2c0783e3449e21e36888ac"
}
},
{
"value": 1.7,
"n": 1,
"scriptPubKey": {
"hex": "76a914b4f1349ec3e7c751c6720e2c0783e3449e21e36888ac"
}
}
]
}
}
}

View File

@ -0,0 +1,111 @@
{
"blockHeight": 139521,
"blockHash": "000000000296ea05e13b5479f6c041de575eec90759f58f57d311a8918b0af17",
"blockTxs": [
"cfe2d2c5bd9929349a9d8f3d8f2423f4f0c9b408ed41b3002be5e7437a20aa7d",
"3f7ac6c55c0b383feb17715aef3cebf29182039fc42577d7c517b2fc04096942",
"3f296b929f6ee4f0ad3d6fce35873d6aeacbdf06aaf2abe384beb6e3f2a4dd03",
"5ef4f9b7e4c0240687c3a6e6a073e0fbc753645d231ca35435b95325778b7186",
"805b5ba055227b0f7dbbdef8e603632c4d25b93f0e87c59fc74cbe8ad8dbe806",
"392785b88f03c82492172827f30cbed4761de3098a0faaa740999b412ff15e46",
"13fafd7c8afc6fd2c860d342eaf0cfe0edd2b994bb836898c02830b2f688155e",
"26bc95fcc71380f0d66e437314c72999c0848cab81fe1f91c9c95bf15b74855c",
"7873d8d774f2aae72100620a21b38ea681b488b328802b6ec3271b1d727c6b73",
"23147585fd4ed3970118027ce9b2e190e264f26fbf5d8c9708a483cee6cada43",
"e079894b2545eca7184a2f0eaccf4b069242f18fa0721aedc8f66b73112a1e8f",
"b36284854fa1947844ecc5d62768be3e14cc44c430db87b1b90184364b30dbf4",
"1fd3ad5d0392cedf318600908270986c801cac161ef06f660591634cc2a29652",
"7a5b8944589b0cfba9c408b24b095648b0040a37fd769a9785982603bb7ca1f7",
"7da1811ec3f2c6381d89e59f40957d36c898ba1bb70b976e0b5490d3b9fa8952",
"dbcfa65bdfe758353305eaff11b300463018efb7fa8f17c6c6a98bb8dba6bcc9",
"c046821e5503770304359792c20c1ed3e71509a19a867acf1dae113bf52d2a6f",
"d3cea11e1a4937323cc94172f93a2e0edc0981a706f2d2c3315ace94b01b375a",
"6ef2a57e38dd891690c8f230b65f26247799b2421860e6cf8a1c7c8cfdedd96e",
"53834414d8a88afe4268b85f959e526a0c677ac6b7dedba9a796d1549852fd41",
"b761ebaccfb6d0eeaa5350ccafdf6a7633e59d6baadc932c6d78491cb08052a6"
],
"txDetails": {
"3f7ac6c55c0b383feb17715aef3cebf29182039fc42577d7c517b2fc04096942": {
"hex": "020000000109d37a59b7da8902b8822547c927e35554b16667ffd698daae985c58c71616a4010000006b483045022100f3ef92ae1c8442eff171bd2dbc69373db384c86617032917b3bb2c5cd892bb2702207485cf5f8e6aa9fe245f5708a5c6ec37580c1c35e54429c6b43b322678f54cad012102ba7dbd059cc4f03e9fa4b6007b407279a154a8fc2103241511df155a52b7ea58feffffff02a055e18e170000001976a914e2114cb0a8b5d6f1c3c720f314cbf79e14bb9cdd88ac8cb65df0440000001976a9141ed486862342afd134f96a6cee5ca105801375df88ac00210200",
"txid": "3f7ac6c55c0b383feb17715aef3cebf29182039fc42577d7c517b2fc04096942",
"blocktime": 1528713762,
"time": 1528713762,
"locktime": 139520,
"vin": [
{
"txid": "a41616c7585c98aeda98d6ff6766b15455e327c9472582b80289dab7597ad309",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "483045022100f3ef92ae1c8442eff171bd2dbc69373db384c86617032917b3bb2c5cd892bb2702207485cf5f8e6aa9fe245f5708a5c6ec37580c1c35e54429c6b43b322678f54cad012102ba7dbd059cc4f03e9fa4b6007b407279a154a8fc2103241511df155a52b7ea58"
}
}
],
"vout": [
{
"value": 1011.81380000,
"n": 0,
"scriptPubKey": {
"hex": "76a914e2114cb0a8b5d6f1c3c720f314cbf79e14bb9cdd88ac"
}
},
{
"value": 2960.90449548,
"n": 1,
"scriptPubKey": {
"hex": "76a9141ed486862342afd134f96a6cee5ca105801375df88ac"
}
}
]
},
"6ef2a57e38dd891690c8f230b65f26247799b2421860e6cf8a1c7c8cfdedd96e": {
"hex": "020000000327ee9a2a360c6304fda56fa029670a95db595f70ae185a6f76ff1de415e07a18000000006a473044022011e7aed7a1cf187a9b6ca294bb76e3576cadebce48b5b944ad8393a60e8aa485022000818546dc7ba47c625258223dcefd6e84dc3faa8d54c646bfc0f55c4506c8f00121023fe7680caadc7bf3f796936de04d77e1007dea53880621c01d7b34720345d4ecfeffffff1ae8beeed571f491410ed327a6821b683d8ae571aea56057634da7aa8ce1041f000000006b4830450221009277cfac065a076814e18613d89c7d85a6461cf5283f2a9cee7254ec83fce637022023cf7186be7714921fe24719450e65a204d803738a1cb9fe35f30753f0696b8b012102aff34da05a74891899aace72f2e650ec1c039bfc519c192e6c231a2b7fa05749feffffff6388454ad1e5718af92def6fe307e64e97c43324d30c322b31edf85088020dc9000000006a47304402204435602e00d22417ff489302758a246df5fbc05e9bc4d0025464556ae7f77e70022036e30d2d46937ee0fc0cdf9a63e7baf8351bd16454ec02311cac52655ac4c32801210395fbe30126fc97a2c8b1e29bc27028a5a6885e4a4116d13e2cbe32c9d71e7f03feffffff02ce177e09000000001976a91437617547a3e0ba0adeead7c8c33c03970341404088acd0f7aad1010000001976a914f0b3dff509993e0b7035ce997b52763ce501d67888ac00210200",
"txid": "6ef2a57e38dd891690c8f230b65f26247799b2421860e6cf8a1c7c8cfdedd96e",
"blocktime": 1528713762,
"time": 1528713762,
"locktime": 139520,
"vin": [
{
"txid": "187ae015e41dff766f5a18ae705f59db950a6729a06fa5fd04630c362a9aee27",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "473044022011e7aed7a1cf187a9b6ca294bb76e3576cadebce48b5b944ad8393a60e8aa485022000818546dc7ba47c625258223dcefd6e84dc3faa8d54c646bfc0f55c4506c8f00121023fe7680caadc7bf3f796936de04d77e1007dea53880621c01d7b34720345d4ec"
}
},
{
"txid": "1f04e18caaa74d635760a5ae71e58a3d681b82a627d30e4191f471d5eebee81a",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "4830450221009277cfac065a076814e18613d89c7d85a6461cf5283f2a9cee7254ec83fce637022023cf7186be7714921fe24719450e65a204d803738a1cb9fe35f30753f0696b8b012102aff34da05a74891899aace72f2e650ec1c039bfc519c192e6c231a2b7fa05749"
}
},
{
"txid": "c90d028850f8ed312b320cd32433c4974ee607e36fef2df98a71e5d14a458863",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "47304402204435602e00d22417ff489302758a246df5fbc05e9bc4d0025464556ae7f77e70022036e30d2d46937ee0fc0cdf9a63e7baf8351bd16454ec02311cac52655ac4c32801210395fbe30126fc97a2c8b1e29bc27028a5a6885e4a4116d13e2cbe32c9d71e7f03"
}
}
],
"vout": [
{
"value": 1.59258574,
"n": 0,
"scriptPubKey": {
"hex": "76a91437617547a3e0ba0adeead7c8c33c03970341404088ac"
}
},
{
"value": 78.12610000,
"n": 1,
"scriptPubKey": {
"hex": "76a914f0b3dff509993e0b7035ce997b52763ce501d67888ac"
}
}
]
}
}
}

View File

@ -0,0 +1,38 @@
{
"blockHeight": 2870000,
"blockHash": "0xeccd6b0031015a19cb7d4e10f28590ba65a6a54ad1baa322b50fe5ad16903895",
"blockTxs": [
"0x17ee235fc0359155b25419e0e4c65d9c500df6e71e8288d6ef020d04cc2f2cb3",
"0xe6b168d6bb3d8ed78e03dbf828b6bfd1fb613f6e129cba624964984553724c5d",
"0xe14e6628e866555091fda44f934dfc6bfbbcd8a81e1281bb682eaf293d248be8",
"0xcffe6d5f4022822ba5f1e64f5b413c7f91c3a48c3739429d72065ec1a8b82e91",
"0x1d261bf23077b7e68ad9300ce9d88e7f4f95075fe98ea76b70534acaf5cf891b",
"0x92f73c26c99ea3b15535829cf686541a1318623baf8c49fe2bf0168bf3c3e272",
"0x392394bb4e4463c9ed59182797b5dbf23aa41c6f6edd7f4b5025d82acf43c357",
"0x3dd838b8d5d9b7155c960f8a138a9c499b87d84b7c9d9a513d8022b1991f959c",
"0x4889b4d1ad3652f6c410a6b6c05a459b86e68363d795f38ec13d5dc6d595d977",
"0xd1e1ff22a80135d904d119252c5d56a8c5b07af9d26de79fd3dda8aeffccf9ae",
"0xd1c3b7835c6032eb9eb07fdce90944f26d470b1c027adf2951b329a783e8e628",
"0x7f0d140329941f120b5b3fc751e30adeb87b2aebbfce5adcd0216604a34b6cc0"
],
"txDetails": {
"0xe6b168d6bb3d8ed78e03dbf828b6bfd1fb613f6e129cba624964984553724c5d": {
"hex": "7b226e6f6e6365223a2230783239666165222c226761735072696365223a223078313261303566323030222c22676173223a2230786462626130222c22746f223a22307836383262373930336131313039386366373730633761656634616130326138356233663336303161222c2276616c7565223a22307830222c22696e707574223a223078663032356361616630303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030323235222c2268617368223a22307865366231363864366262336438656437386530336462663832386236626664316662363133663665313239636261363234393634393834353533373234633564222c22626c6f636b4e756d626572223a223078326263616630222c2266726f6d223a22307864616363396336313735346130633436313666633533323364633934366538396562323732333032222c227472616e73616374696f6e496e646578223a22307831222c2276223a2230783162222c2272223a22307831626434306133313132326330333931386466366431363664373430613661336132326630386132353933346365623136383863363239373736363163383063222c2273223a22307836303766626331356331663739393561343235386635613962636363363362303430333632643139393164356566653133363163353632323265346361383966227d",
"txid": "0xe6b168d6bb3d8ed78e03dbf828b6bfd1fb613f6e129cba624964984553724c5d",
"blocktime": 1521515026,
"time": 1521515026,
"vin": [
{
"addresses": ["0xdacc9c61754a0c4616fc5323dc946e89eb272302"]
}
],
"vout": [
{
"scriptPubKey": {
"addresses": ["0x682b7903a11098cf770c7aef4aa02a85b3f3601a"]
}
}
]
}
}
}

View File

@ -0,0 +1,89 @@
{
"blockHeight": 251102,
"blockHash": "001335906f981bbf0633e124e2fa8afef3d882e34a0306a4e0c55162e57e673d",
"blockTxs": [
"f02aa1c4c86e1d0cef6ccbbc48b2b7b38355bc3612d8f77dd58d04be1ec6ba19",
"a9f7cc34d7e272d2d9fb68cfa1c1941e338f377e6e426ae2fea1c12616d89c63",
"83f3db1d129a77bee9c6cf32cbc12d959cd0af8c8d734c2611db4bfddfe99202"
],
"txDetails": {
"a9f7cc34d7e272d2d9fb68cfa1c1941e338f377e6e426ae2fea1c12616d89c63": {
"hex": "030000807082c40301601ade5f535f62f3da01e0c88b16beb916877fa0fa43299a9e2398b813d0a119020000006a4730440220770472192407cfc5c01e331442ac579a68e445a7ccb0fe8a481161519555794a02207b00b4c01af416a4972c2fd2fba8d58a6467da545400469ab57e9207a0ee3ca201210201d494a45f36f545443bafd1a9050b02f448dd236bb4ce2602f83978980b98f2feffffff02ea5e2c1c000000001976a9144ef2de10b304381a9404ccbe12f83395e7860bbd88ac00a3e1110000000017a9146a8eecfe3a7949a4a8c68754accaea75ab32cd9e8794d40300f1d4030000",
"txid": "a9f7cc34d7e272d2d9fb68cfa1c1941e338f377e6e426ae2fea1c12616d89c63",
"blocktime": 1528781777,
"time": 1528781777,
"locktime": 251028,
"vin": [
{
"txid": "19a1d013b898239e9a2943faa07f8716b9be168bc8e001daf3625f535fde1a60",
"vout": 2,
"sequence": 4294967294,
"scriptSig": {
"hex": "4730440220770472192407cfc5c01e331442ac579a68e445a7ccb0fe8a481161519555794a02207b00b4c01af416a4972c2fd2fba8d58a6467da545400469ab57e9207a0ee3ca201210201d494a45f36f545443bafd1a9050b02f448dd236bb4ce2602f83978980b98f2"
}
}
],
"vout": [
{
"value": 4.72669930,
"n": 0,
"scriptPubKey": {
"hex": "76a9144ef2de10b304381a9404ccbe12f83395e7860bbd88ac",
"addresses": ["tmGunyrqeeHBKX3Jm23zKLokRogrS51Qzqh"]
}
},
{
"value": 3.0,
"n": 1,
"scriptPubKey": {
"hex": "a9146a8eecfe3a7949a4a8c68754accaea75ab32cd9e87",
"addresses": ["t2GGEpYQUKiTsb9WYKD9AKNEriao84tVsr5"]
}
}
]
},
"83f3db1d129a77bee9c6cf32cbc12d959cd0af8c8d734c2611db4bfddfe99202": {
"hex": "030000807082c40302eac0139a677c07b6fcdddd205f4bf538d9cc9fb586565fe77440f93cf1b5ca9a010000006b4830450221009ad50b4f0da90a1876af6b43c029e55f1c8b8c44e94161a7f14c812adcebeaa902204b9df40096337eb43120408d4743693b17ea27fc0f660948a0a761264e67a6b00121036ec451bd1d3d39bb8d2d0264dd5a0ff817ae306ec7ce0c7c9b86be3f3dde8727feffffff6a1ed49e62634ab5a60b23ec73f9014ad1c9d3bd3bf023333c8eb311c802f298000000006b4830450221009008a10ebebf45f1a9aeb01a5b49a5de820a1a396ca1b900ea0420a1c2c49ea7022053fad044ff42792dcad16d084d67d7c4cc565458f78a14292fe5ef5e9f7a20bb012103448301b9253e6822ae05af64c61517fe8cf8b22590cc7d0b308b7f5cbce26db1feffffff0200a3e111000000001976a9149bc587e2cdd13b78e26f601f084ea0597b357f4d88ac3176a002000000001976a91414a88f1032c8ef1c6bd9177f62cdb260b5087b5488acd2d40300f1d4030000",
"txid": "83f3db1d129a77bee9c6cf32cbc12d959cd0af8c8d734c2611db4bfddfe99202",
"blocktime": 1528781777,
"time": 1528781777,
"locktime": 251090,
"vin": [
{
"txid": "9acab5f13cf94074e75f5686b59fccd938f54b5f20ddddfcb6077c679a13c0ea",
"vout": 1,
"sequence": 4294967294,
"scriptSig": {
"hex": "4830450221009ad50b4f0da90a1876af6b43c029e55f1c8b8c44e94161a7f14c812adcebeaa902204b9df40096337eb43120408d4743693b17ea27fc0f660948a0a761264e67a6b00121036ec451bd1d3d39bb8d2d0264dd5a0ff817ae306ec7ce0c7c9b86be3f3dde8727"
}
},
{
"txid": "98f202c811b38e3c3323f03bbdd3c9d14a01f973ec230ba6b54a63629ed41e6a",
"vout": 0,
"sequence": 4294967294,
"scriptSig": {
"hex": "4830450221009008a10ebebf45f1a9aeb01a5b49a5de820a1a396ca1b900ea0420a1c2c49ea7022053fad044ff42792dcad16d084d67d7c4cc565458f78a14292fe5ef5e9f7a20bb012103448301b9253e6822ae05af64c61517fe8cf8b22590cc7d0b308b7f5cbce26db1"
}
}
],
"vout": [
{
"value": 3.0,
"n": 0,
"scriptPubKey": {
"hex": "76a9149bc587e2cdd13b78e26f601f084ea0597b357f4d88ac",
"addresses": ["tmPuzhaxL3vzTqkyJ6wn48Q4ZfAo6PBvHKC"]
}
},
{
"value": 0.44070449,
"n": 1,
"scriptPubKey": {
"hex": "76a91414a88f1032c8ef1c6bd9177f62cdb260b5087b5488ac",
"addresses": ["tmBbamgVqVBTAsEzPmEymbczdoaQvE5qwaR"]
}
}
]
}
}
}

View File

@ -158,6 +158,7 @@ type BlockChainParser interface {
GetAddrIDFromAddress(address string) ([]byte, error)
// address to output script conversions
AddressToOutputScript(address string) ([]byte, error)
OutputScriptToAddresses(script []byte) ([]string, error)
// transactions
PackedTxidLen() int
PackTxid(txid string) ([]byte, error)

View File

@ -4,16 +4,17 @@ VERSION ?= devel
GITCOMMIT = $(shell cd /src && git describe --tags --always --dirty)
BUILDTIME = $(shell date --iso-8601=seconds)
LDFLAGS := -X blockbook/common.version=$(VERSION) -X blockbook/common.gitcommit=$(GITCOMMIT) -X blockbook/common.buildtime=$(BUILDTIME)
ARGS ?=
all: build tools
build: prepare-sources
cd $(GOPATH)/src/blockbook && go build -o $(CURDIR)/blockbook -ldflags="-s -w $(LDFLAGS)"
cd $(GOPATH)/src/blockbook && go build -o $(CURDIR)/blockbook -ldflags="-s -w $(LDFLAGS)" $(ARGS)
cp $(CURDIR)/blockbook /out/blockbook
chown $(PACKAGER) /out/blockbook
build-debug: prepare-sources
cd $(GOPATH)/src/blockbook && go build -o $(CURDIR)/blockbook -ldflags="$(LDFLAGS)"
cd $(GOPATH)/src/blockbook && go build -o $(CURDIR)/blockbook -ldflags="$(LDFLAGS)" $(ARGS)
cp $(CURDIR)/blockbook /out/blockbook
chown $(PACKAGER) /out/blockbook
@ -22,10 +23,10 @@ tools:
chown $(PACKAGER) /out/{ldb,sst_dump}
test: prepare-sources
cd $(GOPATH)/src/blockbook && go test -short ./...
cd $(GOPATH)/src/blockbook && go test -tags unittest ./... $(ARGS)
test-all: prepare-sources
cd $(GOPATH)/src/blockbook && go test ./...
cd $(GOPATH)/src/blockbook && go test -tags 'unittest integration' ./... $(ARGS)
prepare-sources:
@ [ -n "`ls /src 2> /dev/null`" ] || (echo "/src doesn't exist or is empty" 1>&2 && exit 1)

View File

@ -11,5 +11,3 @@ ADD build-deb.sh /build/build-deb.sh
ADD logrotate.sh /build/logrotate.sh
WORKDIR /build
CMD /build/build-deb.sh

View File

@ -8,6 +8,6 @@ mkdir cert && cp /src/server/testcert.* cert
export VERSION=$(dpkg-parsechangelog | sed -rne 's/^Version: ([0-9.]+)([-+~].+)?$/\1/p')
dpkg-buildpackage -us -uc
dpkg-buildpackage -us -uc $@
mv ../*.deb /out
chown $PACKAGER /out/*.deb

View File

@ -0,0 +1,28 @@
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $(basename $0) host" 1>&2
exit 1
fi
host=$1
# change dir to root of git repository
cd $(cd $(dirname $(readlink -f $0)) && git rev-parse --show-toplevel)
# get all testnet ports from configs/
testnet_ports=$(gawk 'match($0, /"rpcURL":\s+"(http|ws):\/\/[^:]+:([0-9]+)"/, a) {print a[2]}' configs/*_testnet*.json)
for port in $testnet_ports
do
ssh -nNT -L $port:localhost:$port blockbook-dev.corp &
pid=$!
echo "Started tunnel to ${host}:${port} (pid: ${pid})"
done
at_exit() {
pkill -P $$
}
trap at_exit EXIT
sleep inf

View File

@ -1,3 +1,5 @@
// +build unittest
package db
import (

View File

@ -1,3 +1,5 @@
// +build unittest
package server
import (