Merge branch 'params-registration' into tests

This commit is contained in:
Jakub Matys 2018-10-02 22:11:07 +02:00
commit e102c81577
27 changed files with 342 additions and 255 deletions

28
Gopkg.lock generated
View File

@ -61,12 +61,6 @@
revision = "1d4478f51bed434f1dadf96dcd9b43aabac66795"
version = "v1.7"
[[projects]]
branch = "master"
name = "github.com/erikdubbelboer/gspt"
packages = ["."]
revision = "e39e726e09cc23d1ccf13b36ce10dbdb4a4510e0"
[[projects]]
name = "github.com/ethereum/go-ethereum"
packages = [".","common","common/hexutil","common/math","core/types","crypto","crypto/secp256k1","crypto/sha3","ethclient","ethdb","log","metrics","p2p/netutil","params","rlp","rpc","trie"]
@ -103,18 +97,6 @@
packages = ["."]
revision = "553a641470496b2327abcac10b36396bd98e45c9"
[[projects]]
name = "github.com/gorilla/context"
packages = ["."]
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
version = "v1.1"
[[projects]]
name = "github.com/gorilla/mux"
packages = ["."]
revision = "53c1911da2b537f792e7cafcb446b05ffe33b996"
version = "v1.6.1"
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
@ -131,7 +113,7 @@
branch = "master"
name = "github.com/jakm/btcutil"
packages = [".","base58","bech32","chaincfg","txscript"]
revision = "a45c5a6a9cb32f0caecb14a4e5a8f82640be1f39"
revision = "c50a69d8979c23daad1728b3574c6f20691174f7"
[[projects]]
branch = "master"
@ -235,12 +217,6 @@
packages = ["websocket"]
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
[[projects]]
name = "gopkg.in/fatih/set.v0"
packages = ["."]
revision = "57907de300222151a123d29255ed17f5ed43fad3"
version = "v0.1.0"
[[projects]]
branch = "v2"
name = "gopkg.in/karalabe/cookiejar.v2"
@ -256,6 +232,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "98fb9a6252acd86d1c0a4b09a42e34673c2ccd6327caf49ed85bcee573601d95"
inputs-digest = "7cb7ad84fe0b30276bb7775d85c4f3281acddb12cb2e10ea4d80198981c9f80b"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -25,6 +25,23 @@ const (
RegTestPrefix = "bchreg:"
)
var (
MainNetParams chaincfg.Params
TestNetParams chaincfg.Params
RegtestParams chaincfg.Params
)
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = bchutil.MainnetMagic
TestNetParams = chaincfg.TestNet3Params
TestNetParams.Net = bchutil.TestnetMagic
RegtestParams = chaincfg.RegressionNetParams
RegtestParams.Net = bchutil.Regtestmagic
}
// BCashParser handle
type BCashParser struct {
*btc.BitcoinParser
@ -62,17 +79,26 @@ func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) (*BCashParser
// the regression test Bitcoin Cash network, the test Bitcoin Cash network and
// the simulation test Bitcoin Cash 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 {
err = chaincfg.Register(&RegtestParams)
}
if err != nil {
panic(err)
}
}
var params *chaincfg.Params
switch chain {
case "test":
params = &chaincfg.TestNet3Params
params.Net = bchutil.TestnetMagic
return &TestNetParams
case "regtest":
params = &chaincfg.RegressionNetParams
params.Net = bchutil.Regtestmagic
return &RegtestParams
default:
params = &chaincfg.MainNetParams
params.Net = bchutil.MainnetMagic
return &MainNetParams
}
return params

View File

