Compare commits
15 Commits
deepcrayon
...
utxocheck
Author | SHA1 | Date |
---|---|---|
Martin Boehm | b6e3f26eb2 | |
Martin Boehm | 72e48ce658 | |
Martin Boehm | 9cfe1f3d25 | |
Martin Boehm | 839f67f6eb | |
Martin Boehm | 267c2b22c1 | |
Martin Boehm | 5a801ed038 | |
Martin Boehm | 3c90059994 | |
Martin Boehm | b4d0e2e819 | |
Martin Boehm | a5a5edef9d | |
Martin Boehm | 923234e97d | |
Vladyslav Burzakovskyy | 466d89a670 | |
Martin Boehm | 358858b418 | |
Martin Boehm | f903a1d6f9 | |
Martin Boehm | 7df8f05b31 | |
Martin Boehm | af1d3fceaa |
|
@ -8,7 +8,6 @@ debug*
|
|||
docker/blockbook
|
||||
build/pkg-defs
|
||||
build/blockbook
|
||||
build/blockchaincfg.json
|
||||
build/ldb
|
||||
build/sst_dump
|
||||
build/*.deb
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
Blockbook is back-end service for Trezor wallet. Although it is open source, the design and development of the core packages
|
||||
is done by Trezor developers in order to keep Blockbook compatible with Trezor.
|
||||
|
||||
Bug fixes and support for new coins are welcome. **Please take note that non-fixing pull requests that change base
|
||||
packages or another coin code will not be accepted.** If you have a need to change some of the existing code, please file
|
||||
Bug fixes and support for new coins are welcome. Please take note that non-fixing pull requests that change base
|
||||
packages or another coin code will not be accepted. If you have a need to change some of the existing code, please file
|
||||
an issue and discuss your request with Blockbook maintainers.
|
||||
|
||||
## Development environment
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Groestlcoin/go-groestl-hash"
|
||||
packages = ["groestl","hash"]
|
||||
revision = "790653ac190c4029ee200e82a8f21b5d1afaf7d6"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8b13694e3e7b33c6f389f367b6a001a1184b051e34880fdd9e58a2207d9f6573"
|
||||
name = "github.com/allegro/bigcache"
|
||||
packages = [
|
||||
".",
|
||||
"queue",
|
||||
]
|
||||
pruneopts = ""
|
||||
revision = "69ea0af04088faa57adb9ac683934277141e92a5"
|
||||
version = "v2.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:10f6df61e4d3de150f3c11c3c6791c5702382c7f4aa983bcab9f49a73fea44a3"
|
||||
name = "github.com/aristanetworks/goarista"
|
||||
packages = ["monotime"]
|
||||
pruneopts = ""
|
||||
revision = "8e7d5b18fe7ad671e07097d5445dbc70422663b2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/agl/ed25519"
|
||||
packages = [".","edwards25519"]
|
||||
revision = "5312a61534124124185d41f09206b9fef1d88403"
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/bsm/go-vlq"
|
||||
packages = ["."]
|
||||
revision = "ec6e8d4f5f4ec0f6e808ffc7f4dcc7516d4d7d49"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/btcd"
|
||||
packages = ["blockchain","btcec","chaincfg","chaincfg/chainhash","database","txscript","wire"]
|
||||
revision = "8e7c0427fee5d4778c5d4eb987150369e3ca1d0e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/btclog"
|
||||
packages = ["."]
|
||||
revision = "84c8d2346e9fc8c7b947e243b9c24e6df9fd206a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/dchest/blake256"
|
||||
packages = ["."]
|
||||
revision = "dee3fe6eb0e98dc774a94fc231f85baf7c29d360"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/deckarep/golang-set"
|
||||
packages = ["."]
|
||||
revision = "1d4478f51bed434f1dadf96dcd9b43aabac66795"
|
||||
version = "v1.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/decred/base58"
|
||||
packages = ["."]
|
||||
revision = "dbeddd8aab76c31eb2ea98351a63fa2c6bf46888"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/decred/dcrd"
|
||||
packages = ["chaincfg","chaincfg/chainec","chaincfg/chainhash","dcrec","dcrec/edwards","dcrec/secp256k1","dcrec/secp256k1/schnorr","dcrjson","dcrutil","txscript","wire"]
|
||||
revision = "e3e8c47c68b010dbddeb783ebad32a3a4993dd71"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/decred/slog"
|
||||
packages = ["."]
|
||||
revision = "fbd821ef791ba2b8ae945f5d44f4e49396d230c5"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[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"]
|
||||
revision = "24d727b6d6e2c0cde222fa12155c4a6db5caaf2e"
|
||||
version = "v1.8.20"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-stack/stack"
|
||||
packages = ["."]
|
||||
revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc"
|
||||
version = "v1.7.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gobuffalo/packr"
|
||||
packages = ["."]
|
||||
revision = "5a2cbb54c4e7d482e3f518c56f1f86f133d5204f"
|
||||
version = "v1.13.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = ["proto"]
|
||||
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
packages = ["."]
|
||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto"]
|
||||
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/snappy"
|
||||
packages = ["."]
|
||||
revision = "553a641470496b2327abcac10b36396bd98e45c9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
packages = ["."]
|
||||
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/bchutil"
|
||||
packages = ["."]
|
||||
revision = "6373f11b6efe1ea81e8713b8788a695b2c144d38"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/btcutil"
|
||||
packages = [".","base58","bech32","chaincfg","hdkeychain","txscript"]
|
||||
revision = "a3d2b8457b77d37c3813742d4030e199b6e09111"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/juju/errors"
|
||||
packages = ["."]
|
||||
revision = "c7d06af17c68cd34c835053720b21f6549d9b0ee"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/golang-socketio"
|
||||
packages = [".","protocol","transport"]
|
||||
revision = "f60b0a8befde091474a624a8ffd81ee9912957b3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mr-tron/base58"
|
||||
packages = ["base58"]
|
||||
revision = "c1bdf7c52f59d6685ca597b9955a443ff95eeee6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/pebbe/zmq4"
|
||||
packages = ["."]
|
||||
revision = "5b443b6471cea4b4f9f85025530c04c93233f76a"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = ["prometheus","prometheus/promhttp"]
|
||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
packages = ["go"]
|
||||
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
|
||||
revision = "d0f7cd64bda49e08b22ae8a730aa57aa0db125d6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [".","internal/util","nfs","xfs"]
|
||||
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/rs/cors"
|
||||
packages = ["."]
|
||||
revision = "feef513b9575b32f84bafa580aad89b011259019"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/schancel/cashaddr-converter"
|
||||
packages = ["address","baseconv","cashaddress","legacy"]
|
||||
revision = "0a38f5822f795dc3727b4caacc298e02938d9eb1"
|
||||
version = "v9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/syndtr/goleveldb"
|
||||
packages = ["leveldb","leveldb/cache","leveldb/comparer","leveldb/errors","leveldb/filter","leveldb/iterator","leveldb/journal","leveldb/memdb","leveldb/opt","leveldb/storage","leveldb/table","leveldb/util"]
|
||||
revision = "714f901b98fdb3aa954b4193d8cbd64a28d80cad"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/tecbot/gorocksdb"
|
||||
packages = ["."]
|
||||
revision = "214b6b7bc0f06812ab5602fdc502a3e619916f38"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ripemd160", "sha3"]
|
||||
revision = "a832865fa7ada6126f4c6124ac49f71be71bff2a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["websocket"]
|
||||
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/karalabe/cookiejar.v2"
|
||||
packages = ["collections/prque"]
|
||||
revision = "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/natefinch/npipe.v2"
|
||||
packages = ["."]
|
||||
revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/bsm/go-vlq",
|
||||
"github.com/deckarep/golang-set",
|
||||
"github.com/decred/dcrd/chaincfg",
|
||||
"github.com/decred/dcrd/dcrjson",
|
||||
"github.com/decred/dcrd/txscript",
|
||||
"github.com/ethereum/go-ethereum",
|
||||
"github.com/ethereum/go-ethereum/common",
|
||||
"github.com/ethereum/go-ethereum/common/hexutil",
|
||||
"github.com/ethereum/go-ethereum/core/types",
|
||||
"github.com/ethereum/go-ethereum/ethclient",
|
||||
"github.com/ethereum/go-ethereum/rpc",
|
||||
"github.com/gobuffalo/packr",
|
||||
"github.com/gogo/protobuf/proto",
|
||||
"github.com/golang/glog",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"github.com/gorilla/websocket",
|
||||
"github.com/juju/errors",
|
||||
"github.com/martinboehm/bchutil",
|
||||
"github.com/martinboehm/btcd/blockchain",
|
||||
"github.com/martinboehm/btcd/chaincfg/chainhash",
|
||||
"github.com/martinboehm/btcd/txscript",
|
||||
"github.com/martinboehm/btcd/wire",
|
||||
"github.com/martinboehm/btcutil",
|
||||
"github.com/martinboehm/btcutil/base58",
|
||||
"github.com/martinboehm/btcutil/chaincfg",
|
||||
"github.com/martinboehm/btcutil/hdkeychain",
|
||||
"github.com/martinboehm/btcutil/txscript",
|
||||
"github.com/martinboehm/golang-socketio",
|
||||
"github.com/martinboehm/golang-socketio/transport",
|
||||
"github.com/pebbe/zmq4",
|
||||
"github.com/prometheus/client_golang/prometheus",
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp",
|
||||
"github.com/schancel/cashaddr-converter/address",
|
||||
"github.com/tecbot/gorocksdb",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/bsm/go-vlq"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/btcd"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/btcutil"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/mux"
|
||||
version = "1.6.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/juju/errors"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/golang-socketio"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/pebbe/zmq4"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
version = "0.8.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/tecbot/gorocksdb"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/ethereum/go-ethereum"
|
||||
version = "1.8.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/golang/protobuf"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/martinboehm/bchutil"
|
23
Makefile
23
Makefile
|
@ -1,9 +1,8 @@
|
|||
BIN_IMAGE = blockbook-build
|
||||
DEB_IMAGE = blockbook-build-deb
|
||||
PACKAGER = $(shell id -u):$(shell id -g)
|
||||
BASE_IMAGE = $$(awk -F= '$$1=="ID" { print $$2 ;}' /etc/os-release):$$(awk -F= '$$1=="VERSION_ID" { print $$2 ;}' /etc/os-release | tr -d '"')
|
||||
NO_CACHE = false
|
||||
TCMALLOC =
|
||||
UPDATE_VENDOR = 1
|
||||
ARGS ?=
|
||||
|
||||
TARGETS=$(subst .json,, $(shell ls configs/coins))
|
||||
|
@ -11,28 +10,28 @@ TARGETS=$(subst .json,, $(shell ls configs/coins))
|
|||
.PHONY: build build-debug test deb
|
||||
|
||||
build: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build ARGS="$(ARGS)"
|
||||
|
||||
build-debug: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
|
||||
|
||||
test: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
|
||||
|
||||
test-integration: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
|
||||
|
||||
test-all: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
|
||||
|
||||
deb-backend-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS)
|
||||
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)
|
||||
|
||||
deb-blockbook-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS)
|
||||
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)
|
||||
|
||||
deb-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS)
|
||||
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)
|
||||
|
||||
deb-blockbook-all: clean-deb $(addprefix deb-blockbook-, $(TARGETS))
|
||||
|
||||
|
@ -45,8 +44,8 @@ build-images: clean-images
|
|||
|
||||
.bin-image:
|
||||
@if [ $$(build/tools/image_status.sh $(BIN_IMAGE):latest build/docker) != "ok" ]; then \
|
||||
echo "Building image $(BIN_IMAGE) from $(BASE_IMAGE)"; \
|
||||
docker build --no-cache=$(NO_CACHE) --build-arg TCMALLOC=$(TCMALLOC) --build-arg BASE_IMAGE=$(BASE_IMAGE) -t $(BIN_IMAGE) build/docker/bin; \
|
||||
echo "Building image $(BIN_IMAGE)..."; \
|
||||
docker build --no-cache=$(NO_CACHE) -t $(BIN_IMAGE) build/docker/bin; \
|
||||
else \
|
||||
echo "Image $(BIN_IMAGE) is up to date"; \
|
||||
fi
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
[![Go Report Card](https://goreportcard.com/badge/trezor/blockbook)](https://goreportcard.com/report/trezor/blockbook)
|
||||
|
||||
# Blockbook
|
||||
|
||||
**Blockbook** is back-end service for Trezor wallet. Main features of **Blockbook** are:
|
||||
|
||||
- index of addresses and address balances of the connected block chain
|
||||
- fast searches in the indexes
|
||||
- simple blockchain explorer
|
||||
- websocket, API and legacy Bitcore Insight compatible socket.io interfaces
|
||||
- support of multiple coins (Bitcoin and Ethereum type), with easy extensibility for other coins
|
||||
- scripts for easy creation of debian packages for backend and blockbook
|
||||
|
||||
## Build and installation instructions
|
||||
|
||||
Officially supported platform is **Debian Linux** and **AMD64** architecture.
|
||||
|
||||
Memory and disk requirements for initial synchronization of **Bitcoin mainnet** are around 32 GB RAM and over 180 GB of disk space. After initial synchronization, fully synchronized instance uses about 10 GB RAM.
|
||||
Other coins should have lower requirements, depending on the size of their block chain. Note that fast SSD disks are highly
|
||||
recommended.
|
||||
|
||||
User installation guide is [here](https://wiki.trezor.io/User_manual:Running_a_local_instance_of_Trezor_Wallet_backend_(Blockbook)).
|
||||
|
||||
Developer build guide is [here](/docs/build.md).
|
||||
|
||||
Contribution guide is [here](CONTRIBUTING.md).
|
||||
|
||||
## Implemented coins
|
||||
|
||||
Blockbook currently supports over 30 coins. The Trezor team implemented
|
||||
|
||||
- Bitcoin, Bitcoin Cash, Zcash, Dash, Litecoin, Bitcoin Gold, Ethereum, Ethereum Classic, Dogecoin, Namecoin, Vertcoin, DigiByte, Liquid
|
||||
|
||||
the rest of coins were implemented by the community.
|
||||
|
||||
Testnets for some coins are also supported, for example:
|
||||
- Bitcoin Testnet, Bitcoin Cash Testnet, ZCash Testnet, Ethereum Testnet Ropsten
|
||||
|
||||
List of all implemented coins is in [the registry of ports](/docs/ports.md).
|
||||
|
||||
## Common issues when running Blockbook or implementing additional coins
|
||||
|
||||
#### Out of memory when doing initial synchronization
|
||||
|
||||
How to reduce memory footprint of the initial sync:
|
||||
|
||||
- disable rocksdb cache by parameter `-dbcache=0`, the default size is 500MB
|
||||
- run blockbook with parameter `-workers=1`. This disables bulk import mode, which caches a lot of data in memory (not in rocksdb cache). It will run about twice as slowly but especially for smaller blockchains it is no problem at all.
|
||||
|
||||
Please add your experience to this [issue](https://github.com/trezor/blockbook/issues/43).
|
||||
|
||||
#### Error `internalState: database is in inconsistent state and cannot be used`
|
||||
|
||||
Blockbook was killed during the initial import, most commonly by OOM killer. By default, Blockbook performs the initial import in bulk import mode, which for performance reasons does not store all the data immediately to the database. If Blockbook is killed during this phase, the database is left in an inconsistent state.
|
||||
|
||||
See above how to reduce the memory footprint, delete the database files and run the import again.
|
||||
|
||||
Check [this](https://github.com/trezor/blockbook/issues/89) or [this](https://github.com/trezor/blockbook/issues/147) issue for more info.
|
||||
|
||||
#### Running on Ubuntu
|
||||
|
||||
[This issue](https://github.com/trezor/blockbook/issues/45) discusses how to run Blockbook on Ubuntu. If you have some additional experience with Blockbook on Ubuntu, please add it to [this issue](https://github.com/trezor/blockbook/issues/45).
|
||||
|
||||
#### My coin implementation is reporting parse errors when importing blockchain
|
||||
|
||||
Your coin's block/transaction data may not be compatible with `BitcoinParser` `ParseBlock`/`ParseTx`, which is used by default. In that case, implement your coin in a similar way we used in case of [zcash](https://github.com/trezor/blockbook/tree/master/bchain/coins/zec) and some other coins. The principle is not to parse the block/transaction data in Blockbook but instead to get parsed transactions as json from the backend.
|
||||
|
||||
## Data storage in RocksDB
|
||||
|
||||
Blockbook stores data the key-value store RocksDB. Database format is described [here](/docs/rocksdb.md).
|
||||
|
||||
## API
|
||||
|
||||
Blockbook API is described [here](/docs/api.md).
|
93
README.md
93
README.md
|
@ -1,57 +1,74 @@
|
|||
# Fork
|
||||
Fork of Trezor Blockbook.
|
||||
[![Go Report Card](https://goreportcard.com/badge/trezor/blockbook)](https://goreportcard.com/report/trezor/blockbook)
|
||||
|
||||
# Blockbook
|
||||
|
||||
The differences:
|
||||
**Blockbook** is back-end service for Trezor wallet. Main features of **Blockbook** are:
|
||||
|
||||
* Just for Ethereum.
|
||||
- index of addresses and address balances of the connected block chain
|
||||
- fast searches in the indexes
|
||||
- simple blockchain explorer
|
||||
- websocket, API and legacy Bitcore Insight compatible socket.io interfaces
|
||||
- support of multiple coins (Bitcoin and Ethereum type), with easy extensibility for other coins
|
||||
- scripts for easy creation of debian packages for backend and blockbook
|
||||
|
||||
* Use existing `geth --full` server.
|
||||
## Build and installation instructions
|
||||
|
||||
* Don't require `backend-*` package.
|
||||
Officially supported platform is **Debian Linux** and **AMD64** architecture.
|
||||
|
||||
* Minimal UI, dark theme.
|
||||
Memory and disk requirements for initial synchronization of **Bitcoin mainnet** are around 32 GB RAM and over 180 GB of disk space. After initial synchronization, fully synchronized instance uses about 10 GB RAM.
|
||||
Other coins should have lower requirements, depending on the size of their block chain. Note that fast SSD disks are highly
|
||||
recommended.
|
||||
|
||||
* Listen only on localhost, no SSL.
|
||||
User installation guide is [here](https://wiki.trezor.io/User_manual:Running_a_local_instance_of_Trezor_Wallet_backend_(Blockbook)).
|
||||
|
||||
* Use spacecruft repos, not github.
|
||||
Developer build guide is [here](/docs/build.md).
|
||||
|
||||
* Don't use CDN.
|
||||
Contribution guide is [here](CONTRIBUTING.md).
|
||||
|
||||
# Install
|
||||
## Implemented coins
|
||||
|
||||
```
|
||||
# Install docker, etc.
|
||||
git clone https://spacecruft.org/spacecruft/blockbook
|
||||
cd blockbook
|
||||
make deb-blockbook-ethereum
|
||||
dpkg -i build/blockbook-ethereum_0.3.4_amd64.deb
|
||||
```
|
||||
Blockbook currently supports over 30 coins. The Trezor team implemented
|
||||
|
||||
Edit config:
|
||||
```
|
||||
vim /opt/coins/blockbook/ethereum/config/blockchaincfg.json
|
||||
```
|
||||
- Bitcoin, Bitcoin Cash, Zcash, Dash, Litecoin, Bitcoin Gold, Ethereum, Ethereum Classic, Dogecoin, Namecoin, Vertcoin, DigiByte, Liquid
|
||||
|
||||
XXX Hardcoded into systemd script, set `geth` node:
|
||||
the rest of coins were implemented by the community.
|
||||
|
||||
```
|
||||
vim /lib/systemd/system/blockbook-ethereum.service
|
||||
systemctl daemon-reload
|
||||
```
|
||||
Testnets for some coins are also supported, for example:
|
||||
- Bitcoin Testnet, Bitcoin Cash Testnet, ZCash Testnet, Ethereum Testnet Ropsten
|
||||
|
||||
Start:
|
||||
```
|
||||
systemctl start blockbook-ethereum.service
|
||||
```
|
||||
List of all implemented coins is in [the registry of ports](/docs/ports.md).
|
||||
|
||||
Logs:
|
||||
```
|
||||
tail -f /opt/coins/blockbook/ethereum/logs/blockbook.INFO
|
||||
```
|
||||
## Common issues when running Blockbook or implementing additional coins
|
||||
|
||||
# Upstream
|
||||
Fork of Trezor Blockbook. See `README-upstream.md`.
|
||||
#### Out of memory when doing initial synchronization
|
||||
|
||||
* https://github.com/trezor/blockbook
|
||||
How to reduce memory footprint of the initial sync:
|
||||
|
||||
- disable rocksdb cache by parameter `-dbcache=0`, the default size is 500MB
|
||||
- run blockbook with parameter `-workers=1`. This disables bulk import mode, which caches a lot of data in memory (not in rocksdb cache). It will run about twice as slowly but especially for smaller blockchains it is no problem at all.
|
||||
|
||||
Please add your experience to this [issue](https://github.com/trezor/blockbook/issues/43).
|
||||
|
||||
#### Error `internalState: database is in inconsistent state and cannot be used`
|
||||
|
||||
Blockbook was killed during the initial import, most commonly by OOM killer. By default, Blockbook performs the initial import in bulk import mode, which for performance reasons does not store all the data immediately to the database. If Blockbook is killed during this phase, the database is left in an inconsistent state.
|
||||
|
||||
See above how to reduce the memory footprint, delete the database files and run the import again.
|
||||
|
||||
Check [this](https://github.com/trezor/blockbook/issues/89) or [this](https://github.com/trezor/blockbook/issues/147) issue for more info.
|
||||
|
||||
#### Running on Ubuntu
|
||||
|
||||
[This issue](https://github.com/trezor/blockbook/issues/45) discusses how to run Blockbook on Ubuntu. If you have some additional experience with Blockbook on Ubuntu, please add it to [this issue](https://github.com/trezor/blockbook/issues/45).
|
||||
|
||||
#### My coin implementation is reporting parse errors when importing blockchain
|
||||
|
||||
Your coin's block/transaction data may not be compatible with `BitcoinParser` `ParseBlock`/`ParseTx`, which is used by default. In that case, implement your coin in a similar way we used in case of [zcash](https://github.com/trezor/blockbook/tree/master/bchain/coins/zec) and some other coins. The principle is not to parse the block/transaction data in Blockbook but instead to get parsed transactions as json from the backend.
|
||||
|
||||
## Data storage in RocksDB
|
||||
|
||||
Blockbook stores data the key-value store RocksDB. Database format is described [here](/docs/rocksdb.md).
|
||||
|
||||
## API
|
||||
|
||||
Blockbook API is described [here](/docs/api.md).
|
||||
|
|
98
api/types.go
98
api/types.go
|
@ -1,16 +1,14 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/common"
|
||||
"blockbook/db"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
"spacecruft.org/spacecruft/blockbook/db"
|
||||
)
|
||||
|
||||
const maxUint32 = ^uint32(0)
|
||||
|
@ -171,12 +169,11 @@ type TokenTransfer struct {
|
|||
|
||||
// EthereumSpecific contains ethereum specific transaction data
|
||||
type EthereumSpecific struct {
|
||||
Status eth.TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending
|
||||
Nonce uint64 `json:"nonce"`
|
||||
GasLimit *big.Int `json:"gasLimit"`
|
||||
GasUsed *big.Int `json:"gasUsed"`
|
||||
GasPrice *Amount `json:"gasPrice"`
|
||||
Data string `json:"data,omitempty"`
|
||||
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending
|
||||
Nonce uint64 `json:"nonce"`
|
||||
GasLimit *big.Int `json:"gasLimit"`
|
||||
GasUsed *big.Int `json:"gasUsed"`
|
||||
GasPrice *Amount `json:"gasPrice"`
|
||||
}
|
||||
|
||||
// Tx holds information about a transaction
|
||||
|
@ -196,7 +193,8 @@ type Tx struct {
|
|||
FeesSat *Amount `json:"fees,omitempty"`
|
||||
Hex string `json:"hex,omitempty"`
|
||||
Rbf bool `json:"rbf,omitempty"`
|
||||
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"`
|
||||
CoinSpecificData interface{} `json:"-"`
|
||||
CoinSpecificJSON json.RawMessage `json:"-"`
|
||||
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
|
||||
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
|
||||
}
|
||||
|
@ -226,8 +224,6 @@ const (
|
|||
AddressFilterVoutInputs = -2
|
||||
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
||||
AddressFilterVoutOutputs = -3
|
||||
// AddressFilterVoutQueryNotNecessary signals that query for transactions is not necessary as there are no transactions for specified contract filter
|
||||
AddressFilterVoutQueryNotNecessary = -4
|
||||
|
||||
// TokensToReturnNonzeroBalance - return only tokens with nonzero balance
|
||||
TokensToReturnNonzeroBalance TokensToReturn = 0
|
||||
|
@ -303,13 +299,12 @@ func (a Utxos) Less(i, j int) bool {
|
|||
|
||||
// BalanceHistory contains info about one point in time of balance history
|
||||
type BalanceHistory struct {
|
||||
Time uint32 `json:"time"`
|
||||
Txs uint32 `json:"txs"`
|
||||
ReceivedSat *Amount `json:"received"`
|
||||
SentSat *Amount `json:"sent"`
|
||||
SentToSelfSat *Amount `json:"sentToSelf"`
|
||||
FiatRates map[string]float64 `json:"rates,omitempty"`
|
||||
Txid string `json:"txid,omitempty"`
|
||||
Time uint32 `json:"time"`
|
||||
Txs uint32 `json:"txs"`
|
||||
ReceivedSat *Amount `json:"received"`
|
||||
SentSat *Amount `json:"sent"`
|
||||
FiatRates map[string]float64 `json:"rates,omitempty"`
|
||||
Txid string `json:"txid,omitempty"`
|
||||
}
|
||||
|
||||
// BalanceHistories is array of BalanceHistory
|
||||
|
@ -331,9 +326,8 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
|||
bhs := make(BalanceHistories, 0)
|
||||
if len(a) > 0 {
|
||||
bha := BalanceHistory{
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
}
|
||||
sort.Sort(a)
|
||||
for i := range a {
|
||||
|
@ -346,19 +340,17 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
|||
bhs = append(bhs, bha)
|
||||
}
|
||||
bha = BalanceHistory{
|
||||
Time: time,
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &Amount{},
|
||||
Time: time,
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
}
|
||||
}
|
||||
if bha.Txid != bh.Txid {
|
||||
bha.Txs += bh.Txs
|
||||
bha.Txid = bh.Txid
|
||||
}
|
||||
(*big.Int)(bha.ReceivedSat).Add((*big.Int)(bha.ReceivedSat), (*big.Int)(bh.ReceivedSat))
|
||||
(*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat))
|
||||
(*big.Int)(bha.SentToSelfSat).Add((*big.Int)(bha.SentToSelfSat), (*big.Int)(bh.SentToSelfSat))
|
||||
(*big.Int)(bha.ReceivedSat).Add((*big.Int)(bha.ReceivedSat), (*big.Int)(bh.ReceivedSat))
|
||||
}
|
||||
if bha.Txs > 0 {
|
||||
bha.Txid = ""
|
||||
|
@ -376,19 +368,19 @@ type Blocks struct {
|
|||
|
||||
// BlockInfo contains extended block header data and a list of block txids
|
||||
type BlockInfo struct {
|
||||
Hash string `json:"hash"`
|
||||
Prev string `json:"previousBlockHash,omitempty"`
|
||||
Next string `json:"nextBlockHash,omitempty"`
|
||||
Height uint32 `json:"height"`
|
||||
Confirmations int `json:"confirmations"`
|
||||
Size int `json:"size"`
|
||||
Time int64 `json:"time,omitempty"`
|
||||
Version common.JSONNumber `json:"version"`
|
||||
MerkleRoot string `json:"merkleRoot"`
|
||||
Nonce string `json:"nonce"`
|
||||
Bits string `json:"bits"`
|
||||
Difficulty string `json:"difficulty"`
|
||||
Txids []string `json:"tx,omitempty"`
|
||||
Hash string `json:"hash"`
|
||||
Prev string `json:"previousBlockHash,omitempty"`
|
||||
Next string `json:"nextBlockHash,omitempty"`
|
||||
Height uint32 `json:"height"`
|
||||
Confirmations int `json:"confirmations"`
|
||||
Size int `json:"size"`
|
||||
Time int64 `json:"time,omitempty"`
|
||||
Version json.Number `json:"version"`
|
||||
MerkleRoot string `json:"merkleRoot"`
|
||||
Nonce string `json:"nonce"`
|
||||
Bits string `json:"bits"`
|
||||
Difficulty string `json:"difficulty"`
|
||||
Txids []string `json:"tx,omitempty"`
|
||||
}
|
||||
|
||||
// Block contains information about block
|
||||
|
@ -421,10 +413,26 @@ type BlockbookInfo struct {
|
|||
About string `json:"about"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// SystemInfo contains information about the running blockbook and backend instance
|
||||
type SystemInfo struct {
|
||||
Blockbook *BlockbookInfo `json:"blockbook"`
|
||||
Backend *common.BackendInfo `json:"backend"`
|
||||
Blockbook *BlockbookInfo `json:"blockbook"`
|
||||
Backend *BackendInfo `json:"backend"`
|
||||
}
|
||||
|
||||
// MempoolTxid contains information about a transaction in mempool
|
||||
|
|
|
@ -67,22 +67,20 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
|||
name: "one",
|
||||
a: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
groupByTime: 3600,
|
||||
want: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -90,76 +88,67 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
|||
name: "aggregate",
|
||||
a: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(0)),
|
||||
Time: 1521504812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521504812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(3)),
|
||||
SentSat: (*Amount)(big.NewInt(4)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521504812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(3)),
|
||||
SentSat: (*Amount)(big.NewInt(4)),
|
||||
Time: 1521504812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(7)),
|
||||
SentSat: (*Amount)(big.NewInt(8)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||
Time: 1521504812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(7)),
|
||||
SentSat: (*Amount)(big.NewInt(8)),
|
||||
Time: 1521504812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(9)),
|
||||
SentSat: (*Amount)(big.NewInt(10)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(5)),
|
||||
Time: 1521534812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(9)),
|
||||
SentSat: (*Amount)(big.NewInt(10)),
|
||||
Time: 1521534812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(12)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521534812,
|
||||
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(12)),
|
||||
Time: 1521534812,
|
||||
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
groupByTime: 3600,
|
||||
want: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(14)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(5)),
|
||||
Time: 1521504000,
|
||||
Txs: 2,
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(14)),
|
||||
Time: 1521504000,
|
||||
Txs: 2,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(20)),
|
||||
SentSat: (*Amount)(big.NewInt(22)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(11)),
|
||||
Time: 1521532800,
|
||||
Txs: 2,
|
||||
ReceivedSat: (*Amount)(big.NewInt(20)),
|
||||
SentSat: (*Amount)(big.NewInt(22)),
|
||||
Time: 1521532800,
|
||||
Txs: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"math/big"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
// ScriptSigV1 is used for legacy api v1
|
||||
|
|
363
api/worker.go
363
api/worker.go
|
@ -1,6 +1,10 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/eth"
|
||||
"blockbook/common"
|
||||
"blockbook/db"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -14,10 +18,6 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
"spacecruft.org/spacecruft/blockbook/db"
|
||||
)
|
||||
|
||||
// Worker is handle to api worker
|
||||
|
@ -253,7 +253,32 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
|||
if err != nil {
|
||||
glog.Errorf("GetErc20FromTx error %v, %v", err, bchainTx)
|
||||
}
|
||||
tokens = w.getTokensFromErc20(ets)
|
||||
tokens = make([]TokenTransfer, len(ets))
|
||||
for i := range ets {
|
||||
e := &ets[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,
|
||||
}
|
||||
}
|
||||
ethTxData := eth.GetEthereumTxData(bchainTx)
|
||||
// mempool txs do not have fees yet
|
||||
if ethTxData.GasUsed != nil {
|
||||
|
@ -268,14 +293,12 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
|||
GasUsed: ethTxData.GasUsed,
|
||||
Nonce: ethTxData.Nonce,
|
||||
Status: ethTxData.Status,
|
||||
Data: ethTxData.Data,
|
||||
}
|
||||
}
|
||||
// for now do not return size, we would have to compute vsize of segwit transactions
|
||||
// size:=len(bchainTx.Hex) / 2
|
||||
var sj json.RawMessage
|
||||
// return CoinSpecificData for all mempool transactions or if requested
|
||||
if specificJSON || bchainTx.Confirmations == 0 {
|
||||
if specificJSON {
|
||||
sj, err = w.chain.GetTransactionSpecific(bchainTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -300,140 +323,14 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
|||
Rbf: rbf,
|
||||
Vin: vins,
|
||||
Vout: vouts,
|
||||
CoinSpecificData: sj,
|
||||
CoinSpecificData: bchainTx.CoinSpecificData,
|
||||
CoinSpecificJSON: 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
|
||||
}
|
||||
|
||||
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool, filter *AddressFilter, maxResults int) ([]string, error) {
|
||||
var err error
|
||||
txids := make([]string, 0, 4)
|
||||
|
@ -503,19 +400,6 @@ func (t *Tx) getAddrVoutValue(addrDesc bchain.AddressDescriptor) *big.Int {
|
|||
}
|
||||
return &val
|
||||
}
|
||||
func (t *Tx) getAddrEthereumTypeMempoolInputValue(addrDesc bchain.AddressDescriptor) *big.Int {
|
||||
var val big.Int
|
||||
if len(t.Vin) > 0 && len(t.Vout) > 0 && bytes.Equal(t.Vin[0].AddrDesc, addrDesc) {
|
||||
val.Add(&val, (*big.Int)(t.Vout[0].ValueSat))
|
||||
// add maximum possible fee (the used value is not yet known)
|
||||
if t.EthereumSpecific != nil && t.EthereumSpecific.GasLimit != nil && t.EthereumSpecific.GasPrice != nil {
|
||||
var fees big.Int
|
||||
fees.Mul((*big.Int)(t.EthereumSpecific.GasPrice), t.EthereumSpecific.GasLimit)
|
||||
val.Add(&val, &fees)
|
||||
}
|
||||
}
|
||||
return &val
|
||||
}
|
||||
|
||||
func (t *Tx) getAddrVinValue(addrDesc bchain.AddressDescriptor) *big.Int {
|
||||
var val big.Int
|
||||
|
@ -612,44 +496,6 @@ func computePaging(count, page, itemsOnPage int) (Paging, int, int, int) {
|
|||
}, from, to, page
|
||||
}
|
||||
|
||||
func (w *Worker) getEthereumToken(index int, addrDesc, contract bchain.AddressDescriptor, details AccountDetails, txs int) (*Token, error) {
|
||||
var b *big.Int
|
||||
validContract := true
|
||||
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(contract)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", contract)
|
||||
}
|
||||
if ci == nil {
|
||||
ci = &bchain.Erc20Contract{}
|
||||
addresses, _, _ := w.chainParser.GetAddressesFromAddrDesc(contract)
|
||||
if len(addresses) > 0 {
|
||||
ci.Contract = addresses[0]
|
||||
ci.Name = addresses[0]
|
||||
}
|
||||
validContract = false
|
||||
}
|
||||
// do not read contract balances etc in case of Basic option
|
||||
if details >= AccountDetailsTokenBalances && validContract {
|
||||
b, err = w.chain.EthereumTypeGetErc20ContractBalance(addrDesc, contract)
|
||||
if err != nil {
|
||||
// return nil, nil, nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractBalance %v %v", addrDesc, c.Contract)
|
||||
glog.Warningf("EthereumTypeGetErc20ContractBalance addr %v, contract %v, %v", addrDesc, contract, err)
|
||||
}
|
||||
} else {
|
||||
b = nil
|
||||
}
|
||||
return &Token{
|
||||
Type: ERC20TokenType,
|
||||
BalanceSat: (*Amount)(b),
|
||||
Contract: ci.Contract,
|
||||
Name: ci.Name,
|
||||
Symbol: ci.Symbol,
|
||||
Transfers: txs,
|
||||
Decimals: ci.Decimals,
|
||||
ContractIndex: strconv.Itoa(index),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescriptor, details AccountDetails, filter *AddressFilter) (*db.AddrBalance, []Token, *bchain.Erc20Contract, uint64, int, int, error) {
|
||||
var (
|
||||
ba *db.AddrBalance
|
||||
|
@ -668,13 +514,6 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetBalance %v", addrDesc)
|
||||
}
|
||||
var filterDesc bchain.AddressDescriptor
|
||||
if filter.Contract != "" {
|
||||
filterDesc, err = w.chainParser.GetAddrDescFromAddress(filter.Contract)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true)
|
||||
}
|
||||
}
|
||||
if ca != nil {
|
||||
ba = &db.AddrBalance{
|
||||
Txs: uint32(ca.TotalTxs),
|
||||
|
@ -686,6 +525,13 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetNonce %v", addrDesc)
|
||||
}
|
||||
var filterDesc bchain.AddressDescriptor
|
||||
if filter.Contract != "" {
|
||||
filterDesc, err = w.chainParser.GetAddrDescFromAddress(filter.Contract)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true)
|
||||
}
|
||||
}
|
||||
if details > AccountDetailsBasic {
|
||||
tokens = make([]Token, len(ca.Contracts))
|
||||
var j int
|
||||
|
@ -697,26 +543,43 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
// filter only transactions of this contract
|
||||
filter.Vout = i + 1
|
||||
}
|
||||
t, err := w.getEthereumToken(i+1, addrDesc, c.Contract, details, int(c.Txs))
|
||||
validContract := true
|
||||
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(c.Contract)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, err
|
||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", c.Contract)
|
||||
}
|
||||
if ci == nil {
|
||||
ci = &bchain.Erc20Contract{}
|
||||
addresses, _, _ := w.chainParser.GetAddressesFromAddrDesc(c.Contract)
|
||||
if len(addresses) > 0 {
|
||||
ci.Contract = addresses[0]
|
||||
ci.Name = addresses[0]
|
||||
}
|
||||
validContract = false
|
||||
}
|
||||
// do not read contract balances etc in case of Basic option
|
||||
if details >= AccountDetailsTokenBalances && validContract {
|
||||
b, err = w.chain.EthereumTypeGetErc20ContractBalance(addrDesc, c.Contract)
|
||||
if err != nil {
|
||||
// return nil, nil, nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractBalance %v %v", addrDesc, c.Contract)
|
||||
glog.Warningf("EthereumTypeGetErc20ContractBalance addr %v, contract %v, %v", addrDesc, c.Contract, err)
|
||||
}
|
||||
} else {
|
||||
b = nil
|
||||
}
|
||||
tokens[j] = Token{
|
||||
Type: ERC20TokenType,
|
||||
BalanceSat: (*Amount)(b),
|
||||
Contract: ci.Contract,
|
||||
Name: ci.Name,
|
||||
Symbol: ci.Symbol,
|
||||
Transfers: int(c.Txs),
|
||||
Decimals: ci.Decimals,
|
||||
ContractIndex: strconv.Itoa(i + 1),
|
||||
}
|
||||
tokens[j] = *t
|
||||
j++
|
||||
}
|
||||
// special handling if filter has contract
|
||||
// if the address has no transactions with given contract, check the balance, the address may have some balance even without transactions
|
||||
if len(filterDesc) > 0 && j == 0 && details >= AccountDetailsTokens {
|
||||
t, err := w.getEthereumToken(0, addrDesc, filterDesc, details, 0)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, err
|
||||
}
|
||||
tokens = []Token{*t}
|
||||
// switch off query for transactions, there are no transactions
|
||||
filter.Vout = AddressFilterVoutQueryNotNecessary
|
||||
} else {
|
||||
tokens = tokens[:j]
|
||||
}
|
||||
tokens = tokens[:j]
|
||||
}
|
||||
ci, err = w.chain.EthereumTypeGetErc20ContractInfo(addrDesc)
|
||||
if err != nil {
|
||||
|
@ -730,8 +593,6 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
totalResults = int(ca.NonContractTxs)
|
||||
} else if filter.Vout > 0 && filter.Vout-1 < len(ca.Contracts) {
|
||||
totalResults = int(ca.Contracts[filter.Vout-1].Txs)
|
||||
} else if filter.Vout == AddressFilterVoutQueryNotNecessary {
|
||||
totalResults = 0
|
||||
}
|
||||
}
|
||||
nonContractTxs = int(ca.NonContractTxs)
|
||||
|
@ -742,16 +603,6 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
BalanceSat: *b,
|
||||
}
|
||||
}
|
||||
// special handling if filtering for a contract, check the ballance of it
|
||||
if len(filterDesc) > 0 && details >= AccountDetailsTokens {
|
||||
t, err := w.getEthereumToken(0, addrDesc, filterDesc, details, 0)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, 0, err
|
||||
}
|
||||
tokens = []Token{*t}
|
||||
// switch off query for transactions, there are no transactions
|
||||
filter.Vout = AddressFilterVoutQueryNotNecessary
|
||||
}
|
||||
}
|
||||
return ba, tokens, ci, n, nonContractTxs, totalResults, nil
|
||||
}
|
||||
|
@ -768,7 +619,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, false)
|
||||
tx, err = w.GetTransaction(txid, false, true)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
||||
}
|
||||
|
@ -787,7 +638,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, false)
|
||||
tx, err = w.GetTransaction(txid, false, true)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
||||
}
|
||||
|
@ -876,7 +727,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, true)
|
||||
tx, err := w.GetTransaction(txid, false, false)
|
||||
// mempool transaction may fail
|
||||
if err != nil || tx == nil {
|
||||
glog.Warning("GetTransaction in mempool: ", err)
|
||||
|
@ -885,12 +736,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
|
|||
if tx.Confirmations == 0 {
|
||||
unconfirmedTxs++
|
||||
uBalSat.Add(&uBalSat, tx.getAddrVoutValue(addrDesc))
|
||||
// ethereum has a different logic - value not in input and add maximum possible fees
|
||||
if w.chainType == bchain.ChainEthereumType {
|
||||
uBalSat.Sub(&uBalSat, tx.getAddrEthereumTypeMempoolInputValue(addrDesc))
|
||||
} else {
|
||||
uBalSat.Sub(&uBalSat, tx.getAddrVinValue(addrDesc))
|
||||
}
|
||||
uBalSat.Sub(&uBalSat, tx.getAddrVinValue(addrDesc))
|
||||
if page == 0 {
|
||||
if option == AccountDetailsTxidHistory {
|
||||
txids = append(txids, tx.Txid)
|
||||
|
@ -903,7 +749,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
|
|||
}
|
||||
}
|
||||
// get tx history if requested by option or check mempool if there are some transactions for a new address
|
||||
if option >= AccountDetailsTxidHistory && filter.Vout != AddressFilterVoutQueryNotNecessary {
|
||||
if option >= AccountDetailsTxidHistory {
|
||||
txc, err := w.getAddressTxids(addrDesc, false, filter, (page+1)*txsOnPage)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "getAddressTxids %v false", addrDesc)
|
||||
|
@ -974,7 +820,7 @@ func (w *Worker) balanceHistoryHeightsFromTo(fromTimestamp, toTimestamp int64) (
|
|||
return fromUnix, fromHeight, toUnix, toHeight
|
||||
}
|
||||
|
||||
func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32, selfAddrDesc map[string]struct{}) (*BalanceHistory, error) {
|
||||
func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32) (*BalanceHistory, error) {
|
||||
var time uint32
|
||||
var err error
|
||||
var ta *db.TxAddresses
|
||||
|
@ -1007,30 +853,17 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
return nil, nil
|
||||
}
|
||||
bh := BalanceHistory{
|
||||
Time: time,
|
||||
Txs: 1,
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &Amount{},
|
||||
Txid: txid,
|
||||
Time: time,
|
||||
Txs: 1,
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
Txid: txid,
|
||||
}
|
||||
countSentToSelf := false
|
||||
if w.chainType == bchain.ChainBitcoinType {
|
||||
// detect if this input is the first of selfAddrDesc
|
||||
// to not to count sentToSelf multiple times if counting multiple xpub addresses
|
||||
ownInputIndex := -1
|
||||
for i := range ta.Inputs {
|
||||
tai := &ta.Inputs[i]
|
||||
if _, found := selfAddrDesc[string(tai.AddrDesc)]; found {
|
||||
if ownInputIndex < 0 {
|
||||
ownInputIndex = i
|
||||
}
|
||||
}
|
||||
if bytes.Equal(addrDesc, tai.AddrDesc) {
|
||||
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat)
|
||||
if ownInputIndex == i {
|
||||
countSentToSelf = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range ta.Outputs {
|
||||
|
@ -1038,17 +871,12 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
if bytes.Equal(addrDesc, tao.AddrDesc) {
|
||||
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat)
|
||||
}
|
||||
if countSentToSelf {
|
||||
if _, found := selfAddrDesc[string(tao.AddrDesc)]; found {
|
||||
(*big.Int)(bh.SentToSelfSat).Add((*big.Int)(bh.SentToSelfSat), &tao.ValueSat)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if w.chainType == bchain.ChainEthereumType {
|
||||
var value big.Int
|
||||
ethTxData := eth.GetEthereumTxData(bchainTx)
|
||||
// add received amount only for OK or unknown status (old) transactions
|
||||
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||
// add received amount only for OK transactions
|
||||
if ethTxData.Status == 1 {
|
||||
if len(bchainTx.Vout) > 0 {
|
||||
bchainVout := &bchainTx.Vout[0]
|
||||
value = bchainVout.ValueSat
|
||||
|
@ -1060,9 +888,6 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
if bytes.Equal(addrDesc, txAddrDesc) {
|
||||
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &value)
|
||||
}
|
||||
if _, found := selfAddrDesc[string(txAddrDesc)]; found {
|
||||
countSentToSelf = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1074,14 +899,9 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
return nil, err
|
||||
}
|
||||
if bytes.Equal(addrDesc, txAddrDesc) {
|
||||
// add received amount only for OK or unknown status (old) transactions, fees always
|
||||
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||
// add sent amount only for OK transactions, however fees always
|
||||
if ethTxData.Status == 1 {
|
||||
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &value)
|
||||
if countSentToSelf {
|
||||
if _, found := selfAddrDesc[string(txAddrDesc)]; found {
|
||||
(*big.Int)(bh.SentToSelfSat).Add((*big.Int)(bh.SentToSelfSat), &value)
|
||||
}
|
||||
}
|
||||
}
|
||||
var feesSat big.Int
|
||||
// mempool txs do not have fees yet
|
||||
|
@ -1142,9 +962,8 @@ func (w *Worker) GetBalanceHistory(address string, fromTimestamp, toTimestamp in
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selfAddrDesc := map[string]struct{}{string(addrDesc): {}}
|
||||
for txi := len(txs) - 1; txi >= 0; txi-- {
|
||||
bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix, selfAddrDesc)
|
||||
bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1774,7 +1593,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
|||
DbColumns: columnStats,
|
||||
About: Text.BlockbookAbout,
|
||||
}
|
||||
backendInfo := &common.BackendInfo{
|
||||
backendInfo := &BackendInfo{
|
||||
BackendError: backendError,
|
||||
BestBlockHash: ci.Bestblockhash,
|
||||
Blocks: ci.Blocks,
|
||||
|
@ -1787,9 +1606,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
|||
Timeoffset: ci.Timeoffset,
|
||||
Version: ci.Version,
|
||||
Warnings: ci.Warnings,
|
||||
Consensus: ci.Consensus,
|
||||
}
|
||||
w.is.SetBackendInfo(backendInfo)
|
||||
glog.Info("GetSystemInfo finished in ", time.Since(start))
|
||||
return &SystemInfo{blockbookInfo, backendInfo}, nil
|
||||
}
|
||||
|
|
14
api/xpub.go
14
api/xpub.go
|
@ -1,6 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/db"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
|
@ -9,8 +11,6 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/db"
|
||||
)
|
||||
|
||||
const defaultAddressesGap = 20
|
||||
|
@ -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, true)
|
||||
tx, err = w.GetTransaction(txid.txid, false, false)
|
||||
// mempool transaction may fail
|
||||
if err != nil || tx == nil {
|
||||
glog.Warning("GetTransaction in mempool: ", err)
|
||||
|
@ -606,18 +606,12 @@ func (w *Worker) GetXpubBalanceHistory(xpub string, fromTimestamp, toTimestamp i
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selfAddrDesc := make(map[string]struct{})
|
||||
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
||||
for i := range da {
|
||||
selfAddrDesc[string(da[i].addrDesc)] = struct{}{}
|
||||
}
|
||||
}
|
||||
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
||||
for i := range da {
|
||||
ad := &da[i]
|
||||
txids := ad.txids
|
||||
for txi := len(txids) - 1; txi >= 0; txi-- {
|
||||
bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix, selfAddrDesc)
|
||||
bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package bchain
|
|||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type addrIndex struct {
|
||||
|
@ -28,7 +27,6 @@ type BaseMempool struct {
|
|||
txEntries map[string]txEntry
|
||||
addrDescToTx map[string][]Outpoint
|
||||
OnNewTxAddr OnNewTxAddrFunc
|
||||
OnNewTx OnNewTxFunc
|
||||
}
|
||||
|
||||
// GetTransactions returns slice of mempool transactions for given address
|
||||
|
@ -115,22 +113,3 @@ func (m *BaseMempool) GetTransactionTime(txid string) uint32 {
|
|||
}
|
||||
return e.time
|
||||
}
|
||||
|
||||
func (m *BaseMempool) txToMempoolTx(tx *Tx) *MempoolTx {
|
||||
mtx := MempoolTx{
|
||||
Hex: tx.Hex,
|
||||
Blocktime: time.Now().Unix(),
|
||||
LockTime: tx.LockTime,
|
||||
Txid: tx.Txid,
|
||||
Version: tx.Version,
|
||||
Vout: tx.Vout,
|
||||
CoinSpecificData: tx.CoinSpecificData,
|
||||
}
|
||||
mtx.Vin = make([]MempoolVin, len(tx.Vin))
|
||||
for i, vin := range tx.Vin {
|
||||
mtx.Vin[i] = MempoolVin{
|
||||
Vin: vin,
|
||||
}
|
||||
}
|
||||
return &mtx
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
// BaseParser implements data parsing/handling functionality base for all other parsers
|
||||
|
@ -40,9 +39,9 @@ func (p *BaseParser) GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescri
|
|||
|
||||
const zeros = "0000000000000000000000000000000000000000"
|
||||
|
||||
// AmountToBigInt converts amount in common.JSONNumber (string) to big.Int
|
||||
// AmountToBigInt converts amount in json.Number (string) to big.Int
|
||||
// it uses string operations to avoid problems with rounding
|
||||
func (p *BaseParser) AmountToBigInt(n common.JSONNumber) (big.Int, error) {
|
||||
func (p *BaseParser) AmountToBigInt(n json.Number) (big.Int, error) {
|
||||
var r big.Int
|
||||
s := string(n)
|
||||
i := strings.IndexByte(s, '.')
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
// +build unittest
|
||||
|
||||
package bchain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
func NewBaseParser(adp int) *BaseParser {
|
||||
|
@ -47,7 +44,7 @@ func TestBaseParser_AmountToDecimalString(t *testing.T) {
|
|||
func TestBaseParser_AmountToBigInt(t *testing.T) {
|
||||
for _, tt := range amounts {
|
||||
t.Run(tt.s, func(t *testing.T) {
|
||||
got, err := NewBaseParser(tt.adp).AmountToBigInt(common.JSONNumber(tt.s))
|
||||
got, err := NewBaseParser(tt.adp).AmountToBigInt(json.Number(tt.s))
|
||||
if err != nil {
|
||||
t.Errorf("BaseParser.AmountToBigInt() error = %v", err)
|
||||
return
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"fmt"
|
||||
|
||||
"github.com/martinboehm/bchutil"
|
||||
|
@ -8,8 +10,6 @@ import (
|
|||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"github.com/martinboehm/btcutil/txscript"
|
||||
"github.com/schancel/cashaddr-converter/address"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// AddressFormat type is used to specify different formats of address
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
@ -8,8 +10,6 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/bchutil"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// BCashRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package bellcoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package bellcoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package bellcoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// BellcoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package bitcore
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,15 +3,14 @@
|
|||
package bitcore
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package bitcore
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// BitcoreRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
package bitzeny
|
||||
|
||||
import (
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
const (
|
||||
MainnetMagic wire.BitcoinNet = 0xf9bea5da
|
||||
TestnetMagic wire.BitcoinNet = 0x594e4559
|
||||
)
|
||||
|
||||
// chain parameters
|
||||
var (
|
||||
MainNetParams chaincfg.Params
|
||||
TestNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
MainNetParams = chaincfg.MainNetParams
|
||||
MainNetParams.Net = MainnetMagic
|
||||
MainNetParams.PubKeyHashAddrID = []byte{81}
|
||||
MainNetParams.ScriptHashAddrID = []byte{5}
|
||||
MainNetParams.Bech32HRPSegwit = "bz"
|
||||
|
||||
TestNetParams = chaincfg.TestNet3Params
|
||||
TestNetParams.Net = TestnetMagic
|
||||
TestNetParams.PubKeyHashAddrID = []byte{111}
|
||||
TestNetParams.ScriptHashAddrID = []byte{196}
|
||||
TestNetParams.Bech32HRPSegwit = "tz"
|
||||
}
|
||||
|
||||
// BitZenyParser handle
|
||||
type BitZenyParser struct {
|
||||
*btc.BitcoinParser
|
||||
}
|
||||
|
||||
// NewBitZenyParser returns new BitZenyParser instance
|
||||
func NewBitZenyParser(params *chaincfg.Params, c *btc.Configuration) *BitZenyParser {
|
||||
return &BitZenyParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main BitZeny network,
|
||||
// and the test BitZeny network
|
||||
func GetChainParams(chain string) *chaincfg.Params {
|
||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||
err := chaincfg.Register(&MainNetParams)
|
||||
if err == nil {
|
||||
err = chaincfg.Register(&TestNetParams)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
switch chain {
|
||||
case "test":
|
||||
return &TestNetParams
|
||||
default:
|
||||
return &MainNetParams
|
||||
}
|
||||
}
|
|
@ -1,290 +0,0 @@
|
|||
// +build unittest
|
||||
|
||||
package bitzeny
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/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
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "P2PKH1",
|
||||
args: args{address: "Zw74N1RSU2xV3a7SBERBiCP11fMwX5yvMu"},
|
||||
want: "76a914d8658ca5c406149071687d370d1d22d972d2f88488ac",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2PKH2",
|
||||
args: args{address: "ZiSn1vTSxGu2kFcnkjjm7bYGhT5BVAVfEG"},
|
||||
want: "76a9144d869697281ad18370313122795e56dfdc3a331388ac",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2SH1",
|
||||
args: args{address: "3CZ3357bm1K81StpEDQtEH3ho3ULx19nc8"},
|
||||
want: "a9147726fc1144eae1b7bd301d87d0a7f846cadb591887",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2SH2",
|
||||
args: args{address: "3M1AjZEuBzScbd9pchiGJSVT4yNfwzSmXP"},
|
||||
want: "a914d3d93b5d7f57b94a4fecde93d4489f2b423fd3c287",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "witness_v0_keyhash",
|
||||
args: args{address: "bz1q7rfrdacyyfwx8gppd8ah9hka8npgqsm44prfnd"},
|
||||
want: "0014f0d236f704225c63a02169fb72dedd3cc2804375",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "witness_v0_scripthashx",
|
||||
args: args{address: "bz1qd2mspe6m2wpztw4q2mccyvyess6569eu59sfvf0u0vdmdwltr5lse8d7sw"},
|
||||
want: "00206ab700e75b538225baa056f182309984354d173ca1609625fc7b1bb6bbeb1d3f",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
parser := NewBitZenyParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parser.GetAddrDescFromAddress(tt.args.address)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("GetAddrDescFromAddress() = %v, want %v", h, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAddressesFromAddrDesc(t *testing.T) {
|
||||
type args struct {
|
||||
script string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
want2 bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "P2PKH",
|
||||
args: args{script: "76a914d8658ca5c406149071687d370d1d22d972d2f88488ac"},
|
||||
want: []string{"Zw74N1RSU2xV3a7SBERBiCP11fMwX5yvMu"},
|
||||
want2: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2SH",
|
||||
args: args{script: "a9147726fc1144eae1b7bd301d87d0a7f846cadb591887"},
|
||||
want: []string{"3CZ3357bm1K81StpEDQtEH3ho3ULx19nc8"},
|
||||
want2: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2WPKH",
|
||||
args: args{script: "0014f0d236f704225c63a02169fb72dedd3cc2804375"},
|
||||
want: []string{"bz1q7rfrdacyyfwx8gppd8ah9hka8npgqsm44prfnd"},
|
||||
want2: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "P2WSH",
|
||||
args: args{script: "00206ab700e75b538225baa056f182309984354d173ca1609625fc7b1bb6bbeb1d3f"},
|
||||
want: []string{"bz1qd2mspe6m2wpztw4q2mccyvyess6569eu59sfvf0u0vdmdwltr5lse8d7sw"},
|
||||
want2: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "OP_RETURN ascii",
|
||||
args: args{script: "6a0461686f6a"},
|
||||
want: []string{"OP_RETURN (ahoj)"},
|
||||
want2: false,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "OP_RETURN hex",
|
||||
args: args{script: "6a072020f1686f6a20"},
|
||||
want: []string{"OP_RETURN 2020f1686f6a20"},
|
||||
want2: false,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
parser := NewBitZenyParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, _ := hex.DecodeString(tt.args.script)
|
||||
got, got2, err := parser.GetAddressesFromAddrDesc(b)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("outputScriptToAddresses() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want)
|
||||
}
|
||||
if !reflect.DeepEqual(got2, tt.want2) {
|
||||
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testTx1 bchain.Tx
|
||||
|
||||
testTxPacked1 = "001c3f1a8be6859d3e0100000001aef422fb91cd91e556966fed4121ac44017a761d71385596536bb447ae05213e000000006a47304402202341ac4297925257dc72eb418a069c45e76f7070340e27501f6308cc7eff45f802204a347915adceff5f6fc9b8075d95d47887d46b344c7bbc8066d315931b189ad001210228c2520812b7f8c63e7a088c61b6348b22fa0c98812e736a1fd896bc828d3c65feffffff028041f13d000000001976a91478379ea136bb5783b675cd11e412bf0703995aeb88aca9983141000000001976a9144d869697281ad18370313122795e56dfdc3a331388ac193f1c00"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testTx1 = bchain.Tx{
|
||||
Hex: "0100000001aef422fb91cd91e556966fed4121ac44017a761d71385596536bb447ae05213e000000006a47304402202341ac4297925257dc72eb418a069c45e76f7070340e27501f6308cc7eff45f802204a347915adceff5f6fc9b8075d95d47887d46b344c7bbc8066d315931b189ad001210228c2520812b7f8c63e7a088c61b6348b22fa0c98812e736a1fd896bc828d3c65feffffff028041f13d000000001976a91478379ea136bb5783b675cd11e412bf0703995aeb88aca9983141000000001976a9144d869697281ad18370313122795e56dfdc3a331388ac193f1c00",
|
||||
Blocktime: 1583392607,
|
||||
Txid: "f81c34b300961877328c3aaa7cd5e69068457868309fbf1e92544e3a6a915bcb",
|
||||
LockTime: 1851161,
|
||||
Version: 1,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
Hex: "47304402202341ac4297925257dc72eb418a069c45e76f7070340e27501f6308cc7eff45f802204a347915adceff5f6fc9b8075d95d47887d46b344c7bbc8066d315931b189ad001210228c2520812b7f8c63e7a088c61b6348b22fa0c98812e736a1fd896bc828d3c65",
|
||||
},
|
||||
Txid: "3e2105ae47b46b53965538711d767a0144ac2141ed6f9656e591cd91fb22f4ae",
|
||||
Vout: 0,
|
||||
Sequence: 4294967294,
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(1039221120),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a91478379ea136bb5783b675cd11e412bf0703995aeb88ac",
|
||||
Addresses: []string{
|
||||
"ZnLWULVbAzjy1TSKxGnpkomeeaEDTHk5Nj",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(1093769385),
|
||||
N: 1,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a9144d869697281ad18370313122795e56dfdc3a331388ac",
|
||||
Addresses: []string{
|
||||
"ZiSn1vTSxGu2kFcnkjjm7bYGhT5BVAVfEG",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PackTx(t *testing.T) {
|
||||
type args struct {
|
||||
tx bchain.Tx
|
||||
height uint32
|
||||
blockTime int64
|
||||
parser *BitZenyParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "BitZeny-1",
|
||||
args: args{
|
||||
tx: testTx1,
|
||||
height: 1851162,
|
||||
blockTime: 1583392607,
|
||||
parser: NewBitZenyParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked1,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("packTx() = %v, want %v", h, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_UnpackTx(t *testing.T) {
|
||||
type args struct {
|
||||
packedTx string
|
||||
parser *BitZenyParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *bchain.Tx
|
||||
want1 uint32
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "BitZeny-1",
|
||||
args: args{
|
||||
packedTx: testTxPacked1,
|
||||
parser: NewBitZenyParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx1,
|
||||
want1: 1851162,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, _ := hex.DecodeString(tt.args.packedTx)
|
||||
got, got1, err := tt.args.parser.UnpackTx(b)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("unpackTx() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if got1 != tt.want1 {
|
||||
t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package bitzeny
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// BitZenyRPC is an interface to JSON-RPC bitcoind service.
|
||||
type BitZenyRPC struct {
|
||||
*btc.BitcoinRPC
|
||||
}
|
||||
|
||||
// NewBitZenyRPC returns new BitZenyRPC instance.
|
||||
func NewBitZenyRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||
b, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &BitZenyRPC{
|
||||
b.(*btc.BitcoinRPC),
|
||||
}
|
||||
s.RPCMarshaler = btc.JSONMarshalerV2{}
|
||||
s.ChainConfig.SupportsEstimateFee = false
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Initialize initializes BitZenyRPC instance.
|
||||
func (b *BitZenyRPC) Initialize() error {
|
||||
ci, err := b.GetChainInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chainName := ci.Chain
|
||||
|
||||
glog.Info("Chain name ", chainName)
|
||||
params := GetChainParams(chainName)
|
||||
|
||||
// always create parser
|
||||
b.Parser = NewBitZenyParser(params, b.ChainConfig)
|
||||
|
||||
// parameters for getInfo request
|
||||
if params.Net == MainnetMagic {
|
||||
b.Testnet = false
|
||||
b.Network = "livenet"
|
||||
} else {
|
||||
b.Testnet = true
|
||||
b.Network = "testnet"
|
||||
}
|
||||
|
||||
glog.Info("rpc: block chain ", params.Name)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,6 +1,44 @@
|
|||
package coins
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/bch"
|
||||
"blockbook/bchain/coins/bellcoin"
|
||||
"blockbook/bchain/coins/bitcore"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/btg"
|
||||
"blockbook/bchain/coins/cpuchain"
|
||||
"blockbook/bchain/coins/dash"
|
||||
"blockbook/bchain/coins/dcr"
|
||||
"blockbook/bchain/coins/deeponion"
|
||||
"blockbook/bchain/coins/digibyte"
|
||||
"blockbook/bchain/coins/divi"
|
||||
"blockbook/bchain/coins/dogecoin"
|
||||
"blockbook/bchain/coins/eth"
|
||||
"blockbook/bchain/coins/flo"
|
||||
"blockbook/bchain/coins/fujicoin"
|
||||
"blockbook/bchain/coins/gamecredits"
|
||||
"blockbook/bchain/coins/grs"
|
||||
"blockbook/bchain/coins/koto"
|
||||
"blockbook/bchain/coins/liquid"
|
||||
"blockbook/bchain/coins/litecoin"
|
||||
"blockbook/bchain/coins/monacoin"
|
||||
"blockbook/bchain/coins/monetaryunit"
|
||||
"blockbook/bchain/coins/myriad"
|
||||
"blockbook/bchain/coins/namecoin"
|
||||
"blockbook/bchain/coins/nuls"
|
||||
"blockbook/bchain/coins/pivx"
|
||||
"blockbook/bchain/coins/polis"
|
||||
"blockbook/bchain/coins/qtum"
|
||||
"blockbook/bchain/coins/ravencoin"
|
||||
"blockbook/bchain/coins/ritocoin"
|
||||
"blockbook/bchain/coins/unobtanium"
|
||||
"blockbook/bchain/coins/vertcoin"
|
||||
"blockbook/bchain/coins/viacoin"
|
||||
"blockbook/bchain/coins/vipstarcoin"
|
||||
"blockbook/bchain/coins/xzc"
|
||||
"blockbook/bchain/coins/zec"
|
||||
"blockbook/common"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -10,48 +48,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/bch"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/bellcoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/bitcore"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/bitzeny"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/cpuchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/dash"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/dcr"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/deeponion"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/digibyte"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/divi"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/dogecoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/firo"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/flo"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/fujicoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/gamecredits"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/grs"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/koto"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/liquid"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/litecoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/monacoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/monetaryunit"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/myriad"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/namecoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/nuls"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/omotenashicoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/pivx"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/polis"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/qtum"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/ravencoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/ritocoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/snowgem"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/trezarcoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/unobtanium"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/vertcoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/viacoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/vipstarcoin"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/zec"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
type blockChainFactory func(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error)
|
||||
|
@ -62,17 +58,14 @@ var BlockChainFactories = make(map[string]blockChainFactory)
|
|||
func init() {
|
||||
BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC
|
||||
BlockChainFactories["Testnet"] = btc.NewBitcoinRPC
|
||||
BlockChainFactories["Signet"] = btc.NewBitcoinRPC
|
||||
BlockChainFactories["Zcash"] = zec.NewZCashRPC
|
||||
BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC
|
||||
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
|
||||
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
|
||||
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
|
||||
BlockChainFactories["Ethereum Testnet Goerli"] = eth.NewEthereumRPC
|
||||
BlockChainFactories["Bcash"] = bch.NewBCashRPC
|
||||
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
|
||||
BlockChainFactories["Bgold"] = btg.NewBGoldRPC
|
||||
BlockChainFactories["Bgold Testnet"] = btg.NewBGoldRPC
|
||||
BlockChainFactories["Dash"] = dash.NewDashRPC
|
||||
BlockChainFactories["Dash Testnet"] = dash.NewDashRPC
|
||||
BlockChainFactories["Decred"] = dcr.NewDecredRPC
|
||||
|
@ -90,7 +83,6 @@ func init() {
|
|||
BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC
|
||||
BlockChainFactories["MonetaryUnit"] = monetaryunit.NewMonetaryUnitRPC
|
||||
BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC
|
||||
BlockChainFactories["DigiByte Testnet"] = digibyte.NewDigiByteRPC
|
||||
BlockChainFactories["Myriad"] = myriad.NewMyriadRPC
|
||||
BlockChainFactories["Liquid"] = liquid.NewLiquidRPC
|
||||
BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC
|
||||
|
@ -98,7 +90,7 @@ func init() {
|
|||
BlockChainFactories["PIVX"] = pivx.NewPivXRPC
|
||||
BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC
|
||||
BlockChainFactories["Polis"] = polis.NewPolisRPC
|
||||
BlockChainFactories["Firo"] = firo.NewFiroRPC
|
||||
BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC
|
||||
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
|
||||
BlockChainFactories["Flo"] = flo.NewFloRPC
|
||||
BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC
|
||||
|
@ -114,12 +106,7 @@ func init() {
|
|||
BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC
|
||||
BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC
|
||||
BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC
|
||||
BlockChainFactories["SnowGem"] = snowgem.NewSnowGemRPC
|
||||
BlockChainFactories["Bitcore"] = bitcore.NewBitcoreRPC
|
||||
BlockChainFactories["Omotenashicoin"] = omotenashicoin.NewOmotenashiCoinRPC
|
||||
BlockChainFactories["Omotenashicoin Testnet"] = omotenashicoin.NewOmotenashiCoinRPC
|
||||
BlockChainFactories["BitZeny"] = bitzeny.NewBitZenyRPC
|
||||
BlockChainFactories["Trezarcoin"] = trezarcoin.NewTrezarcoinRPC
|
||||
}
|
||||
|
||||
// GetCoinNameFromConfig gets coin name and coin shortcut from config file
|
||||
|
@ -191,8 +178,8 @@ func (c *blockChainWithMetrics) CreateMempool(chain bchain.BlockChain) (bchain.M
|
|||
return c.b.CreateMempool(chain)
|
||||
}
|
||||
|
||||
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr, onNewTx)
|
||||
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
|
||||
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr)
|
||||
}
|
||||
|
||||
func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
@ -15,25 +16,8 @@ import (
|
|||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"github.com/martinboehm/btcutil/hdkeychain"
|
||||
"github.com/martinboehm/btcutil/txscript"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
// temp params for signet(wait btcd commit)
|
||||
// magic numbers
|
||||
const (
|
||||
SignetMagic wire.BitcoinNet = 0x6a70c7f0
|
||||
)
|
||||
|
||||
// chain parameters
|
||||
var (
|
||||
SigNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
SigNetParams = chaincfg.TestNet3Params
|
||||
SigNetParams.Net = SignetMagic
|
||||
}
|
||||
|
||||
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
|
||||
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
|
||||
|
||||
|
@ -79,8 +63,6 @@ func GetChainParams(chain string) *chaincfg.Params {
|
|||
return &chaincfg.TestNet3Params
|
||||
case "regtest":
|
||||
return &chaincfg.RegressionNetParams
|
||||
case "signet":
|
||||
return &SigNetParams
|
||||
}
|
||||
return &chaincfg.MainNetParams
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,7 +11,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -259,11 +259,10 @@ func TestGetAddressesFromAddrDesc(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
testTx1, testTx2, testTx3 bchain.Tx
|
||||
testTx1, testTx2 bchain.Tx
|
||||
|
||||
testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700"
|
||||
testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000"
|
||||
testTxPacked3 = "00003d818bfda9aa3e02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -336,54 +335,6 @@ func init() {
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
testTx3 = bchain.Tx{
|
||||
Hex: "02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000",
|
||||
Blocktime: 1607805599,
|
||||
Txid: "24551a58a1d1fb89d7052e2bbac7cb69a7825ee1e39439befbec8c32148cf735",
|
||||
LockTime: 15745,
|
||||
Version: 2,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
Hex: "",
|
||||
},
|
||||
Txid: "9d8b6a98d942ce077574fff2e5dd9e405ba75ed9fb126b3da1b07a859a99b1de",
|
||||
Vout: 0,
|
||||
Sequence: 4294967293,
|
||||
},
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
Hex: "",
|
||||
},
|
||||
Txid: "98227ffe94726bc77c3c587e1e5375305beffb8e43a6eb75233b201e36d3d29f",
|
||||
Vout: 0,
|
||||
Sequence: 4294967293,
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(100000),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "00148091746745464e7555c31e9a5afceac14a02978a",
|
||||
Addresses: []string{
|
||||
"tb1qszghge69ge8824wrr6d94l82c99q99u2ccgv5w",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(1899751),
|
||||
N: 1,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "0014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e",
|
||||
Addresses: []string{
|
||||
"tb1q2e02nl6938f7qkapfxhxufth22lac2s792vsxp",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackTx(t *testing.T) {
|
||||
|
@ -421,17 +372,6 @@ func TestPackTx(t *testing.T) {
|
|||
want: testTxPacked2,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "signet-1",
|
||||
args: args{
|
||||
tx: testTx3,
|
||||
height: 15745,
|
||||
blockTime: 1607805599,
|
||||
parser: NewBitcoinParser(GetChainParams("signet"), &Configuration{}),
|
||||
},
|
||||
want: testTxPacked3,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -480,16 +420,6 @@ func TestUnpackTx(t *testing.T) {
|
|||
want1: 510234,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "signet-1",
|
||||
args: args{
|
||||
packedTx: testTxPacked3,
|
||||
parser: NewBitcoinParser(GetChainParams("signet"), &Configuration{}),
|
||||
},
|
||||
want: &testTx3,
|
||||
want1: 15745,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
@ -16,8 +17,6 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
// BitcoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
@ -155,13 +154,12 @@ func (b *BitcoinRPC) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, err
|
|||
}
|
||||
|
||||
// InitializeMempool creates ZeroMQ subscription and sets AddrDescForOutpointFunc to the Mempool
|
||||
func (b *BitcoinRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||
func (b *BitcoinRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
|
||||
if b.Mempool == nil {
|
||||
return errors.New("Mempool not created")
|
||||
}
|
||||
b.Mempool.AddrDescForOutpoint = addrDescForOutpoint
|
||||
b.Mempool.OnNewTxAddr = onNewTxAddr
|
||||
b.Mempool.OnNewTx = onNewTx
|
||||
if b.mq == nil {
|
||||
mq, err := bchain.NewMQ(b.ChainConfig.MessageQueueBinding, b.pushHandler)
|
||||
if err != nil {
|
||||
|
@ -239,13 +237,13 @@ type CmdGetBlockChainInfo struct {
|
|||
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"`
|
||||
SizeOnDisk int64 `json:"size_on_disk"`
|
||||
Warnings string `json:"warnings"`
|
||||
Chain string `json:"chain"`
|
||||
Blocks int `json:"blocks"`
|
||||
Headers int `json:"headers"`
|
||||
Bestblockhash string `json:"bestblockhash"`
|
||||
Difficulty json.Number `json:"difficulty"`
|
||||
SizeOnDisk int64 `json:"size_on_disk"`
|
||||
Warnings string `json:"warnings"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -258,11 +256,11 @@ type CmdGetNetworkInfo struct {
|
|||
type ResGetNetworkInfo struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result struct {
|
||||
Version common.JSONNumber `json:"version"`
|
||||
Subversion common.JSONNumber `json:"subversion"`
|
||||
ProtocolVersion common.JSONNumber `json:"protocolversion"`
|
||||
Timeoffset float64 `json:"timeoffset"`
|
||||
Warnings string `json:"warnings"`
|
||||
Version json.Number `json:"version"`
|
||||
Subversion json.Number `json:"subversion"`
|
||||
ProtocolVersion json.Number `json:"protocolversion"`
|
||||
Timeoffset float64 `json:"timeoffset"`
|
||||
Warnings string `json:"warnings"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -360,8 +358,8 @@ type CmdEstimateSmartFee struct {
|
|||
type ResEstimateSmartFee struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result struct {
|
||||
Feerate common.JSONNumber `json:"feerate"`
|
||||
Blocks int `json:"blocks"`
|
||||
Feerate json.Number `json:"feerate"`
|
||||
Blocks int `json:"blocks"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -375,8 +373,8 @@ type CmdEstimateFee struct {
|
|||
}
|
||||
|
||||
type ResEstimateFee struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result common.JSONNumber `json:"result"`
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result json.Number `json:"result"`
|
||||
}
|
||||
|
||||
// sendrawtransaction
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -11,8 +12,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
// https://whatthefee.io returns
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package btg
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
@ -8,9 +11,6 @@ import (
|
|||
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package btg
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -12,7 +13,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package btg
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// BGoldRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package cpuchain
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package cpuchain
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// CPUchainRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package dash
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// +build unittest
|
||||
// build unittest
|
||||
|
||||
package dash
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -11,9 +13,6 @@ import (
|
|||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
type testBlock struct {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package dash
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const firstBlockWithSpecialTransactions = 1028160
|
||||
|
|
|
@ -9,19 +9,18 @@ import (
|
|||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
|
||||
cfg "github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
cfg "github.com/decred/dcrd/chaincfg/v3"
|
||||
"github.com/decred/dcrd/dcrec"
|
||||
"github.com/decred/dcrd/dcrutil/v3"
|
||||
"github.com/decred/dcrd/hdkeychain/v3"
|
||||
"github.com/decred/dcrd/txscript/v3"
|
||||
"github.com/decred/dcrd/hdkeychain"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/base58"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -66,9 +65,9 @@ func NewDecredParser(params *chaincfg.Params, c *btc.Configuration) *DecredParse
|
|||
|
||||
switch d.BitcoinParser.Params.Name {
|
||||
case "testnet3":
|
||||
d.netConfig = cfg.TestNet3Params()
|
||||
d.netConfig = &cfg.TestNet3Params
|
||||
default:
|
||||
d.netConfig = cfg.MainNetParams()
|
||||
d.netConfig = &cfg.MainNetParams
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
@ -204,10 +203,7 @@ func (p *DecredParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressD
|
|||
return nil, err
|
||||
}
|
||||
|
||||
const scriptVersion = 0
|
||||
const treasuryEnabled = true
|
||||
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(scriptVersion, script,
|
||||
p.netConfig, treasuryEnabled)
|
||||
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(txscript.DefaultScriptVersion, script, p.netConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -245,9 +241,7 @@ func (p *DecredParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|||
}
|
||||
|
||||
func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
|
||||
pk := extKey.SerializedPubKey()
|
||||
hash := dcrutil.Hash160(pk)
|
||||
addr, err := dcrutil.NewAddressPubKeyHash(hash, p.netConfig, dcrec.STEcdsaSecp256k1)
|
||||
var addr, err = extKey.Address(p.netConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -258,7 +252,7 @@ func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchai
|
|||
// listed indexes
|
||||
func (p *DecredParser) DeriveAddressDescriptors(xpub string, change uint32,
|
||||
indexes []uint32) ([]bchain.AddressDescriptor, error) {
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -289,7 +283,7 @@ func (p *DecredParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32
|
|||
if toIndex <= fromIndex {
|
||||
return nil, errors.New("toIndex<=fromIndex")
|
||||
}
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
package dcr
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dcr
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -15,12 +16,11 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
// voteBitYes defines the vote bit set when a given block validates the previous
|
||||
|
@ -168,61 +168,61 @@ type GetBlockHashResult struct {
|
|||
type GetBlockResult struct {
|
||||
Error Error `json:"error"`
|
||||
Result struct {
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
Size int32 `json:"size"`
|
||||
Height uint32 `json:"height"`
|
||||
Version common.JSONNumber `json:"version"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
StakeRoot string `json:"stakeroot"`
|
||||
RawTx []RawTx `json:"rawtx"`
|
||||
Tx []string `json:"tx,omitempty"`
|
||||
STx []string `json:"stx,omitempty"`
|
||||
Time int64 `json:"time"`
|
||||
Nonce common.JSONNumber `json:"nonce"`
|
||||
VoteBits uint16 `json:"votebits"`
|
||||
FinalState string `json:"finalstate"`
|
||||
Voters uint16 `json:"voters"`
|
||||
FreshStake uint8 `json:"freshstake"`
|
||||
Revocations uint8 `json:"revocations"`
|
||||
PoolSize uint32 `json:"poolsize"`
|
||||
Bits string `json:"bits"`
|
||||
SBits float64 `json:"sbits"`
|
||||
ExtraData string `json:"extradata"`
|
||||
StakeVersion uint32 `json:"stakeversion"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
ChainWork string `json:"chainwork"`
|
||||
PreviousHash string `json:"previousblockhash"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
Size int32 `json:"size"`
|
||||
Height uint32 `json:"height"`
|
||||
Version json.Number `json:"version"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
StakeRoot string `json:"stakeroot"`
|
||||
RawTx []RawTx `json:"rawtx"`
|
||||
Tx []string `json:"tx,omitempty"`
|
||||
STx []string `json:"stx,omitempty"`
|
||||
Time int64 `json:"time"`
|
||||
Nonce json.Number `json:"nonce"`
|
||||
VoteBits uint16 `json:"votebits"`
|
||||
FinalState string `json:"finalstate"`
|
||||
Voters uint16 `json:"voters"`
|
||||
FreshStake uint8 `json:"freshstake"`
|
||||
Revocations uint8 `json:"revocations"`
|
||||
PoolSize uint32 `json:"poolsize"`
|
||||
Bits string `json:"bits"`
|
||||
SBits float64 `json:"sbits"`
|
||||
ExtraData string `json:"extradata"`
|
||||
StakeVersion uint32 `json:"stakeversion"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
ChainWork string `json:"chainwork"`
|
||||
PreviousHash string `json:"previousblockhash"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
type GetBlockHeaderResult struct {
|
||||
Error Error `json:"error"`
|
||||
Result struct {
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
Version common.JSONNumber `json:"version"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
StakeRoot string `json:"stakeroot"`
|
||||
VoteBits uint16 `json:"votebits"`
|
||||
FinalState string `json:"finalstate"`
|
||||
Voters uint16 `json:"voters"`
|
||||
FreshStake uint8 `json:"freshstake"`
|
||||
Revocations uint8 `json:"revocations"`
|
||||
PoolSize uint32 `json:"poolsize"`
|
||||
Bits string `json:"bits"`
|
||||
SBits float64 `json:"sbits"`
|
||||
Height uint32 `json:"height"`
|
||||
Size uint32 `json:"size"`
|
||||
Time int64 `json:"time"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
ExtraData string `json:"extradata"`
|
||||
StakeVersion uint32 `json:"stakeversion"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
ChainWork string `json:"chainwork"`
|
||||
PreviousHash string `json:"previousblockhash,omitempty"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
Version json.Number `json:"version"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
StakeRoot string `json:"stakeroot"`
|
||||
VoteBits uint16 `json:"votebits"`
|
||||
FinalState string `json:"finalstate"`
|
||||
Voters uint16 `json:"voters"`
|
||||
FreshStake uint8 `json:"freshstake"`
|
||||
Revocations uint8 `json:"revocations"`
|
||||
PoolSize uint32 `json:"poolsize"`
|
||||
Bits string `json:"bits"`
|
||||
SBits float64 `json:"sbits"`
|
||||
Height uint32 `json:"height"`
|
||||
Size uint32 `json:"size"`
|
||||
Time int64 `json:"time"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
ExtraData string `json:"extradata"`
|
||||
StakeVersion uint32 `json:"stakeversion"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
ChainWork string `json:"chainwork"`
|
||||
PreviousHash string `json:"previousblockhash,omitempty"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -297,8 +297,8 @@ type EstimateSmartFeeResult struct {
|
|||
}
|
||||
|
||||
type EstimateFeeResult struct {
|
||||
Error Error `json:"error"`
|
||||
Result common.JSONNumber `json:"result"`
|
||||
Error Error `json:"error"`
|
||||
Result json.Number `json:"result"`
|
||||
}
|
||||
|
||||
type SendRawTransactionResult struct {
|
||||
|
@ -637,7 +637,7 @@ func (d *DecredRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
|||
Version: block.Result.Version,
|
||||
Nonce: block.Result.Nonce,
|
||||
Bits: block.Result.Bits,
|
||||
Difficulty: common.JSONNumber(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
|
||||
Difficulty: json.Number(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
|
||||
Txids: block.Result.Tx,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package deeponion
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package deeponion
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package deeponion
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// DeepOnionRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
package digibyte
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const (
|
||||
// MainnetMagic is mainnet network constant
|
||||
MainnetMagic wire.BitcoinNet = 0xdab6c3fa
|
||||
TestnetMagic wire.BitcoinNet = 0xddbdc8fd
|
||||
)
|
||||
|
||||
var (
|
||||
// MainNetParams are parser parameters for mainnet
|
||||
MainNetParams chaincfg.Params
|
||||
TestNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -24,12 +23,6 @@ func init() {
|
|||
MainNetParams.PubKeyHashAddrID = []byte{30}
|
||||
MainNetParams.ScriptHashAddrID = []byte{63}
|
||||
MainNetParams.Bech32HRPSegwit = "dgb"
|
||||
|
||||
TestNetParams = chaincfg.TestNet3Params
|
||||
TestNetParams.Net = TestnetMagic
|
||||
TestNetParams.PubKeyHashAddrID = []byte{126}
|
||||
TestNetParams.ScriptHashAddrID = []byte{140}
|
||||
TestNetParams.Bech32HRPSegwit = "dgbt"
|
||||
}
|
||||
|
||||
// DigiByteParser handle
|
||||
|
@ -37,27 +30,18 @@ type DigiByteParser struct {
|
|||
*btc.BitcoinParser
|
||||
}
|
||||
|
||||
// NewDigiByteParser returns new DigiByteParser instance
|
||||
// NewDigiByteParser returns new VertcoinParser instance
|
||||
func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser {
|
||||
return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main DigiByte network
|
||||
// and the DigiByte Testnet network
|
||||
func GetChainParams(chain string) *chaincfg.Params {
|
||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||
err := chaincfg.Register(&MainNetParams)
|
||||
if err == nil {
|
||||
err = chaincfg.Register(&TestNetParams)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
switch chain {
|
||||
case "test":
|
||||
return &TestNetParams
|
||||
default:
|
||||
return &MainNetParams
|
||||
}
|
||||
return &MainNetParams
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package digibyte
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package digibyte
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// DigiByteRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"math/big"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -14,8 +16,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// DivicoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package dogecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package dogecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -14,8 +16,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package dogecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// DogecoinRPC is an interface to JSON-RPC dogecoind service.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
@ -12,7 +13,6 @@ import (
|
|||
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
var erc20abi = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x06fdde03"},
|
||||
|
@ -145,26 +145,24 @@ func parseErc20StringProperty(contractDesc bchain.AddressDescriptor, data string
|
|||
n := parseErc20NumericProperty(contractDesc, data[64:128])
|
||||
if n != nil {
|
||||
l := n.Uint64()
|
||||
if l > 0 && 2*int(l) <= len(data)-128 {
|
||||
if 2*int(l) <= len(data)-128 {
|
||||
b, err := hex.DecodeString(data[128 : 128+2*l])
|
||||
if err == nil {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// allow string properties as UTF-8 data
|
||||
b, err := hex.DecodeString(data)
|
||||
if err == nil {
|
||||
i := bytes.Index(b, []byte{0})
|
||||
if i > 32 {
|
||||
i = 32
|
||||
}
|
||||
if i > 0 {
|
||||
b = b[:i]
|
||||
}
|
||||
if utf8.Valid(b) {
|
||||
return string(b)
|
||||
} else if len(data) == 64 {
|
||||
// allow string properties as 32 bytes of UTF-8 data
|
||||
b, err := hex.DecodeString(data)
|
||||
if err == nil {
|
||||
i := bytes.Index(b, []byte{0})
|
||||
if i > 0 {
|
||||
b = b[:i]
|
||||
}
|
||||
if utf8.Valid(b) {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
if glog.V(1) {
|
||||
|
@ -183,26 +181,18 @@ func (b *EthereumRPC) EthereumTypeGetErc20ContractInfo(contractDesc bchain.Addre
|
|||
address := EIP55Address(contractDesc)
|
||||
data, err := b.ethCall(erc20NameSignature, address)
|
||||
if err != nil {
|
||||
// ignore the error from the eth_call - since geth v1.9.15 they changed the behavior
|
||||
// and returning error "execution reverted" for some non contract addresses
|
||||
// https://github.com/ethereum/go-ethereum/issues/21249#issuecomment-648647672
|
||||
glog.Warning(errors.Annotatef(err, "erc20NameSignature %v", address))
|
||||
return nil, nil
|
||||
// return nil, errors.Annotatef(err, "erc20NameSignature %v", address)
|
||||
return nil, err
|
||||
}
|
||||
name := parseErc20StringProperty(contractDesc, data)
|
||||
if name != "" {
|
||||
data, err = b.ethCall(erc20SymbolSignature, address)
|
||||
if err != nil {
|
||||
glog.Warning(errors.Annotatef(err, "erc20SymbolSignature %v", address))
|
||||
return nil, nil
|
||||
// return nil, errors.Annotatef(err, "erc20SymbolSignature %v", address)
|
||||
return nil, err
|
||||
}
|
||||
symbol := parseErc20StringProperty(contractDesc, data)
|
||||
data, err = b.ethCall(erc20DecimalsSignature, address)
|
||||
if err != nil {
|
||||
glog.Warning(errors.Annotatef(err, "erc20DecimalsSignature %v", address))
|
||||
// return nil, errors.Annotatef(err, "erc20DecimalsSignature %v", address)
|
||||
return nil, err
|
||||
}
|
||||
contract = &bchain.Erc20Contract{
|
||||
Contract: address,
|
||||
|
|
|
@ -3,13 +3,12 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"blockbook/bchain"
|
||||
"blockbook/tests/dbtestdata"
|
||||
fmt "fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
|
||||
)
|
||||
|
||||
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
|
||||
|
@ -139,16 +138,6 @@ func TestErc20_parseErc20StringProperty(t *testing.T) {
|
|||
args: "0x44616920537461626c65636f696e2076312e3020444444444444444444444444",
|
||||
want: "Dai Stablecoin v1.0 DDDDDDDDDDDD",
|
||||
},
|
||||
{
|
||||
name: "long",
|
||||
args: "0x556e6973776170205631000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
want: "Uniswap V1",
|
||||
},
|
||||
{
|
||||
name: "garbage",
|
||||
args: "0x2234880850896048596206002535425366538144616734015984380565810000",
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
@ -8,7 +9,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
|
@ -76,6 +76,12 @@ type rpcReceipt struct {
|
|||
Logs []*rpcLog `json:"logs"`
|
||||
}
|
||||
|
||||
type rpcEtcReceipt struct {
|
||||
GasUsed string `json:"gasUsed"`
|
||||
Status int `json:"status"`
|
||||
Logs []*rpcLog `json:"logs"`
|
||||
}
|
||||
|
||||
type completeTransaction struct {
|
||||
Tx *rpcTransaction `json:"tx"`
|
||||
Receipt *rpcReceipt `json:"receipt,omitempty"`
|
||||
|
@ -96,31 +102,18 @@ func ethNumber(n string) (int64, error) {
|
|||
return 0, errors.Errorf("Not a number: '%v'", n)
|
||||
}
|
||||
|
||||
func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, receipt *rpcReceipt, blocktime int64, confirmations uint32, fixEIP55 bool) (*bchain.Tx, error) {
|
||||
func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, receipt *rpcReceipt, blocktime int64, confirmations uint32) (*bchain.Tx, error) {
|
||||
txid := tx.Hash
|
||||
var (
|
||||
fa, ta []string
|
||||
err error
|
||||
)
|
||||
if len(tx.From) > 2 {
|
||||
if fixEIP55 {
|
||||
tx.From = EIP55AddressFromAddress(tx.From)
|
||||
}
|
||||
fa = []string{tx.From}
|
||||
}
|
||||
if len(tx.To) > 2 {
|
||||
if fixEIP55 {
|
||||
tx.To = EIP55AddressFromAddress(tx.To)
|
||||
}
|
||||
ta = []string{tx.To}
|
||||
}
|
||||
if fixEIP55 && receipt != nil && receipt.Logs != nil {
|
||||
for _, l := range receipt.Logs {
|
||||
if len(l.Address) > 2 {
|
||||
l.Address = EIP55AddressFromAddress(l.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
ct := completeTransaction{
|
||||
Tx: tx,
|
||||
Receipt: receipt,
|
||||
|
@ -211,9 +204,6 @@ func EIP55Address(addrDesc bchain.AddressDescriptor) string {
|
|||
|
||||
// EIP55AddressFromAddress returns an EIP55-compliant hex string representation of the address
|
||||
func EIP55AddressFromAddress(address string) string {
|
||||
if has0xPrefix(address) {
|
||||
address = address[2:]
|
||||
}
|
||||
b, err := hex.DecodeString(address)
|
||||
if err != nil {
|
||||
return address
|
||||
|
@ -311,14 +301,8 @@ 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 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'}
|
||||
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
|
||||
return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status)
|
||||
}
|
||||
ptLogs := make([]*ProtoCompleteTransaction_ReceiptType_LogType, len(r.Receipt.Logs))
|
||||
for i, l := range r.Receipt.Logs {
|
||||
|
@ -385,18 +369,13 @@ 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: status,
|
||||
Status: hexEncodeBig(pt.Receipt.Status),
|
||||
Logs: logs,
|
||||
}
|
||||
}
|
||||
tx, err := p.ethTxToTx(&rt, rr, int64(pt.BlockTime), 0, false)
|
||||
tx, err := p.ethTxToTx(&rt, rr, int64(pt.BlockTime), 0)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -472,51 +451,40 @@ func (p *EthereumParser) EthereumTypeGetErc20FromTx(tx *bchain.Tx) ([]bchain.Erc
|
|||
return r, nil
|
||||
}
|
||||
|
||||
// TxStatus is status of transaction
|
||||
type TxStatus int
|
||||
|
||||
// statuses of transaction
|
||||
const (
|
||||
TxStatusUnknown = TxStatus(iota - 2)
|
||||
TxStatusPending
|
||||
TxStatusFailure
|
||||
TxStatusOK
|
||||
txStatusUnknown = iota - 2
|
||||
txStatusPending
|
||||
txStatusFailure
|
||||
txStatusOK
|
||||
)
|
||||
|
||||
// EthereumTxData contains ethereum specific transaction data
|
||||
type EthereumTxData struct {
|
||||
Status TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending, -2 unknown
|
||||
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending, -2 unknown
|
||||
Nonce uint64 `json:"nonce"`
|
||||
GasLimit *big.Int `json:"gaslimit"`
|
||||
GasUsed *big.Int `json:"gasused"`
|
||||
GasPrice *big.Int `json:"gasprice"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// GetEthereumTxData returns EthereumTxData from bchain.Tx
|
||||
func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData {
|
||||
return GetEthereumTxDataFromSpecificData(tx.CoinSpecificData)
|
||||
}
|
||||
|
||||
// GetEthereumTxDataFromSpecificData returns EthereumTxData from coinSpecificData
|
||||
func GetEthereumTxDataFromSpecificData(coinSpecificData interface{}) *EthereumTxData {
|
||||
etd := EthereumTxData{Status: TxStatusPending}
|
||||
csd, ok := coinSpecificData.(completeTransaction)
|
||||
etd := EthereumTxData{Status: txStatusPending}
|
||||
csd, ok := tx.CoinSpecificData.(completeTransaction)
|
||||
if ok {
|
||||
if csd.Tx != nil {
|
||||
etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce)
|
||||
etd.GasLimit, _ = hexutil.DecodeBig(csd.Tx.GasLimit)
|
||||
etd.GasPrice, _ = hexutil.DecodeBig(csd.Tx.GasPrice)
|
||||
etd.Data = csd.Tx.Payload
|
||||
}
|
||||
if csd.Receipt != nil {
|
||||
switch csd.Receipt.Status {
|
||||
case "0x1":
|
||||
etd.Status = TxStatusOK
|
||||
etd.Status = txStatusOK
|
||||
case "": // old transactions did not set status
|
||||
etd.Status = TxStatusUnknown
|
||||
etd.Status = txStatusUnknown
|
||||
default:
|
||||
etd.Status = TxStatusFailure
|
||||
etd.Status = txStatusFailure
|
||||
}
|
||||
etd.GasUsed, _ = hexutil.DecodeBig(csd.Receipt.GasUsed)
|
||||
}
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/tests/dbtestdata"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
|
||||
)
|
||||
|
||||
func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
|
||||
|
@ -68,7 +67,7 @@ func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var testTx1, testTx2, testTx1Failed, testTx1NoStatus bchain.Tx
|
||||
var testTx1, testTx2 bchain.Tx
|
||||
|
||||
func init() {
|
||||
|
||||
|
@ -156,83 +155,6 @@ 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) {
|
||||
|
@ -266,24 +188,6 @@ 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 {
|
||||
|
@ -325,18 +229,6 @@ 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 {
|
||||
|
@ -373,30 +265,3 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthereumParser_GetEthereumTxData(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
tx *bchain.Tx
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "Test empty data",
|
||||
tx: &testTx1,
|
||||
want: "0x",
|
||||
},
|
||||
{
|
||||
name: "Test non empty data",
|
||||
tx: &testTx2,
|
||||
want: "0xa9059cbb000000000000000000000000555ee11fbddc0e49a9bab358a8941ad95ffdb48f00000000000000000000000000000000000000000000021e19e0c9bab2400000",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := GetEthereumTxData(tt.tx)
|
||||
if got.Data != tt.want {
|
||||
t.Errorf("EthereumParser.GetEthereumTxData() = %v, want %v", got.Data, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -11,14 +12,11 @@ import (
|
|||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
// EthereumNet type specifies the type of ethereum network
|
||||
|
@ -29,8 +27,6 @@ const (
|
|||
MainNet EthereumNet = 1
|
||||
// TestNet is Ropsten test network
|
||||
TestNet EthereumNet = 3
|
||||
// TestNetGoerli is Goerli test network
|
||||
TestNetGoerli EthereumNet = 5
|
||||
)
|
||||
|
||||
// Configuration represents json config file
|
||||
|
@ -61,6 +57,7 @@ type EthereumRPC struct {
|
|||
chanNewTx chan ethcommon.Hash
|
||||
newTxSubscription *rpc.ClientSubscription
|
||||
ChainConfig *Configuration
|
||||
isETC bool
|
||||
}
|
||||
|
||||
// NewEthereumRPC returns new EthRPC instance.
|
||||
|
@ -92,6 +89,9 @@ func NewEthereumRPC(config json.RawMessage, pushHandler func(bchain.Notification
|
|||
s.Parser = NewEthereumParser(c.BlockAddressesToKeep)
|
||||
s.timeout = time.Duration(c.RPCTimeout) * time.Second
|
||||
|
||||
// detect ethereum classic
|
||||
s.isETC = s.ChainConfig.CoinName == "Ethereum Classic"
|
||||
|
||||
// new blocks notifications handling
|
||||
// the subscription is done in Initialize
|
||||
s.chanNewBlock = make(chan *ethtypes.Header)
|
||||
|
@ -162,9 +162,6 @@ func (b *EthereumRPC) Initialize() error {
|
|||
b.Testnet = true
|
||||
b.Network = "testnet"
|
||||
break
|
||||
case TestNetGoerli:
|
||||
b.Testnet = true
|
||||
b.Network = "goerli"
|
||||
default:
|
||||
return errors.Errorf("Unknown network id %v", id)
|
||||
}
|
||||
|
@ -183,7 +180,7 @@ func (b *EthereumRPC) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, er
|
|||
}
|
||||
|
||||
// InitializeMempool creates subscriptions to newHeads and newPendingTransactions
|
||||
func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||
func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
|
||||
if b.Mempool == nil {
|
||||
return errors.New("Mempool not created")
|
||||
}
|
||||
|
@ -198,7 +195,6 @@ func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOu
|
|||
}
|
||||
|
||||
b.Mempool.OnNewTxAddr = onNewTxAddr
|
||||
b.Mempool.OnNewTx = onNewTx
|
||||
|
||||
if err = b.subscribeEvents(); err != nil {
|
||||
return err
|
||||
|
@ -210,21 +206,25 @@ func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOu
|
|||
}
|
||||
|
||||
func (b *EthereumRPC) subscribeEvents() error {
|
||||
// subscriptions
|
||||
if err := b.subscribe(func() (*rpc.ClientSubscription, error) {
|
||||
// invalidate the previous subscription - it is either the first one or there was an error
|
||||
b.newBlockSubscription = nil
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||
defer cancel()
|
||||
sub, err := b.rpc.EthSubscribe(ctx, b.chanNewBlock, "newHeads")
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "EthSubscribe newHeads")
|
||||
if b.isETC {
|
||||
glog.Info(b.ChainConfig.CoinName, " does not support subscription to newHeads")
|
||||
} else {
|
||||
// subscriptions
|
||||
if err := b.subscribe(func() (*rpc.ClientSubscription, error) {
|
||||
// invalidate the previous subscription - it is either the first one or there was an error
|
||||
b.newBlockSubscription = nil
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||
defer cancel()
|
||||
sub, err := b.rpc.EthSubscribe(ctx, b.chanNewBlock, "newHeads")
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "EthSubscribe newHeads")
|
||||
}
|
||||
b.newBlockSubscription = sub
|
||||
glog.Info("Subscribed to newHeads")
|
||||
return sub, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
b.newBlockSubscription = sub
|
||||
glog.Info("Subscribed to newHeads")
|
||||
return sub, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := b.subscribe(func() (*rpc.ClientSubscription, error) {
|
||||
|
@ -340,15 +340,19 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ver string
|
||||
var ver, protocol string
|
||||
if err := b.rpc.CallContext(ctx, &ver, "web3_clientVersion"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := b.rpc.CallContext(ctx, &protocol, "eth_protocolVersion"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rv := &bchain.ChainInfo{
|
||||
Blocks: int(h.Number.Int64()),
|
||||
Bestblockhash: h.Hash().Hex(),
|
||||
Difficulty: h.Difficulty.String(),
|
||||
Version: ver,
|
||||
Blocks: int(h.Number.Int64()),
|
||||
Bestblockhash: h.Hash().Hex(),
|
||||
Difficulty: h.Difficulty.String(),
|
||||
Version: ver,
|
||||
ProtocolVersion: protocol,
|
||||
}
|
||||
idi := int(id.Uint64())
|
||||
if idi == 1 {
|
||||
|
@ -362,6 +366,12 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
|
|||
func (b *EthereumRPC) getBestHeader() (*ethtypes.Header, error) {
|
||||
b.bestHeaderLock.Lock()
|
||||
defer b.bestHeaderLock.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 the best header was not updated for 15 minutes, there could be a subscription problem, reconnect RPC
|
||||
// do it only in case of normal operation, not initial synchronization
|
||||
if b.bestHeaderTime.Add(15*time.Minute).Before(time.Now()) && !b.bestHeaderTime.IsZero() && b.mempoolInitialized {
|
||||
|
@ -537,7 +547,7 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
|
|||
btxs := make([]bchain.Tx, len(body.Transactions))
|
||||
for i := range body.Transactions {
|
||||
tx := &body.Transactions[i]
|
||||
btx, err := b.Parser.ethTxToTx(tx, &rpcReceipt{Logs: logs[tx.Hash]}, bbh.Time, uint32(bbh.Confirmations), true)
|
||||
btx, err := b.Parser.ethTxToTx(tx, &rpcReceipt{Logs: logs[tx.Hash]}, bbh.Time, uint32(bbh.Confirmations))
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash)
|
||||
}
|
||||
|
@ -573,8 +583,8 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
|||
}
|
||||
return &bchain.BlockInfo{
|
||||
BlockHeader: *bch,
|
||||
Difficulty: common.JSONNumber(head.Difficulty),
|
||||
Nonce: common.JSONNumber(head.Nonce),
|
||||
Difficulty: json.Number(head.Difficulty),
|
||||
Nonce: json.Number(head.Nonce),
|
||||
Txids: txs.Transactions,
|
||||
}, nil
|
||||
}
|
||||
|
@ -603,7 +613,7 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||
var btx *bchain.Tx
|
||||
if tx.BlockNumber == "" {
|
||||
// mempool tx
|
||||
btx, err = b.Parser.ethTxToTx(tx, nil, 0, 0, true)
|
||||
btx, err = b.Parser.ethTxToTx(tx, nil, 0, 0)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
|
@ -624,9 +634,33 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
var receipt rpcReceipt
|
||||
err = b.rpc.CallContext(ctx, &receipt, "eth_getTransactionReceipt", hash)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
if b.isETC {
|
||||
var rawReceipt json.RawMessage
|
||||
var etcReceipt rpcEtcReceipt
|
||||
err = b.rpc.CallContext(ctx, &rawReceipt, "eth_getTransactionReceipt", hash)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
err = json.Unmarshal(rawReceipt, &etcReceipt)
|
||||
if err == nil {
|
||||
receipt.GasUsed = etcReceipt.GasUsed
|
||||
receipt.Logs = etcReceipt.Logs
|
||||
if etcReceipt.Status == 0 {
|
||||
receipt.Status = "0x0"
|
||||
} else {
|
||||
receipt.Status = "0x1"
|
||||
}
|
||||
} else {
|
||||
err = json.Unmarshal(rawReceipt, &receipt)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "unmarshal receipt for txid %v, %v", txid, string(rawReceipt))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = b.rpc.CallContext(ctx, &receipt, "eth_getTransactionReceipt", hash)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
}
|
||||
n, err := ethNumber(tx.BlockNumber)
|
||||
if err != nil {
|
||||
|
@ -636,7 +670,7 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
btx, err = b.Parser.ethTxToTx(tx, &receipt, time, confirmations, true)
|
||||
btx, err = b.Parser.ethTxToTx(tx, &receipt, time, confirmations)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
|
@ -724,18 +758,6 @@ func (b *EthereumRPC) EthereumTypeEstimateGas(params map[string]interface{}) (ui
|
|||
if ok && len(s) > 0 {
|
||||
msg.Data = ethcommon.FromHex(s)
|
||||
}
|
||||
s, ok = getStringFromMap("value", params)
|
||||
if ok && len(s) > 0 {
|
||||
msg.Value, _ = hexutil.DecodeBig(s)
|
||||
}
|
||||
s, ok = getStringFromMap("gas", params)
|
||||
if ok && len(s) > 0 {
|
||||
msg.Gas, _ = hexutil.DecodeUint64(s)
|
||||
}
|
||||
s, ok = getStringFromMap("gasPrice", params)
|
||||
if ok && len(s) > 0 {
|
||||
msg.GasPrice, _ = hexutil.DecodeBig(s)
|
||||
}
|
||||
return b.client.EstimateGas(ctx, msg)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: bchain/coins/eth/ethtx.proto
|
||||
// source: tx.proto
|
||||
|
||||
/*
|
||||
Package eth is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
bchain/coins/eth/ethtx.proto
|
||||
tx.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ProtoCompleteTransaction
|
||||
|
@ -228,34 +228,33 @@ func init() {
|
|||
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("bchain/coins/eth/ethtx.proto", fileDescriptor0) }
|
||||
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 409 bytes of a gzipped FileDescriptorProto
|
||||
// 393 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x8a, 0xd4, 0x30,
|
||||
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,
|
||||
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,
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package firo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
)
|
||||
|
||||
// FiroMsgTx encapsulate firo tx and extra
|
||||
type FiroMsgTx struct {
|
||||
wire.MsgTx
|
||||
Extra []byte
|
||||
}
|
||||
|
||||
// TxHash calculate hash of transaction
|
||||
func (msg *FiroMsgTx) TxHash() chainhash.Hash {
|
||||
extraSize := uint64(len(msg.Extra))
|
||||
sizeOfExtraSize := 0
|
||||
if extraSize != 0 {
|
||||
sizeOfExtraSize = wire.VarIntSerializeSize(extraSize)
|
||||
}
|
||||
|
||||
// Original payload
|
||||
buf := bytes.NewBuffer(make([]byte, 0,
|
||||
msg.SerializeSizeStripped()+sizeOfExtraSize+len(msg.Extra)))
|
||||
_ = msg.SerializeNoWitness(buf)
|
||||
|
||||
// Extra payload
|
||||
if extraSize != 0 {
|
||||
wire.WriteVarInt(buf, 0, extraSize)
|
||||
buf.Write(msg.Extra)
|
||||
}
|
||||
|
||||
return chainhash.DoubleHashH(buf.Bytes())
|
||||
}
|
||||
|
||||
// FiroDecode to decode bitcoin tx and extra
|
||||
func (msg *FiroMsgTx) FiroDecode(r io.Reader, pver uint32, enc wire.MessageEncoding) error {
|
||||
if err := msg.MsgTx.BtcDecode(r, pver, enc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// extra
|
||||
version := uint32(msg.Version)
|
||||
txVersion := version & 0xffff
|
||||
txType := (version >> 16) & 0xffff
|
||||
if txVersion == 3 && txType != 0 {
|
||||
|
||||
extraSize, err := wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg.Extra = make([]byte, extraSize)
|
||||
_, err = io.ReadFull(r, msg.Extra[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
package flo
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
package flo
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package flo
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// FloRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package fujicoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package fujicoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package fujicoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// FujicoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package gamecredits
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package gamecredits
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package gamecredits
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// GameCreditsRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package grs
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/base58"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package grs
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
@ -11,8 +13,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package grs
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// GroestlcoinRPC is an interface to JSON-RPC service
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package koto
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package koto
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
@ -11,8 +13,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package koto
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// KotoRPC is an interface to JSON-RPC bitcoind service
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package liquid
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"strconv"
|
||||
|
||||
vlq "github.com/bsm/go-vlq"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/martinboehm/btcd/txscript"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package liquid
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package liquid
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// LiquidRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package litecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package litecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package litecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// LitecoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package monacoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package monacoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package monacoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// MonacoinRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
package monetaryunit
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package monetaryunit
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package monetaryunit
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// MonetaryUnitRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package myriad
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
package myriad
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -10,8 +12,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package myriad
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// MyriadRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -13,7 +14,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package namecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// NamecoinRPC is an interface to JSON-RPC namecoin service.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package nuls
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
vlq "github.com/bsm/go-vlq"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/base58"
|
||||
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"github.com/martinboehm/btcutil/hdkeychain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
// +build unittest
|
||||
|
||||
package nuls
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/martinboehm/btcutil/hdkeychain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -43,7 +41,7 @@ func init() {
|
|||
{
|
||||
ValueSat: *big.NewInt(399999000000),
|
||||
N: 0,
|
||||
JsonValue: common.JSONNumber("0"),
|
||||
JsonValue: json.Number("0"),
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "Nse4zpZHsUuU7h5ymv28pcGbwHju3joV",
|
||||
Addresses: []string{
|
||||
|
@ -75,7 +73,7 @@ func init() {
|
|||
{
|
||||
ValueSat: *big.NewInt(400000000000),
|
||||
N: 0,
|
||||
JsonValue: common.JSONNumber("0"),
|
||||
JsonValue: json.Number("0"),
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "Nse4ikjE88g2BgsNwsswTdkSwiSrKjjS",
|
||||
Addresses: []string{
|
||||
|
@ -86,7 +84,7 @@ func init() {
|
|||
{
|
||||
ValueSat: *big.NewInt(7286565570000),
|
||||
N: 1,
|
||||
JsonValue: common.JSONNumber("0"),
|
||||
JsonValue: json.Number("0"),
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "Nse119z2oSDJYkFkxmwYDiYtPfBeNkqi",
|
||||
Addresses: []string{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package nuls
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
|
@ -14,10 +16,9 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// NulsRPC is an interface to JSON-RPC bitcoind service
|
||||
|
|
|
@ -1,266 +0,0 @@
|
|||
package omotenashicoin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/martinboehm/btcd/blockchain"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
|
||||
)
|
||||
|
||||
// magic numbers
|
||||
const (
|
||||
MainnetMagic wire.BitcoinNet = 0xdda5b5d1
|
||||
TestnetMagic wire.BitcoinNet = 0x54644363
|
||||
|
||||
// Zerocoin op codes
|
||||
OP_ZEROCOINMINT = 0xc1
|
||||
OP_ZEROCOINSPEND = 0xc2
|
||||
)
|
||||
|
||||
// chain parameters
|
||||
var (
|
||||
MainNetParams chaincfg.Params
|
||||
TestNetParams chaincfg.Params
|
||||
)
|
||||
|
||||
func init() {
|
||||
// mainnet Address encoding magics
|
||||
MainNetParams = chaincfg.MainNetParams
|
||||
MainNetParams.Net = MainnetMagic
|
||||
MainNetParams.PubKeyHashAddrID = []byte{63} // char S
|
||||
MainNetParams.ScriptHashAddrID = []byte{18}
|
||||
MainNetParams.PrivateKeyID = []byte{191}
|
||||
|
||||
// testnet Address encoding magics
|
||||
TestNetParams = chaincfg.TestNet3Params
|
||||
TestNetParams.Net = TestnetMagic
|
||||
TestNetParams.PubKeyHashAddrID = []byte{83}
|
||||
TestNetParams.ScriptHashAddrID = []byte{18}
|
||||
TestNetParams.PrivateKeyID = []byte{193}
|
||||
}
|
||||
|
||||
// OmotenashiCoinParser handle
|
||||
type OmotenashiCoinParser struct {
|
||||
*btc.BitcoinParser
|
||||
baseparser *bchain.BaseParser
|
||||
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
|
||||
}
|
||||
|
||||
// NewOmotenashiCoinParser returns new OmotenashiCoinParser instance
|
||||
func NewOmotenashiCoinParser(params *chaincfg.Params, c *btc.Configuration) *OmotenashiCoinParser {
|
||||
p := &OmotenashiCoinParser{
|
||||
BitcoinParser: btc.NewBitcoinParser(params, c),
|
||||
baseparser: &bchain.BaseParser{},
|
||||
}
|
||||
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
|
||||
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
||||
return p
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main OmotenashiCoin network
|
||||
func GetChainParams(chain string) *chaincfg.Params {
|
||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||
err := chaincfg.Register(&MainNetParams)
|
||||
if err == nil {
|
||||
err = chaincfg.Register(&TestNetParams)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
switch chain {
|
||||
case "test":
|
||||
return &TestNetParams
|
||||
default:
|
||||
return &MainNetParams
|
||||
}
|
||||
}
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
func (p *OmotenashiCoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
r := bytes.NewReader(b)
|
||||
w := wire.MsgBlock{}
|
||||
h := wire.BlockHeader{}
|
||||
err := h.Deserialize(r)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "Deserialize")
|
||||
}
|
||||
|
||||
if h.Version > 3 && h.Version < 7 {
|
||||
// Skip past AccumulatorCheckpoint (block version 4, 5 and 6)
|
||||
r.Seek(32, io.SeekCurrent)
|
||||
}
|
||||
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "DecodeTransactions")
|
||||
}
|
||||
|
||||
txs := make([]bchain.Tx, len(w.Transactions))
|
||||
for ti, t := range w.Transactions {
|
||||
txs[ti] = p.TxFromMsgTx(t, false)
|
||||
}
|
||||
|
||||
return &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
Size: len(b),
|
||||
Time: h.Timestamp.Unix(),
|
||||
},
|
||||
Txs: txs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PackTx packs transaction to byte array using protobuf
|
||||
func (p *OmotenashiCoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
|
||||
return p.baseparser.PackTx(tx, height, blockTime)
|
||||
}
|
||||
|
||||
// UnpackTx unpacks transaction from protobuf byte array
|
||||
func (p *OmotenashiCoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
return p.baseparser.UnpackTx(buf)
|
||||
}
|
||||
|
||||
// ParseTx parses byte array containing transaction and returns Tx struct
|
||||
func (p *OmotenashiCoinParser) ParseTx(b []byte) (*bchain.Tx, error) {
|
||||
t := wire.MsgTx{}
|
||||
r := bytes.NewReader(b)
|
||||
if err := t.Deserialize(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := p.TxFromMsgTx(&t, true)
|
||||
tx.Hex = hex.EncodeToString(b)
|
||||
return &tx, nil
|
||||
}
|
||||
|
||||
// TxFromMsgTx parses tx and adds handling for OP_ZEROCOINSPEND inputs
|
||||
func (p *OmotenashiCoinParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.Tx {
|
||||
vin := make([]bchain.Vin, len(t.TxIn))
|
||||
for i, in := range t.TxIn {
|
||||
|
||||
// extra check to not confuse Tx with single OP_ZEROCOINSPEND input as a coinbase Tx
|
||||
if !isZeroCoinSpendScript(in.SignatureScript) && blockchain.IsCoinBaseTx(t) {
|
||||
vin[i] = bchain.Vin{
|
||||
Coinbase: hex.EncodeToString(in.SignatureScript),
|
||||
Sequence: in.Sequence,
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
s := bchain.ScriptSig{
|
||||
Hex: hex.EncodeToString(in.SignatureScript),
|
||||
// missing: Asm,
|
||||
}
|
||||
|
||||
txid := in.PreviousOutPoint.Hash.String()
|
||||
|
||||
vin[i] = bchain.Vin{
|
||||
Txid: txid,
|
||||
Vout: in.PreviousOutPoint.Index,
|
||||
Sequence: in.Sequence,
|
||||
ScriptSig: s,
|
||||
}
|
||||
}
|
||||
vout := make([]bchain.Vout, len(t.TxOut))
|
||||
for i, out := range t.TxOut {
|
||||
addrs := []string{}
|
||||
if parseAddresses {
|
||||
addrs, _, _ = p.OutputScriptToAddressesFunc(out.PkScript)
|
||||
}
|
||||
s := bchain.ScriptPubKey{
|
||||
Hex: hex.EncodeToString(out.PkScript),
|
||||
Addresses: addrs,
|
||||
// missing: Asm,
|
||||
// missing: Type,
|
||||
}
|
||||
var vs big.Int
|
||||
vs.SetInt64(out.Value)
|
||||
vout[i] = bchain.Vout{
|
||||
ValueSat: vs,
|
||||
N: uint32(i),
|
||||
ScriptPubKey: s,
|
||||
}
|
||||
}
|
||||
tx := bchain.Tx{
|
||||
Txid: t.TxHash().String(),
|
||||
Version: t.Version,
|
||||
LockTime: t.LockTime,
|
||||
Vin: vin,
|
||||
Vout: vout,
|
||||
// skip: BlockHash,
|
||||
// skip: Confirmations,
|
||||
// skip: Time,
|
||||
// skip: Blocktime,
|
||||
}
|
||||
return tx
|
||||
}
|
||||
|
||||
// ParseTxFromJson parses JSON message containing transaction and returns Tx struct
|
||||
func (p *OmotenashiCoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
|
||||
var tx bchain.Tx
|
||||
err := json.Unmarshal(msg, &tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range tx.Vout {
|
||||
vout := &tx.Vout[i]
|
||||
// convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal
|
||||
vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vout.JsonValue = ""
|
||||
|
||||
if vout.ScriptPubKey.Addresses == nil {
|
||||
vout.ScriptPubKey.Addresses = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
return &tx, nil
|
||||
}
|
||||
|
||||
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||
func (p *OmotenashiCoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
||||
if isZeroCoinSpendScript(script) {
|
||||
return []string{"Zerocoin Spend"}, false, nil
|
||||
}
|
||||
if isZeroCoinMintScript(script) {
|
||||
return []string{"Zerocoin Mint"}, false, nil
|
||||
}
|
||||
|
||||
rv, s, _ := p.BitcoinOutputScriptToAddressesFunc(script)
|
||||
return rv, s, nil
|
||||
}
|
||||
|
||||
func (p *OmotenashiCoinParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor {
|
||||
if len(tx.Vin) > input {
|
||||
scriptHex := tx.Vin[input].ScriptSig.Hex
|
||||
|
||||
if scriptHex != "" {
|
||||
script, _ := hex.DecodeString(scriptHex)
|
||||
return script
|
||||
}
|
||||
}
|
||||
|
||||
s := make([]byte, 10)
|
||||
return s
|
||||
}
|
||||
|
||||
// Checks if script is OP_ZEROCOINMINT
|
||||
func isZeroCoinMintScript(signatureScript []byte) bool {
|
||||
return len(signatureScript) > 1 && signatureScript[0] == OP_ZEROCOINMINT
|
||||
}
|
||||
|
||||
// Checks if script is OP_ZEROCOINSPEND
|
||||
func isZeroCoinSpendScript(signatureScript []byte) bool {
|
||||
return len(signatureScript) >= 100 && signatureScript[0] == OP_ZEROCOINSPEND
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue