diff --git a/.gitignore b/.gitignore index 23e1078ccc..98fe00b344 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ debug* docker/blockbook build/pkg-defs build/blockbook +build/blockchaincfg.json build/ldb build/sst_dump build/*.deb diff --git a/Makefile b/Makefile index 7a32acf591..5cc8c0ebb3 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ BIN_IMAGE = blockbook-build DEB_IMAGE = blockbook-build-deb PACKAGER = $(shell id -u):$(shell id -g) NO_CACHE = false -UPDATE_VENDOR = 1 ARGS ?= TARGETS=$(subst .json,, $(shell ls configs/coins)) @@ -10,28 +9,28 @@ TARGETS=$(subst .json,, $(shell ls configs/coins)) .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 ARGS="$(ARGS)" + docker run -t --rm -e PACKAGER=$(PACKAGER) -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 ARGS="$(ARGS)" + docker run -t --rm -e PACKAGER=$(PACKAGER) -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" --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)" + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)" test-integration: .bin-image - docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)" + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)" test-all: .bin-image - docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)" + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)" deb-backend-%: .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 backend $* $(ARGS) + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS) deb-blockbook-%: .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 blockbook $* $(ARGS) + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS) deb-%: .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 all $* $(ARGS) + docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS) deb-blockbook-all: clean-deb $(addprefix deb-blockbook-, $(TARGETS)) diff --git a/api/types.go b/api/types.go index f674382393..38f0fd8740 100644 --- a/api/types.go +++ b/api/types.go @@ -196,8 +196,7 @@ type Tx struct { FeesSat *Amount `json:"fees,omitempty"` Hex string `json:"hex,omitempty"` Rbf bool `json:"rbf,omitempty"` - CoinSpecificData interface{} `json:"-"` - CoinSpecificJSON json.RawMessage `json:"-"` + CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"` TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"` EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"` } @@ -424,18 +423,19 @@ type BlockbookInfo struct { // BackendInfo is used to get information about blockchain type BackendInfo struct { - BackendError string `json:"error,omitempty"` - Chain string `json:"chain,omitempty"` - Blocks int `json:"blocks,omitempty"` - Headers int `json:"headers,omitempty"` - BestBlockHash string `json:"bestBlockHash,omitempty"` - Difficulty string `json:"difficulty,omitempty"` - SizeOnDisk int64 `json:"sizeOnDisk,omitempty"` - Version string `json:"version,omitempty"` - Subversion string `json:"subversion,omitempty"` - ProtocolVersion string `json:"protocolVersion,omitempty"` - Timeoffset float64 `json:"timeOffset,omitempty"` - Warnings string `json:"warnings,omitempty"` + BackendError string `json:"error,omitempty"` + Chain string `json:"chain,omitempty"` + Blocks int `json:"blocks,omitempty"` + Headers int `json:"headers,omitempty"` + BestBlockHash string `json:"bestBlockHash,omitempty"` + Difficulty string `json:"difficulty,omitempty"` + SizeOnDisk int64 `json:"sizeOnDisk,omitempty"` + Version string `json:"version,omitempty"` + Subversion string `json:"subversion,omitempty"` + ProtocolVersion string `json:"protocolVersion,omitempty"` + Timeoffset float64 `json:"timeOffset,omitempty"` + Warnings string `json:"warnings,omitempty"` + Consensus interface{} `json:"consensus,omitempty"` } // SystemInfo contains information about the running blockbook and backend instance diff --git a/api/worker.go b/api/worker.go index 39941e0aa7..87a14b5639 100644 --- a/api/worker.go +++ b/api/worker.go @@ -274,7 +274,8 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe // for now do not return size, we would have to compute vsize of segwit transactions // size:=len(bchainTx.Hex) / 2 var sj json.RawMessage - if specificJSON { + // return CoinSpecificData for all mempool transactions or if requested + if specificJSON || bchainTx.Confirmations == 0 { sj, err = w.chain.GetTransactionSpecific(bchainTx) if err != nil { return nil, err @@ -299,14 +300,140 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe Rbf: rbf, Vin: vins, Vout: vouts, - CoinSpecificData: bchainTx.CoinSpecificData, - CoinSpecificJSON: sj, + CoinSpecificData: sj, TokenTransfers: tokens, EthereumSpecific: ethSpecific, } return r, nil } +// GetTransactionFromMempoolTx converts bchain.MempoolTx to Tx, with limited amount of data +// it is not doing any request to backend or to db +func (w *Worker) GetTransactionFromMempoolTx(mempoolTx *bchain.MempoolTx) (*Tx, error) { + var err error + var valInSat, valOutSat, feesSat big.Int + var pValInSat *big.Int + var tokens []TokenTransfer + var ethSpecific *EthereumSpecific + vins := make([]Vin, len(mempoolTx.Vin)) + rbf := false + for i := range mempoolTx.Vin { + bchainVin := &mempoolTx.Vin[i] + vin := &vins[i] + vin.Txid = bchainVin.Txid + vin.N = i + vin.Vout = bchainVin.Vout + vin.Sequence = int64(bchainVin.Sequence) + // detect explicit Replace-by-Fee transactions as defined by BIP125 + if bchainVin.Sequence < 0xffffffff-1 { + rbf = true + } + vin.Hex = bchainVin.ScriptSig.Hex + vin.Coinbase = bchainVin.Coinbase + if w.chainType == bchain.ChainBitcoinType { + // bchainVin.Txid=="" is coinbase transaction + if bchainVin.Txid != "" { + vin.ValueSat = (*Amount)(&bchainVin.ValueSat) + vin.AddrDesc = bchainVin.AddrDesc + vin.Addresses, vin.IsAddress, _ = w.chainParser.GetAddressesFromAddrDesc(vin.AddrDesc) + if vin.ValueSat != nil { + valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat)) + } + } + } else if w.chainType == bchain.ChainEthereumType { + if len(bchainVin.Addresses) > 0 { + vin.AddrDesc, err = w.chainParser.GetAddrDescFromAddress(bchainVin.Addresses[0]) + if err != nil { + glog.Errorf("GetAddrDescFromAddress error %v, tx %v, bchainVin %v", err, mempoolTx.Txid, bchainVin) + } + vin.Addresses = bchainVin.Addresses + vin.IsAddress = true + } + } + } + vouts := make([]Vout, len(mempoolTx.Vout)) + for i := range mempoolTx.Vout { + bchainVout := &mempoolTx.Vout[i] + vout := &vouts[i] + vout.N = i + vout.ValueSat = (*Amount)(&bchainVout.ValueSat) + valOutSat.Add(&valOutSat, &bchainVout.ValueSat) + vout.Hex = bchainVout.ScriptPubKey.Hex + vout.AddrDesc, vout.Addresses, vout.IsAddress, err = w.getAddressesFromVout(bchainVout) + if err != nil { + glog.V(2).Infof("getAddressesFromVout error %v, %v, output %v", err, mempoolTx.Txid, bchainVout.N) + } + } + if w.chainType == bchain.ChainBitcoinType { + // for coinbase transactions valIn is 0 + feesSat.Sub(&valInSat, &valOutSat) + if feesSat.Sign() == -1 { + feesSat.SetUint64(0) + } + pValInSat = &valInSat + } else if w.chainType == bchain.ChainEthereumType { + if len(mempoolTx.Vout) > 0 { + valOutSat = mempoolTx.Vout[0].ValueSat + } + tokens = w.getTokensFromErc20(mempoolTx.Erc20) + ethTxData := eth.GetEthereumTxDataFromSpecificData(mempoolTx.CoinSpecificData) + ethSpecific = &EthereumSpecific{ + GasLimit: ethTxData.GasLimit, + GasPrice: (*Amount)(ethTxData.GasPrice), + GasUsed: ethTxData.GasUsed, + Nonce: ethTxData.Nonce, + Status: ethTxData.Status, + Data: ethTxData.Data, + } + } + r := &Tx{ + Blocktime: mempoolTx.Blocktime, + FeesSat: (*Amount)(&feesSat), + Locktime: mempoolTx.LockTime, + Txid: mempoolTx.Txid, + ValueInSat: (*Amount)(pValInSat), + ValueOutSat: (*Amount)(&valOutSat), + Version: mempoolTx.Version, + Hex: mempoolTx.Hex, + Rbf: rbf, + Vin: vins, + Vout: vouts, + TokenTransfers: tokens, + EthereumSpecific: ethSpecific, + } + return r, nil +} + +func (w *Worker) getTokensFromErc20(erc20 []bchain.Erc20Transfer) []TokenTransfer { + tokens := make([]TokenTransfer, len(erc20)) + for i := range erc20 { + e := &erc20[i] + cd, err := w.chainParser.GetAddrDescFromAddress(e.Contract) + if err != nil { + glog.Errorf("GetAddrDescFromAddress error %v, contract %v", err, e.Contract) + continue + } + erc20c, err := w.chain.EthereumTypeGetErc20ContractInfo(cd) + if err != nil { + glog.Errorf("GetErc20ContractInfo error %v, contract %v", err, e.Contract) + } + if erc20c == nil { + erc20c = &bchain.Erc20Contract{Name: e.Contract} + } + tokens[i] = TokenTransfer{ + Type: ERC20TokenType, + Token: e.Contract, + From: e.From, + To: e.To, + Decimals: erc20c.Decimals, + Value: (*Amount)(&e.Tokens), + Name: erc20c.Name, + Symbol: erc20c.Symbol, + } + } + return tokens +} + // GetTransactionFromMempoolTx converts bchain.MempoolTx to Tx, with limited amount of data // it is not doing any request to backend or to db func (w *Worker) GetTransactionFromMempoolTx(mempoolTx *bchain.MempoolTx) (*Tx, error) { @@ -758,7 +885,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail if ta == nil { glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses") // as fallback, get tx from backend - tx, err = w.GetTransaction(txid, false, true) + tx, err = w.GetTransaction(txid, false, false) if err != nil { return nil, errors.Annotatef(err, "GetTransaction %v", txid) } @@ -777,7 +904,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail tx = w.txFromTxAddress(txid, ta, blockInfo, bestheight) } } else { - tx, err = w.GetTransaction(txid, false, true) + tx, err = w.GetTransaction(txid, false, false) if err != nil { return nil, errors.Annotatef(err, "GetTransaction %v", txid) } @@ -866,7 +993,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc) } for _, txid := range txm { - tx, err := w.GetTransaction(txid, false, false) + tx, err := w.GetTransaction(txid, false, true) // mempool transaction may fail if err != nil || tx == nil { glog.Warning("GetTransaction in mempool: ", err) @@ -1777,6 +1904,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) { Timeoffset: ci.Timeoffset, Version: ci.Version, Warnings: ci.Warnings, + Consensus: ci.Consensus, } glog.Info("GetSystemInfo finished in ", time.Since(start)) return &SystemInfo{blockbookInfo, backendInfo}, nil diff --git a/api/xpub.go b/api/xpub.go index 8b1cdc584a..843249fa52 100644 --- a/api/xpub.go +++ b/api/xpub.go @@ -416,7 +416,7 @@ func (w *Worker) GetXpubAddress(xpub string, page int, txsOnPage int, option Acc // the same tx can have multiple addresses from the same xpub, get it from backend it only once tx, foundTx := txmMap[txid.txid] if !foundTx { - tx, err = w.GetTransaction(txid.txid, false, false) + tx, err = w.GetTransaction(txid.txid, false, true) // mempool transaction may fail if err != nil || tx == nil { glog.Warning("GetTransaction in mempool: ", err) diff --git a/bchain/coins/eth/ethparser.go b/bchain/coins/eth/ethparser.go index 8a48058cbc..98e0f6a7eb 100644 --- a/bchain/coins/eth/ethparser.go +++ b/bchain/coins/eth/ethparser.go @@ -311,8 +311,14 @@ func (p *EthereumParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ( if pt.Receipt.GasUsed, err = hexDecodeBig(r.Receipt.GasUsed); err != nil { return nil, errors.Annotatef(err, "GasUsed %v", r.Receipt.GasUsed) } - if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil { - return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status) + if r.Receipt.Status != "" { + if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil { + return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status) + } + } else { + // unknown status, use 'U' as status bytes + // there is a potential for conflict with value 0x55 but this is not used by any chain at this moment + pt.Receipt.Status = []byte{'U'} } ptLogs := make([]*ProtoCompleteTransaction_ReceiptType_LogType, len(r.Receipt.Logs)) for i, l := range r.Receipt.Logs { @@ -379,9 +385,14 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { Topics: topics, } } + status := "" + // handle a special value []byte{'U'} as unknown state + if len(pt.Receipt.Status) != 1 || pt.Receipt.Status[0] != 'U' { + status = hexEncodeBig(pt.Receipt.Status) + } rr = &rpcReceipt{ GasUsed: hexEncodeBig(pt.Receipt.GasUsed), - Status: hexEncodeBig(pt.Receipt.Status), + Status: status, Logs: logs, } } diff --git a/bchain/coins/eth/ethparser_test.go b/bchain/coins/eth/ethparser_test.go index cad6f34936..3d82c28c4f 100644 --- a/bchain/coins/eth/ethparser_test.go +++ b/bchain/coins/eth/ethparser_test.go @@ -68,7 +68,7 @@ func TestEthParser_GetAddrDescFromAddress(t *testing.T) { } } -var testTx1, testTx2 bchain.Tx +var testTx1, testTx2, testTx1Failed, testTx1NoStatus bchain.Tx func init() { @@ -156,6 +156,83 @@ func init() { }, }, } + + testTx1Failed = bchain.Tx{ + Blocktime: 1534858022, + Time: 1534858022, + Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b", + Vin: []bchain.Vin{ + { + Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"}, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(1999622000000000000), + ScriptPubKey: bchain.ScriptPubKey{ + Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"}, + }, + }, + }, + CoinSpecificData: completeTransaction{ + Tx: &rpcTransaction{ + AccountNonce: "0xb26c", + GasPrice: "0x430e23400", + GasLimit: "0x5208", + To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f", + Value: "0x1bc0159d530e6000", + Payload: "0x", + Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b", + BlockNumber: "0x41eee8", + From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97", + TransactionIndex: "0xa", + }, + Receipt: &rpcReceipt{ + GasUsed: "0x5208", + Status: "0x0", + Logs: []*rpcLog{}, + }, + }, + } + + testTx1NoStatus = bchain.Tx{ + Blocktime: 1534858022, + Time: 1534858022, + Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b", + Vin: []bchain.Vin{ + { + Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"}, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(1999622000000000000), + ScriptPubKey: bchain.ScriptPubKey{ + Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"}, + }, + }, + }, + CoinSpecificData: completeTransaction{ + Tx: &rpcTransaction{ + AccountNonce: "0xb26c", + GasPrice: "0x430e23400", + GasLimit: "0x5208", + To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f", + Value: "0x1bc0159d530e6000", + Payload: "0x", + Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b", + BlockNumber: "0x41eee8", + From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97", + TransactionIndex: "0xa", + }, + Receipt: &rpcReceipt{ + GasUsed: "0x5208", + Status: "", + Logs: []*rpcLog{}, + }, + }, + } + } func TestEthereumParser_PackTx(t *testing.T) { @@ -189,6 +266,24 @@ func TestEthereumParser_PackTx(t *testing.T) { }, want: dbtestdata.EthTx2Packed, }, + { + name: "3", + args: args{ + tx: &testTx1Failed, + height: 4321000, + blockTime: 1534858022, + }, + want: dbtestdata.EthTx1FailedPacked, + }, + { + name: "4", + args: args{ + tx: &testTx1NoStatus, + height: 4321000, + blockTime: 1534858022, + }, + want: dbtestdata.EthTx1NoStatusPacked, + }, } p := NewEthereumParser(1) for _, tt := range tests { @@ -230,6 +325,18 @@ func TestEthereumParser_UnpackTx(t *testing.T) { want: &testTx2, want1: 4321000, }, + { + name: "3", + args: args{hex: dbtestdata.EthTx1FailedPacked}, + want: &testTx1Failed, + want1: 4321000, + }, + { + name: "4", + args: args{hex: dbtestdata.EthTx1NoStatusPacked}, + want: &testTx1NoStatus, + want1: 4321000, + }, } p := NewEthereumParser(1) for _, tt := range tests { diff --git a/bchain/coins/eth/tx.pb.go b/bchain/coins/eth/ethtx.pb.go similarity index 73% rename from bchain/coins/eth/tx.pb.go rename to bchain/coins/eth/ethtx.pb.go index ff10c6cbd0..6023a259b5 100644 --- a/bchain/coins/eth/tx.pb.go +++ b/bchain/coins/eth/ethtx.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: tx.proto +// source: bchain/coins/eth/ethtx.proto /* Package eth is a generated protocol buffer package. It is generated from these files: - tx.proto + bchain/coins/eth/ethtx.proto It has these top-level messages: ProtoCompleteTransaction @@ -228,33 +228,34 @@ func init() { proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType") } -func init() { proto.RegisterFile("tx.proto", fileDescriptor0) } +func init() { proto.RegisterFile("bchain/coins/eth/ethtx.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 393 bytes of a gzipped FileDescriptorProto + // 409 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x8a, 0xd4, 0x30, - 0x14, 0xc6, 0xe9, 0x9f, 0xf9, 0xb3, 0xa7, 0x55, 0x24, 0x88, 0x84, 0xe2, 0x45, 0x59, 0xbc, 0xa8, - 0x5e, 0x14, 0x5c, 0x7d, 0x81, 0x75, 0xc4, 0x55, 0x18, 0xd6, 0x21, 0x46, 0xef, 0xb3, 0x69, 0xd8, - 0x29, 0xb6, 0x4d, 0x69, 0x52, 0xe8, 0xbe, 0x91, 0x2f, 0xe4, 0xbb, 0x78, 0x29, 0x39, 0x4d, 0xd7, - 0x11, 0x51, 0xbc, 0x3b, 0xbf, 0x6f, 0xce, 0x37, 0xf9, 0xbe, 0xa4, 0xb0, 0xb5, 0x53, 0xd9, 0x0f, - 0xda, 0x6a, 0x12, 0x29, 0x7b, 0x3c, 0xff, 0xb6, 0x02, 0x7a, 0x70, 0xb8, 0xd3, 0x6d, 0xdf, 0x28, - 0xab, 0xf8, 0x20, 0x3a, 0x23, 0xa4, 0xad, 0x75, 0x47, 0x72, 0x48, 0xde, 0x34, 0x5a, 0x7e, 0xbd, - 0x1e, 0xdb, 0x1b, 0x35, 0xd0, 0x20, 0x0f, 0x8a, 0x07, 0xec, 0x54, 0x22, 0x4f, 0xe1, 0x0c, 0x91, - 0xd7, 0xad, 0xa2, 0x61, 0x1e, 0x14, 0x31, 0xfb, 0x25, 0x90, 0xd7, 0x10, 0xf2, 0x89, 0x46, 0x79, - 0x50, 0x24, 0x17, 0xcf, 0x4a, 0x65, 0x8f, 0xe5, 0xdf, 0x8e, 0x2a, 0xf9, 0xc4, 0xef, 0x7a, 0xc5, - 0x42, 0x3e, 0x91, 0x1d, 0x6c, 0x98, 0x92, 0xaa, 0xee, 0x2d, 0x8d, 0xd1, 0xfa, 0xfc, 0xdf, 0x56, - 0xbf, 0x8c, 0xfe, 0xc5, 0x99, 0xfd, 0x08, 0x60, 0x3d, 0xff, 0x27, 0x39, 0x87, 0xf4, 0x52, 0x4a, - 0x3d, 0x76, 0xf6, 0x5a, 0x77, 0x52, 0x61, 0x8d, 0x98, 0xfd, 0xa6, 0x91, 0x0c, 0xb6, 0x57, 0xc2, - 0x1c, 0x86, 0x5a, 0xce, 0x35, 0x52, 0x76, 0xcf, 0xfe, 0xb7, 0x7d, 0xdd, 0xd6, 0x16, 0xbb, 0xc4, - 0xec, 0x9e, 0xc9, 0x63, 0x58, 0x7d, 0x11, 0xcd, 0xa8, 0x30, 0x69, 0xca, 0x66, 0x20, 0x14, 0x36, - 0x07, 0x71, 0xd7, 0x68, 0x51, 0xd1, 0x15, 0xea, 0x0b, 0x12, 0x02, 0xf1, 0x7b, 0x61, 0x8e, 0x74, - 0x8d, 0x32, 0xce, 0xe4, 0x21, 0x84, 0x5c, 0xd3, 0x0d, 0x2a, 0x21, 0xd7, 0x6e, 0xe7, 0xdd, 0xa0, - 0x5b, 0xba, 0x9d, 0x77, 0xdc, 0x4c, 0x5e, 0xc0, 0xa3, 0x93, 0xca, 0x1f, 0xba, 0x4a, 0x4d, 0xf4, - 0x0c, 0x9f, 0xe3, 0x0f, 0x3d, 0xfb, 0x1e, 0x40, 0x72, 0x72, 0x27, 0x2e, 0xcd, 0x95, 0x30, 0x9f, - 0x8d, 0xaa, 0xb0, 0x7a, 0xca, 0x16, 0x24, 0x4f, 0x60, 0xfd, 0xc9, 0x0a, 0x3b, 0x1a, 0xdf, 0xd9, - 0x13, 0xd9, 0x41, 0xb4, 0xd7, 0xb7, 0x34, 0xca, 0xa3, 0x22, 0xb9, 0x78, 0xf9, 0xdf, 0xb7, 0x5f, - 0xee, 0xf5, 0x2d, 0xbe, 0x82, 0x73, 0x67, 0x1f, 0x61, 0xe3, 0xd9, 0x25, 0xb8, 0xac, 0xaa, 0x41, - 0x19, 0xb3, 0x24, 0xf0, 0xe8, 0xba, 0xbe, 0x15, 0x56, 0xf8, 0xf3, 0x71, 0x76, 0xa9, 0xb8, 0xee, - 0x6b, 0x69, 0x30, 0x40, 0xca, 0x3c, 0xdd, 0xac, 0xf1, 0xb3, 0x7d, 0xf5, 0x33, 0x00, 0x00, 0xff, - 0xff, 0xde, 0xd5, 0x28, 0xa3, 0xc2, 0x02, 0x00, 0x00, + 0x18, 0xc5, 0xe9, 0x9f, 0x99, 0xd9, 0xfd, 0xa6, 0x8a, 0x04, 0x91, 0x30, 0xec, 0x45, 0x59, 0xbc, + 0x18, 0xbd, 0xe8, 0xe2, 0xea, 0x0b, 0xac, 0x23, 0xae, 0xc2, 0xb0, 0x0e, 0x31, 0x7a, 0x9f, 0x49, + 0xc3, 0x36, 0x38, 0x6d, 0x4a, 0x93, 0x42, 0xf7, 0x8d, 0x7c, 0x21, 0xdf, 0xc5, 0x4b, 0xc9, 0xd7, + 0x74, 0x1d, 0x11, 0x65, 0x2f, 0x0a, 0xf9, 0x9d, 0x7e, 0xa7, 0x39, 0x27, 0x29, 0x9c, 0xed, 0x65, + 0x25, 0x74, 0x73, 0x21, 0x8d, 0x6e, 0xec, 0x85, 0x72, 0x95, 0x7f, 0xdc, 0x50, 0xb4, 0x9d, 0x71, + 0x86, 0x24, 0xca, 0x55, 0xe7, 0xdf, 0x67, 0x40, 0x77, 0x1e, 0x37, 0xa6, 0x6e, 0x0f, 0xca, 0x29, + 0xde, 0x89, 0xc6, 0x0a, 0xe9, 0xb4, 0x69, 0x48, 0x0e, 0xcb, 0xb7, 0x07, 0x23, 0xbf, 0xdd, 0xf4, + 0xf5, 0x5e, 0x75, 0x34, 0xca, 0xa3, 0xf5, 0x23, 0x76, 0x2c, 0x91, 0x33, 0x38, 0x45, 0xe4, 0xba, + 0x56, 0x34, 0xce, 0xa3, 0x75, 0xca, 0x7e, 0x0b, 0xe4, 0x0d, 0xc4, 0x7c, 0xa0, 0x49, 0x1e, 0xad, + 0x97, 0x97, 0xcf, 0x0b, 0xe5, 0xaa, 0xe2, 0x5f, 0x5b, 0x15, 0x7c, 0xe0, 0x77, 0xad, 0x62, 0x31, + 0x1f, 0xc8, 0x06, 0x16, 0x4c, 0x49, 0xa5, 0x5b, 0x47, 0x53, 0xb4, 0xbe, 0xf8, 0xbf, 0x35, 0x0c, + 0xa3, 0x7f, 0x72, 0xae, 0x7e, 0x46, 0x30, 0x1f, 0xbf, 0x49, 0xce, 0x21, 0xbb, 0x92, 0xd2, 0xf4, + 0x8d, 0xbb, 0x31, 0x8d, 0x54, 0x58, 0x23, 0x65, 0x7f, 0x68, 0x64, 0x05, 0x27, 0xd7, 0xc2, 0xee, + 0x3a, 0x2d, 0xc7, 0x1a, 0x19, 0xbb, 0xe7, 0xf0, 0x6e, 0xab, 0x6b, 0xed, 0xb0, 0x4b, 0xca, 0xee, + 0x99, 0x3c, 0x85, 0xd9, 0x57, 0x71, 0xe8, 0x15, 0x26, 0xcd, 0xd8, 0x08, 0x84, 0xc2, 0x62, 0x27, + 0xee, 0x0e, 0x46, 0x94, 0x74, 0x86, 0xfa, 0x84, 0x84, 0x40, 0xfa, 0x41, 0xd8, 0x8a, 0xce, 0x51, + 0xc6, 0x35, 0x79, 0x0c, 0x31, 0x37, 0x74, 0x81, 0x4a, 0xcc, 0x8d, 0x9f, 0x79, 0xdf, 0x99, 0x9a, + 0x9e, 0x8c, 0x33, 0x7e, 0x4d, 0x5e, 0xc2, 0x93, 0xa3, 0xca, 0x1f, 0x9b, 0x52, 0x0d, 0xf4, 0x14, + 0xaf, 0xe3, 0x2f, 0x7d, 0xf5, 0x23, 0x82, 0xe5, 0xd1, 0x99, 0xf8, 0x34, 0xd7, 0xc2, 0x7e, 0xb1, + 0xaa, 0xc4, 0xea, 0x19, 0x9b, 0x90, 0x3c, 0x83, 0xf9, 0x67, 0x27, 0x5c, 0x6f, 0x43, 0xe7, 0x40, + 0x64, 0x03, 0xc9, 0xd6, 0xdc, 0xd2, 0x24, 0x4f, 0xd6, 0xcb, 0xcb, 0x57, 0x0f, 0x3e, 0xfd, 0x62, + 0x6b, 0x6e, 0xf1, 0x16, 0xbc, 0x7b, 0xf5, 0x09, 0x16, 0x81, 0x7d, 0x82, 0xab, 0xb2, 0xec, 0x94, + 0xb5, 0x53, 0x82, 0x80, 0xbe, 0xeb, 0x3b, 0xe1, 0x44, 0xd8, 0x1f, 0xd7, 0x3e, 0x15, 0x37, 0xad, + 0x96, 0x16, 0x03, 0x64, 0x2c, 0xd0, 0x7e, 0x8e, 0xbf, 0xed, 0xeb, 0x5f, 0x01, 0x00, 0x00, 0xff, + 0xff, 0xc2, 0x69, 0x8d, 0xdf, 0xd6, 0x02, 0x00, 0x00, } diff --git a/bchain/coins/eth/tx.proto b/bchain/coins/eth/ethtx.proto similarity index 100% rename from bchain/coins/eth/tx.proto rename to bchain/coins/eth/ethtx.proto diff --git a/bchain/coins/zec/zcashrpc.go b/bchain/coins/zec/zcashrpc.go index 9cf75852f4..47376e1c79 100644 --- a/bchain/coins/zec/zcashrpc.go +++ b/bchain/coins/zec/zcashrpc.go @@ -7,6 +7,7 @@ import ( "github.com/juju/errors" "github.com/trezor/blockbook/bchain" "github.com/trezor/blockbook/bchain/coins/btc" + "github.com/trezor/blockbook/common" ) // ZCashRPC is an interface to JSON-RPC bitcoind service @@ -14,6 +15,23 @@ type ZCashRPC struct { *btc.BitcoinRPC } +type ResGetBlockChainInfo struct { + Error *bchain.RPCError `json:"error"` + Result struct { + Chain string `json:"chain"` + Blocks int `json:"blocks"` + Headers int `json:"headers"` + Bestblockhash string `json:"bestblockhash"` + Difficulty common.JSONNumber `json:"difficulty"` + Pruned bool `json:"pruned"` + SizeOnDisk int64 `json:"size_on_disk"` + Consensus struct { + Chaintip string `json:"chaintip"` + Nextblock string `json:"nextblock"` + } `json:"consensus"` + } `json:"result"` +} + // NewZCashRPC returns new ZCashRPC instance func NewZCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { b, err := btc.NewBitcoinRPC(config, pushHandler) @@ -54,6 +72,41 @@ func (z *ZCashRPC) Initialize() error { return nil } +func (z *ZCashRPC) GetChainInfo() (*bchain.ChainInfo, error) { + chainInfo := ResGetBlockChainInfo{} + err := z.Call(&btc.CmdGetBlockChainInfo{Method: "getblockchaininfo"}, &chainInfo) + if err != nil { + return nil, err + } + if chainInfo.Error != nil { + return nil, chainInfo.Error + } + + networkInfo := btc.ResGetNetworkInfo{} + err = z.Call(&btc.CmdGetNetworkInfo{Method: "getnetworkinfo"}, &networkInfo) + if err != nil { + return nil, err + } + if networkInfo.Error != nil { + return nil, networkInfo.Error + } + + return &bchain.ChainInfo{ + Bestblockhash: chainInfo.Result.Bestblockhash, + Blocks: chainInfo.Result.Blocks, + Chain: chainInfo.Result.Chain, + Difficulty: string(chainInfo.Result.Difficulty), + Headers: chainInfo.Result.Headers, + SizeOnDisk: chainInfo.Result.SizeOnDisk, + Version: string(networkInfo.Result.Version), + Subversion: string(networkInfo.Result.Subversion), + ProtocolVersion: string(networkInfo.Result.ProtocolVersion), + Timeoffset: networkInfo.Result.Timeoffset, + Consensus: chainInfo.Result.Consensus, + Warnings: networkInfo.Result.Warnings, + }, nil +} + // GetBlock returns block with given hash. func (z *ZCashRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { var err error diff --git a/bchain/mq.go b/bchain/mq.go index 65596040a7..640052387a 100644 --- a/bchain/mq.go +++ b/bchain/mq.go @@ -89,6 +89,8 @@ func (mq *MQ) run(callback func(NotificationType)) { } repeatedError = true time.Sleep(100 * time.Millisecond) + } else { + repeatedError = false } repeatedError = false if msg != nil && len(msg) >= 3 { diff --git a/bchain/types.go b/bchain/types.go index 6f536153e8..78c8a531be 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -161,17 +161,18 @@ type MempoolEntry struct { // ChainInfo is used to get information about blockchain type ChainInfo struct { - Chain string `json:"chain"` - Blocks int `json:"blocks"` - Headers int `json:"headers"` - Bestblockhash string `json:"bestblockhash"` - Difficulty string `json:"difficulty"` - SizeOnDisk int64 `json:"size_on_disk"` - Version string `json:"version"` - Subversion string `json:"subversion"` - ProtocolVersion string `json:"protocolversion"` - Timeoffset float64 `json:"timeoffset"` - Warnings string `json:"warnings"` + Chain string `json:"chain"` + Blocks int `json:"blocks"` + Headers int `json:"headers"` + Bestblockhash string `json:"bestblockhash"` + Difficulty string `json:"difficulty"` + SizeOnDisk int64 `json:"size_on_disk"` + Version string `json:"version"` + Subversion string `json:"subversion"` + ProtocolVersion string `json:"protocolversion"` + Timeoffset float64 `json:"timeoffset"` + Warnings string `json:"warnings"` + Consensus interface{} `json:"consensus,omitempty"` } // RPCError defines rpc error returned by backend diff --git a/blockbook.go b/blockbook.go index 85d4170154..76ae13d0bf 100644 --- a/blockbook.go +++ b/blockbook.go @@ -545,12 +545,22 @@ func syncIndexLoop() { } func onNewBlockHash(hash string, height uint32) { + defer func() { + if r := recover(); r != nil { + glog.Error("onNewBlockHash recovered from panic: ", r) + } + }() for _, c := range callbacksOnNewBlock { c(hash, height) } } func onNewFiatRatesTicker(ticker *db.CurrencyRatesTicker) { + defer func() { + if r := recover(); r != nil { + glog.Error("onNewFiatRatesTicker recovered from panic: ", r) + } + }() for _, c := range callbacksOnNewFiatRatesTicker { c(ticker) } @@ -617,6 +627,11 @@ func storeInternalStateLoop() { } func onNewTxAddr(tx *bchain.Tx, desc bchain.AddressDescriptor) { + defer func() { + if r := recover(); r != nil { + glog.Error("onNewTxAddr recovered from panic: ", r) + } + }() for _, c := range callbacksOnNewTxAddr { c(tx, desc) } diff --git a/build/docker/bin/Dockerfile b/build/docker/bin/Dockerfile index c5e4616452..b6b4aa059d 100644 --- a/build/docker/bin/Dockerfile +++ b/build/docker/bin/Dockerfile @@ -9,12 +9,12 @@ RUN apt-get update && \ liblz4-dev graphviz && \ apt-get clean -ENV GOLANG_VERSION=go1.14.2.linux-amd64 -ENV ROCKSDB_VERSION=v5.18.3 +ENV GOLANG_VERSION=go1.15.5.linux-amd64 +ENV ROCKSDB_VERSION=v6.13.3 ENV GOPATH=/go ENV PATH=$PATH:$GOPATH/bin ENV CGO_CFLAGS="-I/opt/rocksdb/include" -ENV CGO_LDFLAGS="-L/opt/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4" +ENV CGO_LDFLAGS="-L/opt/rocksdb -ldl -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4" RUN mkdir /build @@ -35,7 +35,7 @@ RUN strip /opt/rocksdb/ldb /opt/rocksdb/sst_dump && \ # install build tools RUN go get github.com/gobuffalo/packr/... -# download pre-loaded depencencies +# pre-load depencencies RUN \ cleanup() { rm -rf $GOPATH/src/github.com/trezor ; } && \ trap cleanup EXIT && \ @@ -43,8 +43,7 @@ RUN \ cd $GOPATH/src/github.com/trezor && \ git clone https://github.com/trezor/blockbook.git && \ cd blockbook && \ - env GO111MODULE=on go mod vendor && \ - cp -r vendor /build/vendor + go mod download ADD Makefile /build/Makefile diff --git a/build/docker/bin/Makefile b/build/docker/bin/Makefile index bbae71dcc0..3db4f032ee 100644 --- a/build/docker/bin/Makefile +++ b/build/docker/bin/Makefile @@ -1,5 +1,4 @@ SHELL = /bin/bash -UPDATE_VENDOR ?= 1 VERSION ?= devel GITCOMMIT = $(shell cd /src && git describe --always --dirty) BUILDTIME = $(shell date --iso-8601=seconds) @@ -38,15 +37,8 @@ prepare-sources: rm -rf $(BLOCKBOOK_SRC) mkdir -p $(BLOCKBOOK_BASE) cp -r /src $(BLOCKBOOK_SRC) - $(MAKE) prepare-vendor - -prepare-vendor: - @ if [ "$(UPDATE_VENDOR)" -eq 1 ]; then \ - echo "Updating vendor"; \ - cd $(BLOCKBOOK_SRC) && rm -rf vendor* && cp -r /build/vendor . && env GO111MODULE=on go mod vendor ; \ - else \ - echo "Update of vendor not demanded, keeping version from src" ; \ - fi + cd $(BLOCKBOOK_SRC) && go mod download + sed -i 's/maxRequestContentLength\ =\ 1024\ \*\ 1024\ \*\ 5/maxRequestContentLength = 1024 * 1024 * 20/g' $(GOPATH)/pkg/mod/github.com/ethereum/go-ethereum*/rpc/http.go generate-data: cd $(BLOCKBOOK_SRC) && packr clean && packr diff --git a/build/docker/deb/gpg-keys/dash-releases.asc b/build/docker/deb/gpg-keys/dash-releases.asc index 203bdc2b08..66f98fee0a 100644 --- a/build/docker/deb/gpg-keys/dash-releases.asc +++ b/build/docker/deb/gpg-keys/dash-releases.asc @@ -1,91 +1,65 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Comment: User-ID: Alexander Block (codablock) -Comment: Created: 5/29/18 3:12 PM -Comment: Type: 4096-bit RSA -Comment: Usage: Signing, Encryption, Certifying User-IDs -Comment: Fingerprint: 99DF0DABDEE182FA53A33AE763A96B406102E091 -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 -=nX/z ------END PGP PUBLIC KEY BLOCK----- +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 +96I= +=85Kq +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/configs/coins/bcash.json b/configs/coins/bcash.json index 1747eec69f..c0b73fad8b 100644 --- a/configs/coins/bcash.json +++ b/configs/coins/bcash.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.22.0", - "binary_url": "https://download.bitcoinabc.org/0.22.0/linux/bitcoin-abc-0.22.0-x86_64-linux-gnu.tar.gz", + "version": "22.1.0", + "binary_url": "https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v22.1.0/bitcoin-cash-node-22.1.0-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "9d3718cbaf0516cc1e2bff40bd9ff708e61b6ed2469afb18e87e9fc1de3c4d5c", + "verification_source": "aa1002d51833b0de44084bde09951223be4f9c455427aef277f91dacd2f0f657", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.22.0/", + "subversion": "/Bitcoin ABC Cash Node:22.1.0/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, diff --git a/configs/coins/bcash_testnet.json b/configs/coins/bcash_testnet.json index 4fe3a7f71a..e1866befa4 100644 --- a/configs/coins/bcash_testnet.json +++ b/configs/coins/bcash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash-testnet", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.22.0", - "binary_url": "https://download.bitcoinabc.org/0.22.0/linux/bitcoin-abc-0.22.0-x86_64-linux-gnu.tar.gz", + "version": "22.1.0", + "binary_url": "https://github.com/bitcoin-cash-node/bitcoin-cash-node/releases/download/v22.1.0/bitcoin-cash-node-22.1.0-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "9d3718cbaf0516cc1e2bff40bd9ff708e61b6ed2469afb18e87e9fc1de3c4d5c", + "verification_source": "aa1002d51833b0de44084bde09951223be4f9c455427aef277f91dacd2f0f657", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.22.0/", + "subversion": "/Bitcoin ABC Cash Node:22.1.0/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, diff --git a/configs/coins/dash.json b/configs/coins/dash.json index bfb2fdef5e..94e1060a19 100644 --- a/configs/coins/dash.json +++ b/configs/coins/dash.json @@ -22,15 +22,15 @@ "package_name": "backend-dash", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.15.0.0", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.15.0.0/dashcore-0.15.0.0-x86_64-linux-gnu.tar.gz", + "version": "0.16.0.1", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.16.0.1/dashcore-0.16.0.1-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.15.0.0/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.16.0.1/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" ], - "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/dashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/dashd -deprecatedrpc=estimatefee -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", diff --git a/configs/coins/dash_testnet.json b/configs/coins/dash_testnet.json index 3bd4eb3bf6..c4378e0fae 100644 --- a/configs/coins/dash_testnet.json +++ b/configs/coins/dash_testnet.json @@ -22,15 +22,15 @@ "package_name": "backend-dash-testnet", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.15.0.0", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.15.0.0/dashcore-0.15.0.0-x86_64-linux-gnu.tar.gz", + "version": "0.16.0.1", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.16.0.1/dashcore-0.16.0.1-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.15.0.0/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.16.0.1/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" ], - "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/dashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/dashd -deprecatedrpc=estimatefee -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", diff --git a/configs/coins/deeponion.json b/configs/coins/deeponion.json index d5c42fd2af..fee9476791 100644 --- a/configs/coins/deeponion.json +++ b/configs/coins/deeponion.json @@ -22,12 +22,13 @@ "package_name": "backend-deeponion", "package_revision": "satoshilabs-1", "system_user": "deeponion", - "version": "2.0.5", - "binary_url": "https://github.com/deeponion/deeponion/releases/download/v2.0.5/deeponion-2.0.5-x86_64-linux-gnu.tar.gz", + "version": "2.2.0", + "binary_url": "https://github.com/deeponion/deeponion/releases/download/v2.2.0/DeepOnion-2.2.0-x86_64-linux-gnu.tar.gz", "extract_command": "tar -C backend --strip 1 -xpf", "exclude_files": [ + "bin/DeepOnion-qt" ], - "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/DeepOniond -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/DeepOniond -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", @@ -49,7 +50,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/DeepOnionCore:2.0.5/", + "subversion": "/DeepOnionCore:2.2.0/", "mempool_workers": 8, "mempool_sub_workers": 2, "block_addresses_to_keep": 300, diff --git a/configs/coins/ethereum-classic.json b/configs/coins/ethereum-classic.json index 5918861b95..0674fc957d 100644 --- a/configs/coins/ethereum-classic.json +++ b/configs/coins/ethereum-classic.json @@ -19,10 +19,10 @@ "package_name": "backend-ethereum-classic", "package_revision": "satoshilabs-1", "system_user": "ethereum-classic", - "version": "1.11.15", - "binary_url": "https://github.com/etclabscore/core-geth/releases/download/v1.11.15/core-geth-linux-v1.11.15.zip", + "version": "1.11.18", + "binary_url": "https://github.com/etclabscore/core-geth/releases/download/v1.11.18/core-geth-linux-v1.11.18.zip", "verification_type": "sha256", - "verification_source": "44ea5fa939280d000db66d1b54d6e900977231fa1275c754259b8474e9cb7df7", + "verification_source": "ee1533e546e9520eeb327be30978b55449cce09341c3d242f4104ae41b2c9c2c", "extract_command": "unzip -d backend", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --classic --ipcdisable --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 38337 --ws --wsaddr 127.0.0.1 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" --rpc --rpcport 8137 -rpcaddr 127.0.0.1 --rpccorsdomain \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/ethereum.json b/configs/coins/ethereum.json index 7272149509..aa138a6235 100644 --- a/configs/coins/ethereum.json +++ b/configs/coins/ethereum.json @@ -21,10 +21,10 @@ "package_name": "backend-ethereum", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.21-0287d548", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.21-0287d548.tar.gz", + "version": "1.9.24-cc05b050", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.21-0287d548.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --ipcdisable --syncmode full --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 38336 --ws --wsaddr 127.0.0.1 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" --rpc --rpcport 8136 -rpcaddr 127.0.0.1 --rpccorsdomain \"*\" --rpcvhosts \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/ethereum_testnet_ropsten.json b/configs/coins/ethereum_testnet_ropsten.json index 8913dd3cc3..57f9a4cc55 100644 --- a/configs/coins/ethereum_testnet_ropsten.json +++ b/configs/coins/ethereum_testnet_ropsten.json @@ -20,10 +20,10 @@ "package_name": "backend-ethereum-testnet-ropsten", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.21-0287d548", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.21-0287d548.tar.gz", + "version": "1.9.24-cc05b050", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.21-0287d548.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --testnet --syncmode full --ipcdisable --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 48336 --ws --wsaddr 127.0.0.1 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/qtum.json b/configs/coins/qtum.json index e6fed7c2ff..95609e66a1 100644 --- a/configs/coins/qtum.json +++ b/configs/coins/qtum.json @@ -22,10 +22,10 @@ "package_name": "backend-qtum", "package_revision": "satoshilabs-1", "system_user": "qtum", - "version": "0.19.1", - "binary_url": "https://github.com/qtumproject/qtum/releases/download/mainnet-ignition-v0.19.1/qtum-0.19.1-x86_64-linux-gnu.tar.gz", + "version": "0.20.1", + "binary_url": "https://github.com/qtumproject/qtum/releases/download/mainnet-ignition-v0.20.1/qtum-0.20.1-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "044a8e535ff8a220dbcd1fe7fadae2429c123c97bd1fb5e7c50abc0e6640c8d4", + "verification_source": "e9a77eb3e2b76625fdc8058c12bc0790309b24b9c1ac39f4895e4f8756cf0010", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/qtum-qt" @@ -67,4 +67,4 @@ "package_maintainer": "CodeFace", "package_maintainer_email": "codeface@qtum.info" } -} \ No newline at end of file +} diff --git a/configs/coins/qtum_testnet.json b/configs/coins/qtum_testnet.json index 8fce110a6d..507c1503b0 100644 --- a/configs/coins/qtum_testnet.json +++ b/configs/coins/qtum_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-qtum-testnet", "package_revision": "satoshilabs-1", "system_user": "qtum", - "version": "0.19.1", - "binary_url": "https://github.com/qtumproject/qtum/releases/download/mainnet-ignition-v0.19.1/qtum-0.19.1-x86_64-linux-gnu.tar.gz", + "version": "0.20.1", + "binary_url": "https://github.com/qtumproject/qtum/releases/download/mainnet-ignition-v0.20.1/qtum-0.20.1-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "044a8e535ff8a220dbcd1fe7fadae2429c123c97bd1fb5e7c50abc0e6640c8d4", + "verification_source": "e9a77eb3e2b76625fdc8058c12bc0790309b24b9c1ac39f4895e4f8756cf0010", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/qtum-qt" @@ -67,4 +67,4 @@ "package_maintainer": "CodeFace", "package_maintainer_email": "codeface@qtum.info" } -} \ No newline at end of file +} diff --git a/configs/coins/ritocoin.json b/configs/coins/ritocoin.json index d8788f942d..5e71ecb484 100644 --- a/configs/coins/ritocoin.json +++ b/configs/coins/ritocoin.json @@ -22,10 +22,10 @@ "package_name": "backend-ritocoin", "package_revision": "satoshilabs-1", "system_user": "ritocoin", - "version": "2.4.0.0", - "binary_url": "https://github.com/RitoProject/Ritocoin/releases/download/2.4.1.0/rito-2.4.1.0-x86_64-linux-gnu.tar.gz", + "version": "2.4.2.0", + "binary_url": "https://github.com/RitoProject/Ritocoin/releases/download/2.4.2.0/rito-2.4.2.0-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "753f8a536080af1f2348e255a1cf7115039b22f6753d278931ddd5473906bc39", + "verification_source": "69301b7bfa74765d5b535b2c2b93bcbd4d5c2870625004593b4c5c769e098f67", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/rito-qt" diff --git a/configs/coins/zcash.json b/configs/coins/zcash.json index 92bbe307ea..15a2a47407 100644 --- a/configs/coins/zcash.json +++ b/configs/coins/zcash.json @@ -22,10 +22,10 @@ "package_name": "backend-zcash", "package_revision": "satoshilabs-1", "system_user": "zcash", - "version": "4.0.0", - "binary_url": "https://z.cash/downloads/zcash-4.0.0-linux64-debian-stretch.tar.gz", + "version": "4.1.1", + "binary_url": "https://z.cash/downloads/zcash-4.1.1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", - "verification_source": "a0daf673d45e92fe97f2dd43bbaf6d6653940643aff62915f46df89af4d8c8b5", + "verification_source": "50b639f0d1c7177809535bad7631490297aa7873d867425096eb8c7a04b2b132", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/zcashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", diff --git a/configs/coins/zcash_testnet.json b/configs/coins/zcash_testnet.json index 057406c47e..e593a0d0ab 100644 --- a/configs/coins/zcash_testnet.json +++ b/configs/coins/zcash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-zcash-testnet", "package_revision": "satoshilabs-1", "system_user": "zcash", - "version": "4.0.0", - "binary_url": "https://z.cash/downloads/zcash-4.0.0-linux64-debian-stretch.tar.gz", + "version": "4.1.1", + "binary_url": "https://z.cash/downloads/zcash-4.1.1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", - "verification_source": "a0daf673d45e92fe97f2dd43bbaf6d6653940643aff62915f46df89af4d8c8b5", + "verification_source": "50b639f0d1c7177809535bad7631490297aa7873d867425096eb8c7a04b2b132", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/zcashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", diff --git a/db/dboptions.go b/db/dboptions.go index 155c4c86a0..4011cbce86 100644 --- a/db/dboptions.go +++ b/db/dboptions.go @@ -4,9 +4,6 @@ package db import "C" import ( - "reflect" - "unsafe" - "github.com/tecbot/gorocksdb" ) @@ -45,18 +42,13 @@ func boolToChar(b bool) C.uchar { */ func createAndSetDBOptions(bloomBits int, c *gorocksdb.Cache, maxOpenFiles int) *gorocksdb.Options { - // blockOpts := gorocksdb.NewDefaultBlockBasedTableOptions() - cNativeBlockOpts := C.rocksdb_block_based_options_create() - blockOpts := &gorocksdb.BlockBasedTableOptions{} - cBlockField := reflect.Indirect(reflect.ValueOf(blockOpts)).FieldByName("c") - cBlockPtr := (**C.rocksdb_block_based_table_options_t)(unsafe.Pointer(cBlockField.UnsafeAddr())) - *cBlockPtr = cNativeBlockOpts + blockOpts := gorocksdb.NewDefaultBlockBasedTableOptions() blockOpts.SetBlockSize(32 << 10) // 32kB blockOpts.SetBlockCache(c) if bloomBits > 0 { blockOpts.SetFilterPolicy(gorocksdb.NewBloomFilter(bloomBits)) } - C.rocksdb_block_based_options_set_format_version(cNativeBlockOpts, 4) + blockOpts.SetFormatVersion(4) opts := gorocksdb.NewDefaultOptions() opts.SetBlockBasedTableFactory(blockOpts) diff --git a/db/rocksdb.go b/db/rocksdb.go index 84e716a1cd..b505cd4fb3 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -157,7 +157,7 @@ func NewRocksDB(path string, cacheSize, maxOpenFiles int, parser bchain.BlockCha return nil, errors.New("Unknown chain type") } - c := gorocksdb.NewLRUCache(cacheSize) + c := gorocksdb.NewLRUCache(uint64(cacheSize)) db, cfh, err := openDB(path, c, maxOpenFiles) if err != nil { return nil, err @@ -308,17 +308,17 @@ func (d *RocksDB) Reopen() error { return nil } -func atoi(s string) int { +func atoUint64(s string) uint64 { i, err := strconv.Atoi(s) if err != nil { return 0 } - return i + return uint64(i) } // GetMemoryStats returns memory usage statistics as reported by RocksDB func (d *RocksDB) GetMemoryStats() string { - var total, indexAndFilter, memtable int + var total, indexAndFilter, memtable uint64 type columnStats struct { name string indexAndFilter string @@ -329,12 +329,12 @@ func (d *RocksDB) GetMemoryStats() string { cs[i].name = cfNames[i] cs[i].indexAndFilter = d.db.GetPropertyCF("rocksdb.estimate-table-readers-mem", d.cfh[i]) cs[i].memtable = d.db.GetPropertyCF("rocksdb.cur-size-all-mem-tables", d.cfh[i]) - indexAndFilter += atoi(cs[i].indexAndFilter) - memtable += atoi(cs[i].memtable) + indexAndFilter += atoUint64(cs[i].indexAndFilter) + memtable += atoUint64(cs[i].memtable) } m := struct { - cacheUsage int - pinnedCacheUsage int + cacheUsage uint64 + pinnedCacheUsage uint64 columns []columnStats }{ cacheUsage: d.cache.GetUsage(), diff --git a/db/sync.go b/db/sync.go index c2d6ca2955..267bd94adb 100644 --- a/db/sync.go +++ b/db/sync.go @@ -44,6 +44,7 @@ func NewSyncWorker(db *RocksDB, chain bchain.BlockChain, syncWorkers, syncChunk } var errSynced = errors.New("synced") +var errFork = errors.New("fork") // ErrOperationInterrupted is returned when operation is interrupted by OS signal var ErrOperationInterrupted = errors.New("ErrOperationInterrupted") @@ -105,7 +106,7 @@ func (w *SyncWorker) resyncIndex(onNewBlock bchain.OnNewBlockFunc, initialSync b } if remoteHash != localBestHash { // forked - the remote hash differs from the local hash at the same height - glog.Info("resync: local is forked at height ", localBestHeight, ", local hash ", localBestHash, ", remote hash", remoteHash) + glog.Info("resync: local is forked at height ", localBestHeight, ", local hash ", localBestHash, ", remote hash ", remoteHash) return w.handleFork(localBestHeight, localBestHash, onNewBlock, initialSync) } glog.Info("resync: local at ", localBestHeight, " is behind") @@ -141,7 +142,11 @@ func (w *SyncWorker) resyncIndex(onNewBlock bchain.OnNewBlockFunc, initialSync b return w.resyncIndex(onNewBlock, initialSync) } } - return w.connectBlocks(onNewBlock, initialSync) + err = w.connectBlocks(onNewBlock, initialSync) + if err == errFork { + return w.resyncIndex(onNewBlock, initialSync) + } + return err } func (w *SyncWorker) handleFork(localBestHeight uint32, localBestHash string, onNewBlock bchain.OnNewBlockFunc, initialSync bool) error { @@ -382,9 +387,9 @@ func (w *SyncWorker) getBlockChain(out chan blockResult, done chan struct{}) { hash := w.startHash height := w.startHeight + prevHash := "" - // some coins do not return Next hash - // must loop until error + // loop until error ErrBlockNotFound for { select { case <-done: @@ -399,6 +404,12 @@ func (w *SyncWorker) getBlockChain(out chan blockResult, done chan struct{}) { out <- blockResult{err: err} return } + if block.Prev != "" && prevHash != "" && prevHash != block.Prev { + glog.Infof("sync: fork detected at height %d %s, local prevHash %s, remote prevHash %s", height, block.Hash, prevHash, block.Prev) + out <- blockResult{err: errFork} + return + } + prevHash = block.Hash hash = block.Next height++ out <- blockResult{block: block} diff --git a/docs/api.md b/docs/api.md index af4c3163a0..dd38d6f501 100644 --- a/docs/api.md +++ b/docs/api.md @@ -764,11 +764,32 @@ The websocket interface provides the following requests: The client can subscribe to the following events: -- new block added to blockchain -- new transaction for given address (list of addresses) -- new currency rate ticker +- `subscribeNewBlock` - new block added to blockchain +- `subscribeAddresses` - new transaction for given address (list of addresses) +- `subscribeFiatRates` - new currency rate ticker There can be always only one subscription of given event per connection, i.e. new list of addresses replaces previous list of addresses. _Note: If there is reorg on the backend (blockchain), you will get a new block hash with the same or even smaller height if the reorg is deeper_ +Websocket communication format +``` +{ + "id":"1", //an id to help to identify the response + "method":"", + "params": +} +``` + +Example for subscribing to an address (or multiple addresses) +``` +{ + "id":"1", + "method":"subscribeAddresses", + "params":{ + "addresses":["mnYYiDCb2JZXnqEeXta1nkt5oCVe2RVhJj", "tb1qp0we5epypgj4acd2c4au58045ruud2pd6heuee"] + } +} +``` + + diff --git a/docs/build.md b/docs/build.md index 951420711a..407db78f67 100644 --- a/docs/build.md +++ b/docs/build.md @@ -194,7 +194,7 @@ like macOS or Windows, please read instructions specific for each project. Setup go environment: ``` -wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.tz && tar xf go1.14.2.linux-amd64.tar.gz +wget https://golang.org/dl/go1.14.2.linux-amd64.tar.gz && tar xf go1.14.2.linux-amd64.tar.gz sudo mv go /opt/go sudo ln -s /opt/go/bin/go /usr/bin/go # see `go help gopath` for details @@ -211,6 +211,7 @@ sudo apt-get update && sudo apt-get install -y \ build-essential git wget pkg-config libzmq3-dev libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev git clone https://github.com/facebook/rocksdb.git cd rocksdb +git checkout v6.8.1 CFLAGS=-fPIC CXXFLAGS=-fPIC make release ``` @@ -218,11 +219,20 @@ Setup variables for gorocksdb: https://github.com/tecbot/gorocksdb ``` export CGO_CFLAGS="-I/path/to/rocksdb/include" -export CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4" +export CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lm -lz -ldl -lbz2 -lsnappy -llz4" ``` Install ZeroMQ: https://github.com/zeromq/libzmq +``` +git clone https://github.com/zeromq/libzmq +cd libzmq +./autogen.sh +./configure +make +sudo make install +``` + Get blockbook sources, install dependencies, build: ``` @@ -242,9 +252,11 @@ When you have running back-end daemon you can start Blockbook. It is highly reco for both Blockbook and back-end daemon. You can use *contrib/scripts/build-blockchaincfg.sh* that will generate Blockbook's blockchain configuration from our coin definition files. +Also, check that your operating system open files limit is set to high enough value - recommended is at least 20000. + Example for Bitcoin: ``` -contrib/scripts/build-blockchaincfg.sh +./contrib/scripts/build-blockchaincfg.sh ./blockbook -sync -blockchaincfg=build/blockchaincfg.json -internal=:9030 -public=:9130 -certfile=server/testcert -logtostderr ``` diff --git a/go.mod b/go.mod index 9385b1f1c1..de7759c626 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/trezor/blockbook -go 1.13 +go 1.15 require ( github.com/Groestlcoin/go-groestl-hash v0.0.0-20181012171753-790653ac190c // indirect github.com/allegro/bigcache v1.2.1 // indirect - github.com/aristanetworks/goarista v0.0.0-20200224203130-895b4c57c44d // indirect + github.com/aristanetworks/goarista v0.0.0-20201012165903-2cb20defcd66 // indirect github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e github.com/cenkalti/backoff/v3 v3.0.0 github.com/deckarep/golang-set v1.7.1 diff --git a/go.sum b/go.sum index cc3fb80e99..31a7b64490 100644 --- a/go.sum +++ b/go.sum @@ -65,7 +65,7 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= +github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= @@ -136,6 +136,8 @@ github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcug github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -143,6 +145,8 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+q github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= @@ -254,6 +258,8 @@ github.com/decred/dcrd/dcrutil v1.3.0 h1:LtKIiDnq925yJT/4OpIKKiU9/WaxfD9LfhxrpLS github.com/decred/dcrd/dcrutil v1.3.0/go.mod h1:7fUT70QAarhDwQK62g92uDbbYpjXlXngpy5RBiecufo= github.com/decred/dcrd/hdkeychain v1.1.1 h1:6+BwOmPfEyw/Krm+91RXysc76F1jqCta3m45DyD5+s4= github.com/decred/dcrd/hdkeychain v1.1.1/go.mod h1:CLBVXLoO63fIiqkv38KR23zXGSgrfiAWOybOKTneLhA= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/txscript v1.1.0 h1:MwkLXdc4Yq83oeNNEQJdlBTkNlorKXn8Nd5W2JXyMZg= github.com/decred/dcrd/txscript v1.1.0/go.mod h1:gbcq6gpGfKddPmZSKp+17ils2cLzUqHopXf8H5rCY7Y= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= @@ -300,6 +306,7 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= @@ -1441,7 +1448,6 @@ github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.m github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -1485,7 +1491,6 @@ github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXx github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -1504,9 +1509,7 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= @@ -1516,10 +1519,7 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289/go.mod h1:FGbBv5OPKjch+jNUJmEQpMZytIdyW0NdBtWFcfSKusc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1650,6 +1650,7 @@ github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -1831,7 +1832,6 @@ golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1962,8 +1962,6 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1988,8 +1986,6 @@ golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2090,7 +2086,6 @@ golang.org/x/tools v0.0.0-20201016152635-c90119023dcc h1:rWX1cgVidb8uib2Kl1bEPS1 golang.org/x/tools v0.0.0-20201016152635-c90119023dcc/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2190,7 +2185,7 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= -gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= @@ -2200,8 +2195,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUk gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= -gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= diff --git a/server/public.go b/server/public.go index 9575499197..5470fa6f95 100644 --- a/server/public.go +++ b/server/public.go @@ -975,6 +975,9 @@ func (s *PublicServer) apiTxSpecific(r *http.Request, apiVersion int) (interface var err error s.metrics.ExplorerViews.With(common.Labels{"action": "api-tx-specific"}).Inc() tx, err = s.chain.GetTransactionSpecific(&bchain.Tx{Txid: txid}) + if err == bchain.ErrTxNotFound { + return nil, api.NewAPIError(fmt.Sprintf("Transaction '%v' not found", txid), true) + } return tx, err } diff --git a/server/websocket.go b/server/websocket.go index db019c18c6..20ea3af1d1 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -143,24 +143,40 @@ func (s *WebsocketServer) GetHandler() http.Handler { } func (s *WebsocketServer) closeChannel(c *websocketChannel) { + if c.CloseOut() { + c.conn.Close() + s.onDisconnect(c) + } +} + +func (c *websocketChannel) CloseOut() bool { c.aliveLock.Lock() defer c.aliveLock.Unlock() if c.alive { - c.conn.Close() c.alive = false //clean out close(c.out) for len(c.out) > 0 { <-c.out } - s.onDisconnect(c) + return true } + return false } -func (c *websocketChannel) IsAlive() bool { +func (c *websocketChannel) DataOut(data *websocketRes) { c.aliveLock.Lock() defer c.aliveLock.Unlock() - return c.alive + if c.alive { + if len(c.out) < outChannelSize-1 { + c.out <- data + } else { + glog.Warning("Channel ", c.id, " overflow, closing") + // close the connection but do not call CloseOut - would call duplicate c.aliveLock.Lock + // CloseOut will be called because the closed connection will cause break in the inputLoop + c.conn.Close() + } + } } func (s *WebsocketServer) inputLoop(c *websocketChannel) { @@ -204,11 +220,18 @@ func (s *WebsocketServer) inputLoop(c *websocketChannel) { } func (s *WebsocketServer) outputLoop(c *websocketChannel) { + defer func() { + if r := recover(); r != nil { + glog.Error("recovered from panic: ", r, ", ", c.id) + s.closeChannel(c) + } + }() for m := range c.out { err := c.conn.WriteJSON(m) if err != nil { glog.Error("Error sending message to ", c.id, ", ", err) s.closeChannel(c) + return } } } @@ -383,18 +406,6 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs }, } -func sendResponse(c *websocketChannel, req *websocketReq, data interface{}) { - defer func() { - if r := recover(); r != nil { - glog.Error("Client ", c.id, ", onRequest ", req.Method, " recovered from panic: ", r) - } - }() - c.out <- &websocketRes{ - ID: req.ID, - Data: data, - } -} - func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) { var err error var data interface{} @@ -408,7 +419,10 @@ func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) { } // nil data means no response if data != nil { - sendResponse(c, req, data) + c.DataOut(&websocketRes{ + ID: req.ID, + Data: data, + }) } }() t := time.Now() @@ -665,11 +679,25 @@ func (s *WebsocketServer) unmarshalAddresses(params []byte) ([]bchain.AddressDes return rv, nil } +// unsubscribe addresses without addressSubscriptionsLock - can be called only from subscribeAddresses and unsubscribeAddresses +func (s *WebsocketServer) doUnsubscribeAddresses(c *websocketChannel) { + for ads, sa := range s.addressSubscriptions { + for sc := range sa { + if sc == c { + delete(sa, c) + } + } + if len(sa) == 0 { + delete(s.addressSubscriptions, ads) + } + } +} + func (s *WebsocketServer) subscribeAddresses(c *websocketChannel, addrDesc []bchain.AddressDescriptor, req *websocketReq) (res interface{}, err error) { - // unsubscribe all previous subscriptions - s.unsubscribeAddresses(c) s.addressSubscriptionsLock.Lock() defer s.addressSubscriptionsLock.Unlock() + // unsubscribe all previous subscriptions + s.doUnsubscribeAddresses(c) for i := range addrDesc { ads := string(addrDesc[i]) as, ok := s.addressSubscriptions[ads] @@ -686,26 +714,30 @@ func (s *WebsocketServer) subscribeAddresses(c *websocketChannel, addrDesc []bch func (s *WebsocketServer) unsubscribeAddresses(c *websocketChannel) (res interface{}, err error) { s.addressSubscriptionsLock.Lock() defer s.addressSubscriptionsLock.Unlock() - for ads, sa := range s.addressSubscriptions { + s.doUnsubscribeAddresses(c) + return &subscriptionResponse{false}, nil +} + +// unsubscribe fiat rates without fiatRatesSubscriptionsLock - can be called only from subscribeFiatRates and unsubscribeFiatRates +func (s *WebsocketServer) doUnsubscribeFiatRates(c *websocketChannel) { + for fr, sa := range s.fiatRatesSubscriptions { for sc := range sa { if sc == c { delete(sa, c) } } if len(sa) == 0 { - delete(s.addressSubscriptions, ads) + delete(s.fiatRatesSubscriptions, fr) } } - return &subscriptionResponse{false}, nil } // subscribeFiatRates subscribes all FiatRates subscriptions by this channel func (s *WebsocketServer) subscribeFiatRates(c *websocketChannel, currency string, req *websocketReq) (res interface{}, err error) { - // unsubscribe all previous subscriptions - s.unsubscribeFiatRates(c) s.fiatRatesSubscriptionsLock.Lock() defer s.fiatRatesSubscriptionsLock.Unlock() - + // unsubscribe all previous subscriptions + s.doUnsubscribeFiatRates(c) if currency == "" { currency = allFiatRates } @@ -722,16 +754,7 @@ func (s *WebsocketServer) subscribeFiatRates(c *websocketChannel, currency strin func (s *WebsocketServer) unsubscribeFiatRates(c *websocketChannel) (res interface{}, err error) { s.fiatRatesSubscriptionsLock.Lock() defer s.fiatRatesSubscriptionsLock.Unlock() - for fr, sa := range s.fiatRatesSubscriptions { - for sc := range sa { - if sc == c { - delete(sa, c) - } - } - if len(sa) == 0 { - delete(s.fiatRatesSubscriptions, fr) - } - } + s.doUnsubscribeFiatRates(c) return &subscriptionResponse{false}, nil } @@ -747,12 +770,10 @@ func (s *WebsocketServer) OnNewBlock(hash string, height uint32) { Hash: hash, } for c, id := range s.newBlockSubscriptions { - if c.IsAlive() { - c.out <- &websocketRes{ - ID: id, - Data: &data, - } - } + c.DataOut(&websocketRes{ + ID: id, + Data: &data, + }) } glog.Info("broadcasting new block ", height, " ", hash, " to ", len(s.newBlockSubscriptions), " channels") } @@ -790,6 +811,38 @@ func (s *WebsocketServer) sendOnNewTxAddr(stringAddressDescriptor string, tx *ap } } +func (s *WebsocketServer) sendOnNewTxAddr(stringAddressDescriptor string, tx *api.Tx) { + addrDesc := bchain.AddressDescriptor(stringAddressDescriptor) + addr, _, err := s.chainParser.GetAddressesFromAddrDesc(addrDesc) + if err != nil { + glog.Error("GetAddressesFromAddrDesc error ", err, " for ", addrDesc) + return + } + if len(addr) == 1 { + data := struct { + Address string `json:"address"` + Tx *api.Tx `json:"tx"` + }{ + Address: addr[0], + Tx: tx, + } + // get the list of subscriptions again, this time keep the lock + s.addressSubscriptionsLock.Lock() + defer s.addressSubscriptionsLock.Unlock() + as, ok := s.addressSubscriptions[stringAddressDescriptor] + if ok { + for c, id := range as { + if c.IsAlive() { + c.out <- &websocketRes{ + ID: id, + Data: &data, + } + } + } + glog.Info("broadcasting new tx ", tx.Txid, ", addr ", addr[0], " to ", len(as), " channels") + } + } +}>>>>> bbupdate // OnNewTx is a callback that broadcasts info about a tx affecting subscribed address func (s *WebsocketServer) OnNewTx(tx *bchain.MempoolTx) { // check if there is any subscription in inputs, outputs and erc20 @@ -847,8 +900,6 @@ func (s *WebsocketServer) OnNewTx(tx *bchain.MempoolTx) { } func (s *WebsocketServer) broadcastTicker(currency string, rates map[string]float64) { - s.fiatRatesSubscriptionsLock.Lock() - defer s.fiatRatesSubscriptionsLock.Unlock() as, ok := s.fiatRatesSubscriptions[currency] if ok && len(as) > 0 { data := struct { @@ -856,24 +907,20 @@ func (s *WebsocketServer) broadcastTicker(currency string, rates map[string]floa }{ Rates: rates, } - // get the list of subscriptions again, this time keep the lock - as, ok = s.fiatRatesSubscriptions[currency] - if ok { - for c, id := range as { - if c.IsAlive() { - c.out <- &websocketRes{ - ID: id, - Data: &data, - } - } - } - glog.Info("broadcasting new rates for currency ", currency, " to ", len(as), " channels") + for c, id := range as { + c.DataOut(&websocketRes{ + ID: id, + Data: &data, + }) } + glog.Info("broadcasting new rates for currency ", currency, " to ", len(as), " channels") } } // OnNewFiatRatesTicker is a callback that broadcasts info about fiat rates affecting subscribed currency func (s *WebsocketServer) OnNewFiatRatesTicker(ticker *db.CurrencyRatesTicker) { + s.fiatRatesSubscriptionsLock.Lock() + defer s.fiatRatesSubscriptionsLock.Unlock() for currency, rate := range ticker.Rates { s.broadcastTicker(currency, map[string]float64{currency: rate}) } diff --git a/static/templates/tx.html b/static/templates/tx.html index ee4279f131..7257ebcbf9 100644 --- a/static/templates/tx.html +++ b/static/templates/tx.html @@ -78,7 +78,7 @@
Raw Transaction