@ -7,10 +7,19 @@ import (
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress(t *testing.T) {
mainParserCashAddr, mainParserLegacy, testParserCashAddr, _ := setupParsers(t)
tests := []struct {

View File

@ -42,6 +42,9 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser
// the regression test Bitcoin network, the test Bitcoin network and
// the simulation test Bitcoin network, in this order
func GetChainParams(chain string) *chaincfg.Params {
if !chaincfg.IsRegistered(&chaincfg.MainNetParams) {
chaincfg.RegisterBitcoinParams()
}
switch chain {
case "test":
return &chaincfg.TestNet3Params

View File

@ -6,10 +6,19 @@ import (
"blockbook/bchain"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress(t *testing.T) {
type args struct {
address string

View File

@ -23,7 +23,7 @@ var (
TestNetParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
@ -39,14 +39,6 @@ func initParams() {
// see https://github.com/satoshilabs/slips/blob/master/slip-0173.md
MainNetParams.Bech32HRPSegwit = "btg"
TestNetParams.Bech32HRPSegwit = "tbtg"
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
// BGoldParser handle
@ -63,8 +55,14 @@ func NewBGoldParser(params *chaincfg.Params, c *btc.Configuration) *BGoldParser
// the regression test Bitcoin Cash network, the test Bitcoin Cash network and
// the simulation test Bitcoin Cash network, in this order
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":

View File

@ -8,10 +8,19 @@ import (
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
type testBlock struct {
size int
time int64

View File

@ -19,7 +19,7 @@ var (
RegtestParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
@ -40,17 +40,6 @@ func initParams() {
// Address encoding magics
RegtestParams.PubKeyHashAddrID = []byte{140} // base58 prefix: y
RegtestParams.ScriptHashAddrID = []byte{19} // base58 prefix: 8 or 9
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err == nil {
err = chaincfg.Register(&RegtestParams)
}
if err != nil {
panic(err)
}
}
// DashParser handle
@ -67,8 +56,17 @@ func NewDashParser(params *chaincfg.Params, c *btc.Configuration) *DashParser {
// the regression test Dash network, the test Dash network and
// the simulation test Dash network, in this order
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err == nil {
err = chaincfg.Register(&RegtestParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":

View File

@ -18,16 +18,11 @@ var (
MainNetParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{30}
MainNetParams.ScriptHashAddrID = []byte{22}
err := chaincfg.Register(&MainNetParams)
if err != nil {
panic(err)
}
}
// DogecoinParser handle
@ -43,8 +38,11 @@ func NewDogecoinParser(params *chaincfg.Params, c *btc.Configuration) *DogecoinP
// GetChainParams contains network parameters for the main Dogecoin network,
// and the test Dogecoin network
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err != nil {
panic(err)
}
}
switch chain {
default:

View File

@ -10,11 +10,20 @@ import (
"fmt"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) {
type args struct {
address string

View File

@ -48,6 +48,7 @@ type EthereumRPC struct {
Mempool *bchain.NonUTXOMempool
bestHeaderMu sync.Mutex
bestHeader *ethtypes.Header
bestHeaderTime time.Time
chanNewBlock chan *ethtypes.Header
newBlockSubscription *rpc.ClientSubscription
chanNewTx chan ethcommon.Hash
@ -96,6 +97,7 @@ func NewEthereumRPC(config json.RawMessage, pushHandler func(bchain.Notification
// update best header to the new header
s.bestHeaderMu.Lock()
s.bestHeader = h
s.bestHeaderTime = time.Now()
s.bestHeaderMu.Unlock()
// notify blockbook
pushHandler(bchain.NotificationNewBlock)
@ -188,7 +190,7 @@ func (b *EthereumRPC) Initialize() error {
return nil
}
// subscribeNewBlocks subscribes to new blocks notification
// subscribe subscribes notification and tries to resubscribe in case of error
func (b *EthereumRPC) subscribe(f func() (*rpc.ClientSubscription, error)) error {
s, err := f()
if err != nil {
@ -281,6 +283,12 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
func (b *EthereumRPC) getBestHeader() (*ethtypes.Header, error) {
b.bestHeaderMu.Lock()
defer b.bestHeaderMu.Unlock()
// ETC does not have newBlocks subscription, bestHeader must be updated very often (each 1 second)
if b.isETC {
if b.bestHeaderTime.Add(1 * time.Second).Before(time.Now()) {
b.bestHeader = nil
}
}
if b.bestHeader == nil {
var err error
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
@ -289,6 +297,7 @@ func (b *EthereumRPC) getBestHeader() (*ethtypes.Header, error) {
if err != nil {
return nil, err
}
b.bestHeaderTime = time.Now()
}
return b.bestHeader, nil
}

View File

@ -18,7 +18,7 @@ var (
TestNetParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{48}
@ -30,14 +30,6 @@ func initParams() {
TestNetParams.PubKeyHashAddrID = []byte{111}
TestNetParams.ScriptHashAddrID = []byte{58}
TestNetParams.Bech32HRPSegwit = "tltc"
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
// LitecoinParser handle
@ -53,8 +45,17 @@ func NewLitecoinParser(params *chaincfg.Params, c *btc.Configuration) *LitecoinP
// GetChainParams contains network parameters for the main Litecoin network,
// and the test Litecoin network
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&chaincfg.MainNetParams) {
chaincfg.RegisterBitcoinParams()
}
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":

View File

@ -7,10 +7,19 @@ import (
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Testnet(t *testing.T) {
type args struct {
address string
@ -28,17 +37,29 @@ func Test_GetAddrDescFromAddress_Testnet(t *testing.T) {
wantErr: false,
},
{
name: "P2SH1",
name: "P2SH1-legacy",
args: args{address: "2MvGVySztevmycxrSmMRjJaVj2iJin7qpap"},
want: "a9142126232e3f47ae0f1246ec5f05fc400d83c86a0d87",
wantErr: false,
},
{
name: "P2SH2",
name: "P2SH2-legacy",
args: args{address: "2N9a2TNzWz1FEKGFxUdMEh62V83URdZ5QAZ"},
want: "a914b31049e7ee51501fe19e3e0cdb803dc84cf99f9e87",
wantErr: false,
},
{
name: "P2SH1",
args: args{address: "QPdG6Ts8g2q4m9cVPTTkPGwAB6kYgXB7Hc"},
want: "a9142126232e3f47ae0f1246ec5f05fc400d83c86a0d87",
wantErr: false,
},
{
name: "P2SH2",
args: args{address: "QcvnaPrm17JKTT216jPFmnTvGRvFX2fWzN"},
want: "a914b31049e7ee51501fe19e3e0cdb803dc84cf99f9e87",
wantErr: false,
},
}
parser := NewLitecoinParser(GetChainParams("test"), &btc.Configuration{})

View File

@ -26,7 +26,7 @@ var (
MonaTestParams monacoinCfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{50}
@ -48,14 +48,6 @@ func initParams() {
MonaTestParams.PubKeyHashAddrID = 111
MonaTestParams.ScriptHashAddrID = 117
MonaTestParams.Bech32HRPSegwit = "tmona"
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
// MonacoinParser handle
@ -65,14 +57,22 @@ type MonacoinParser struct {
// NewMonacoinParser returns new MonacoinParser instance
func NewMonacoinParser(params *chaincfg.Params, c *btc.Configuration) *MonacoinParser {
return &MonacoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
p := &MonacoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
return p
}
// GetChainParams contains network parameters for the main Monacoin network,
// and the test Monacoin network
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":
@ -82,17 +82,6 @@ func GetChainParams(chain string) *chaincfg.Params {
}
}
// GetMonaChainParams contains network parameters for the main Monacoin network,
// and the test Monacoin network
func GetMonaChainParams(chain string) *monacoinCfg.Params {
switch chain {
case "test":
return &MonaTestParams
default:
return &MonaMainParams
}
}
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address
func (p *MonacoinParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
return p.addressToOutputScript(address)
@ -123,3 +112,52 @@ func (p *MonacoinParser) addressToOutputScript(address string) ([]byte, error) {
return script, nil
}
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *MonacoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
return p.OutputScriptToAddressesFunc(addrDesc)
}
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
func (p *MonacoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
switch p.Params.Net {
case MainnetMagic:
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, &MonaMainParams)
if err != nil {
return nil, false, err
}
rv := make([]string, len(addresses))
for i, a := range addresses {
rv[i] = a.EncodeAddress()
}
var s bool
if sc != txscript.NonStandardTy && sc != txscript.NullDataTy {
s = true
} else if len(rv) == 0 {
or := btc.TryParseOPReturn(script)
if or != "" {
rv = []string{or}
}
}
return rv, s, nil
default:
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, &MonaTestParams)
if err != nil {
return nil, false, err
}
rv := make([]string, len(addresses))
for i, a := range addresses {
rv[i] = a.EncodeAddress()
}
var s bool
if sc != txscript.NonStandardTy && sc != txscript.NullDataTy {
s = true
} else if len(rv) == 0 {
or := btc.TryParseOPReturn(script)
if or != "" {
rv = []string{or}
}
}
return rv, s, nil
}
}

View File

@ -7,10 +7,19 @@ import (
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Testnet(t *testing.T) {
type args struct {
address string

View File

@ -18,16 +18,11 @@ var (
MainNetParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{52}
MainNetParams.ScriptHashAddrID = []byte{13}
err := chaincfg.Register(&MainNetParams)
if err != nil {
panic(err)
}
}
// NamecoinParser handle
@ -43,8 +38,11 @@ func NewNamecoinParser(params *chaincfg.Params, c *btc.Configuration) *NamecoinP
// GetChainParams contains network parameters for the main Namecoin network,
// and the test Namecoin network
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err != nil {
panic(err)
}
}
switch chain {
default:

View File

@ -8,11 +8,20 @@ import (
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) {
type args struct {
address string

View File

@ -18,7 +18,7 @@ var (
TestNetParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
MainNetParams.PubKeyHashAddrID = []byte{71}
@ -30,14 +30,6 @@ func initParams() {
TestNetParams.PubKeyHashAddrID = []byte{74}
TestNetParams.ScriptHashAddrID = []byte{196}
TestNetParams.Bech32HRPSegwit = "tvtc"
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
// VertcoinParser handle
@ -53,8 +45,14 @@ func NewVertcoinParser(params *chaincfg.Params, c *btc.Configuration) *VertcoinP
// GetChainParams contains network parameters for the main Vertcoin network,
// and the test Vertcoin network
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
switch chain {
case "test":

View File

@ -7,10 +7,19 @@ import (
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) {
type args struct {
address string

View File

@ -17,9 +17,10 @@ const (
var (
MainNetParams chaincfg.Params
TestNetParams chaincfg.Params
RegtestParams chaincfg.Params
)
func initParams() {
func init() {
MainNetParams = chaincfg.MainNetParams
MainNetParams.Net = MainnetMagic
@ -36,13 +37,8 @@ func initParams() {
TestNetParams.PubKeyHashAddrID = []byte{0x1D, 0x25} // base58 prefix: tm
TestNetParams.ScriptHashAddrID = []byte{0x1C, 0xBA} // base58 prefix: t2
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
RegtestParams = chaincfg.RegressionNetParams
RegtestParams.Net = RegtestMagic
}
// ZCashParser handle
@ -63,16 +59,24 @@ func NewZCashParser(params *chaincfg.Params, c *btc.Configuration) *ZCashParser
// the regression test ZCash network, the test ZCash network and
// the simulation test ZCash network, in this order
func GetChainParams(chain string) *chaincfg.Params {
if MainNetParams.Name == "" {
initParams()
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err == nil {
err = chaincfg.Register(&RegtestParams)
}
if err != nil {
panic(err)
}
}
var params *chaincfg.Params
switch chain {
case "test":
return &TestNetParams
case "regtest":
params = &chaincfg.RegressionNetParams
params.Net = RegtestMagic
return &RegtestParams
default:
return &MainNetParams
}

View File

@ -8,8 +8,11 @@ import (
"bytes"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"github.com/jakm/btcutil/chaincfg"
)
var (
@ -91,6 +94,12 @@ func init() {
}
}
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func TestGetAddrDesc(t *testing.T) {
type args struct {
tx bchain.Tx

View File

@ -1,7 +1,7 @@
SHELL = /bin/bash
UPDATE_VENDOR ?= 1
VERSION ?= devel
GITCOMMIT = $(shell cd /src && git describe --tags --always --dirty)
GITCOMMIT = $(shell cd /src && git describe --always --dirty)
BUILDTIME = $(shell date --iso-8601=seconds)
LDFLAGS := -X blockbook/common.version=$(VERSION) -X blockbook/common.gitcommit=$(GITCOMMIT) -X blockbook/common.buildtime=$(BUILDTIME)
BLOCKBOOK_SRC := $(GOPATH)/src/blockbook

View File

@ -11,9 +11,10 @@ package=$1
coin=$2
shift 2
mkdir build
mkdir -p build
cp -r /src/build/templates build
cp -r /src/configs .
ln -s /src/ /go/src/blockbook
go run build/templates/generate.go $coin
# backend

View File

@ -42,20 +42,17 @@ type connectBlockStats struct {
// RocksDB handle
type RocksDB struct {
path string
db *gorocksdb.DB
wo *gorocksdb.WriteOptions
ro *gorocksdb.ReadOptions
cfh []*gorocksdb.ColumnFamilyHandle
chainParser bchain.BlockChainParser
is *common.InternalState
metrics *common.Metrics
cache *gorocksdb.Cache
maxOpenFiles int
cbs connectBlockStats
chanUpdateBalance chan updateBalanceData
chanUpdateBalanceResult chan error
updateBalancesMap map[string]*AddrBalance
path string
db *gorocksdb.DB
wo *gorocksdb.WriteOptions
ro *gorocksdb.ReadOptions
cfh []*gorocksdb.ColumnFamilyHandle
chainParser bchain.BlockChainParser
is *common.InternalState
metrics *common.Metrics
cache *gorocksdb.Cache
maxOpenFiles int
cbs connectBlockStats
}
const (
@ -93,20 +90,7 @@ func NewRocksDB(path string, cacheSize, maxOpenFiles int, parser bchain.BlockCha
db, cfh, err := openDB(path, c, maxOpenFiles)
wo := gorocksdb.NewDefaultWriteOptions()
ro := gorocksdb.NewDefaultReadOptions()
rdb := &RocksDB{
path: path,
db: db,
wo: wo,
ro: ro,
cfh: cfh,
chainParser: parser,
metrics: metrics,
cache: c,
maxOpenFiles: maxOpenFiles,
cbs: connectBlockStats{},
}
rdb.initUpdateBalancesWorker()
return rdb, nil
return &RocksDB{path, db, wo, ro, cfh, parser, nil, metrics, c, maxOpenFiles, connectBlockStats{}}, nil
}
func (d *RocksDB) closeDB() error {
@ -290,8 +274,6 @@ func (d *RocksDB) writeBlock(block *bchain.Block, op int) error {
txAddressesMap := make(map[string]*TxAddresses)
balances := make(map[string]*AddrBalance)
if err := d.processAddressesUTXO(block, addresses, txAddressesMap, balances); err != nil {
// reinitialize balanceWorker so that there are no left balances in the queue
d.initUpdateBalancesWorker()
return err
}
if err := d.storeAddresses(wb, block.Height, addresses); err != nil {
@ -380,80 +362,7 @@ func (d *RocksDB) GetAndResetConnectBlockStats() string {
return s
}
type updateBalanceData struct {
valueSat big.Int
strAddrDesc string
addrDesc bchain.AddressDescriptor
processed, output bool
}
func (d *RocksDB) initUpdateBalancesWorker() {
if d.chanUpdateBalance != nil {
close(d.chanUpdateBalance)
}
d.chanUpdateBalance = make(chan updateBalanceData, 16)
d.chanUpdateBalanceResult = make(chan error, 16)
go d.updateBalancesWorker()
}
// updateBalancesWorker is a single worker used to update balances in parallel to processAddressesUTXO
func (d *RocksDB) updateBalancesWorker() {
var err error
for bd := range d.chanUpdateBalance {
ab, e := d.updateBalancesMap[bd.strAddrDesc]
if !e {
ab, err = d.GetAddrDescBalance(bd.addrDesc)
if err != nil {
d.chanUpdateBalanceResult <- err
continue
}
if ab == nil {
ab = &AddrBalance{}
}
d.updateBalancesMap[bd.strAddrDesc] = ab
d.cbs.balancesMiss++
} else {
d.cbs.balancesHit++
}
// add number of trx in balance only once, address can be multiple times in tx
if !bd.processed {
ab.Txs++
}
if bd.output {
ab.BalanceSat.Add(&ab.BalanceSat, &bd.valueSat)
} else {
ab.BalanceSat.Sub(&ab.BalanceSat, &bd.valueSat)
if ab.BalanceSat.Sign() < 0 {
d.resetValueSatToZero(&ab.BalanceSat, bd.addrDesc, "balance")
}
ab.SentSat.Add(&ab.SentSat, &bd.valueSat)
}
d.chanUpdateBalanceResult <- nil
}
}
func (d *RocksDB) dispatchUpdateBalance(dispatchedBalances int, valueSat *big.Int, strAddrDesc string, addrDesc bchain.AddressDescriptor, processed, output bool) (int, error) {
loop:
for {
select {
// process as many results as possible
case err := <-d.chanUpdateBalanceResult:
if err != nil {
return 0, err
}
dispatchedBalances--
// send input to be processed
case d.chanUpdateBalance <- updateBalanceData{*valueSat, strAddrDesc, addrDesc, processed, output}:
dispatchedBalances++
break loop
}
}
return dispatchedBalances, nil
}
func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string][]outpoint, txAddressesMap map[string]*TxAddresses, balances map[string]*AddrBalance) error {
d.updateBalancesMap = balances
dispatchedBalances := 0
blockTxIDs := make([][]byte, len(block.Txs))
blockTxAddresses := make([]*TxAddresses, len(block.Txs))
// first process all outputs so that inputs can point to txs in this block
@ -495,10 +404,25 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
btxID: btxID,
index: int32(i),
})
dispatchedBalances, err = d.dispatchUpdateBalance(dispatchedBalances, &output.ValueSat, strAddrDesc, addrDesc, processed, true)
if err != nil {
return err
ab, e := balances[strAddrDesc]
if !e {
ab, err = d.GetAddrDescBalance(addrDesc)
if err != nil {
return err
}
if ab == nil {
ab = &AddrBalance{}
}
balances[strAddrDesc] = ab
d.cbs.balancesMiss++
} else {
d.cbs.balancesHit++
}
// add number of trx in balance only once, address can be multiple times in tx
if !processed {
ab.Txs++
}
ab.BalanceSat.Add(&ab.BalanceSat, &output.ValueSat)
}
}
// process inputs
@ -564,16 +488,29 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
btxID: spendingTxid,
index: ^int32(i),
})
dispatchedBalances, err = d.dispatchUpdateBalance(dispatchedBalances, &ot.ValueSat, strAddrDesc, ot.AddrDesc, processed, false)
if err != nil {
return err
ab, e := balances[strAddrDesc]
if !e {
ab, err = d.GetAddrDescBalance(ot.AddrDesc)
if err != nil {
return err
}
if ab == nil {
ab = &AddrBalance{}
}
balances[strAddrDesc] = ab
d.cbs.balancesMiss++
} else {
d.cbs.balancesHit++
}
}
}
for i := 0; i < dispatchedBalances; i++ {
err := <-d.chanUpdateBalanceResult
if err != nil {
return err
// add number of trx in balance only once, address can be multiple times in tx
if !processed {
ab.Txs++
}
ab.BalanceSat.Sub(&ab.BalanceSat, &ot.ValueSat)
if ab.BalanceSat.Sign() < 0 {
d.resetValueSatToZero(&ab.BalanceSat, ot.AddrDesc, "balance")
}
ab.SentSat.Add(&ab.SentSat, &ot.ValueSat)
}
}
return nil

View File

@ -18,6 +18,7 @@ import (
"testing"
vlq "github.com/bsm/go-vlq"
"github.com/jakm/btcutil/chaincfg"
"github.com/juju/errors"
)
@ -25,6 +26,12 @@ import (
// for number n, the packing is: 2*n if n>=0 else 2*(-n)-1
// takes only 1 byte if abs(n)<127
func TestMain(m *testing.M) {
c := m.Run()
chaincfg.ResetParams()
os.Exit(c)
}
func bitcoinTestnetParser() *btc.BitcoinParser {
return btc.NewBitcoinParser(
btc.GetChainParams("test"),

View File

@ -8,16 +8,18 @@
<table class="table table-striped data-table table-hover">
<thead>
<tr>
<th style="width: 20%;">Height</th>
<th style="width: 10%;">Height</th>
<th style="width: 48%;">Hash</th>
<th>Timestamp</span></th>
<th class="text-right" style="width: 20%;">Transactions</th>
<th class="text-right" style="width: 20%;">Size</th>
<th class="text-right" style="width: 10%;">Transactions</th>
<th class="text-right" style="width: 10%;">Size</th>
</tr>
</thead>
<tbody>
{{- range $b := $blocks.Blocks -}}
<tr>
<td><a href="/block/{{$b.Height}}">{{$b.Height}}</a></td>
<td class="ellipsis">{{$b.Hash}}</td>
<td>{{formatUnixTime $b.Time}}</td>
<td class="text-right">{{$b.Txs}}</td>
<td class="text-right">{{$b.Size}}</td>

View File

@ -1,11 +1,11 @@
{
"bcash": {
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",
"EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"]
"EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"]
},
"bcash_testnet": {
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",
"EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"]
"EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"]
},
"bitcoin": {
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",