Compare commits
162 Commits
v0.3.2
...
deepcrayon
Author | SHA1 | Date |
---|---|---|
jebba | a8595591f0 | |
jebba | cd8161a10d | |
jebba | f4f7612655 | |
jebba | e2a3404b06 | |
jebba | afabba64a9 | |
jebba | 473df3d139 | |
jebba | a337163a2d | |
jebba | 65be7edda2 | |
jebba | 0c93f8803d | |
jebba | 8fd633c6d3 | |
jebba | 2771784113 | |
jebba | f05eff6b13 | |
jebba | 7ba8d7f143 | |
jebba | 14c92e8bd5 | |
jebba | 4b352b5bbc | |
jebba | 124717da69 | |
jebba | 2f1c4bc3af | |
jebba | 0ce520d1d5 | |
jebba | 8ef0a2a3d5 | |
jebba | 27c9434383 | |
jebba | fb64efefdc | |
kaladin | 1f6cddd4ab | |
CodeFace | 78c8a9d499 | |
Vitalij DovhanyÄŤ | d8640f4e2f | |
vdovhanyc | d588904fb3 | |
Martin Boehm | e6e6e64351 | |
jsimon | 61c2834002 | |
Martin Boehm | 0ae8ba57a2 | |
Martin Boehm | 8f3106d009 | |
vdovhanych | 099a158f8c | |
Perlover | 37c7f4fbd1 | |
Martin Boehm | db597c1f66 | |
Martin Boehm | dcbcb99055 | |
Martin Boehm | 212b767925 | |
WO | 3fe28d185c | |
Rikard Wissing | d0a1cb29f6 | |
Martin Boehm | 2be5930862 | |
Yusaku Senga | 5fdc26bc14 | |
Martin Boehm | 7e54336e0c | |
Martin Boehm | 7dffe2e0f9 | |
Martin Boehm | d992369426 | |
David Hill | d97b5e14e8 | |
JoHnY | 9df39273ea | |
Pavol Rusnak | 66c072bf25 | |
Jin Eguchi | 505d859f91 | |
Dehumanizer77 | d631bf9265 | |
Martin Kuvandzhiev | 295b630ec8 | |
Dehumanizer77 | b4149946bd | |
Dehumanizer77 | 6981222a43 | |
Peter John Bushnell | bb9fce02cb | |
Jin Eguchi | 077e637093 | |
araarakelyan1985 | 15b88ef23d | |
Martin | 4697d756e0 | |
Martin | 4766110255 | |
Tomas Susanka | 360cac85f6 | |
jackielove4u | 554041c32c | |
CodeFace | d12e6551ea | |
Martin Boehm | 96e8329171 | |
Martin Boehm | f094ee578d | |
Martin Boehm | 00352cb5fe | |
CryptoManiac | c0c2dc4151 | |
Martin Boehm | da1c0d762e | |
Martin Boehm | fc267ed2f4 | |
Martin Boehm | 69d13e0688 | |
Martin Boehm | 248de3cb34 | |
Martin Boehm | 636167c72a | |
Martin Boehm | 24a783be50 | |
Martin Boehm | 579b42cf27 | |
Martin Boehm | 576b8b57b7 | |
Martin Kuvandzhiev | 786047f8c2 | |
Dehumanizer77 | 3ccfd181b7 | |
Dehumanizer77 | 6274f4b3d4 | |
Dehumanizer77 | 2b786c9832 | |
Dehumanizer77 | bc009454d0 | |
Dehumanizer77 | 5e7d0e9f75 | |
Pavol Rusnak | c915f35224 | |
Pavol Rusnak | 3369295e10 | |
hewigovens | 5534372e7c | |
Martin Boehm | fc25200ff8 | |
Martin Boehm | 3d9954bf79 | |
nezero | 214d0144ef | |
Liam Alford | ec79702bab | |
Scotty0448 | e666e7c5a4 | |
JoHnY | 4832205f45 | |
1000101 | b05346b1a1 | |
WO | dcf77a5680 | |
1000101 | 7f1cf09d05 | |
Martin | a1993173ab | |
jackielove4u | bea6b6230f | |
jackielove4u | 72486c606f | |
1000101 | a8ee6aefb0 | |
1000101 | 52cbc7162d | |
Pavol Rusnak | 81ce876d8b | |
Braydon Fuller | 7b70ee0ad0 | |
Braydon Fuller | a83cb7684f | |
Pavol Rusnak | 0f4eadd935 | |
1000101 | e66fa79383 | |
1000101 | f99406e9cf | |
1000101 | be73064223 | |
Panu | 79907e7aa5 | |
1000101 | 2fb1e779c0 | |
1000101 | a530f5612a | |
Martin Boehm | ab285c6b05 | |
Martin Boehm | 17c9080135 | |
1000101 | 791948623e | |
Scotty0448 | af5e8f18ba | |
root | 07ac3c8401 | |
Martin Boehm | 83616bce83 | |
codeface | 22145d0cc2 | |
Dehumanizer77 | 92ae2052c3 | |
Dehumanizer77 | 30149e51d2 | |
Martin Boehm | abb6453fb3 | |
Martin Boehm | eb4e10ac67 | |
1000101 | 5350027e1d | |
1000101 | 7d6c61623e | |
Martin Boehm | 994567aed9 | |
Martin Boehm | dd7964297d | |
Martin Boehm | 3be3bb5c3d | |
Martin Boehm | 0a3ea6e225 | |
Martin Boehm | bc001ce3a3 | |
Martin Boehm | 76324be8ec | |
Martin Boehm | 01d8e48e73 | |
Martin Boehm | ff607bc334 | |
Martin Boehm | e60c320ae7 | |
Martin Boehm | dd2dc6b2ee | |
wakiyamap | b957ed66ab | |
Adam Collier | 3ebe99edb2 | |
v | bad9f992e1 | |
jackielove4u | 707ac28954 | |
Martin Boehm | b6961ca600 | |
Martin Boehm | 5492a51534 | |
Martin Boehm | a7d95a49df | |
Martin Boehm | ee3217aba8 | |
Martin Boehm | c3d58f0649 | |
Martin Boehm | 180b5655d5 | |
hewigovens | 3ba7289587 | |
ciripel | a34ee217b5 | |
WO | 11e9de2ffe | |
Martin Boehm | 81a1acd6f8 | |
Martin Boehm | 997fa661e7 | |
Martin Boehm | 8a926a0799 | |
Martin Boehm | 828e10b629 | |
Scotty0448 | a6fd137283 | |
Dehumanizer77 | f97d23590c | |
Dehumanizer77 | 945827c330 | |
Dehumanizer77 | 42bc7d2ba3 | |
Adam Collier | ddd981a405 | |
Dehumanizer77 | ea6a7e0db6 | |
Scotty0448 | 7eb4675f54 | |
ciripel | 124dee84fa | |
Martin Boehm | 5f1957b4ff | |
Martin Boehm | c43a7a4feb | |
ilmango | e99a8eba65 | |
Martin Boehm | 2a3c5426ca | |
Kirill Fomichev | c2e32b0a25 | |
Martin Boehm | 4338d10dcb | |
TheTrunk | b4bddc8c0e | |
JoHnY | c705600aae | |
Martin Boehm | 48584b3070 | |
David Hill | 395db88a60 | |
David Hill | 8f8ade727c | |
David Hill | 13527bda06 |
|
@ -8,6 +8,7 @@ debug*
|
|||
docker/blockbook
|
||||
build/pkg-defs
|
||||
build/blockbook
|
||||
build/blockchaincfg.json
|
||||
build/ldb
|
||||
build/sst_dump
|
||||
build/*.deb
|
||||
|
|
|
@ -1,298 +0,0 @@
|
|||
# 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
|
74
Gopkg.toml
74
Gopkg.toml
|
@ -1,74 +0,0 @@
|
|||
|
||||
# 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,8 +1,9 @@
|
|||
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
|
||||
UPDATE_VENDOR = 1
|
||||
TCMALLOC =
|
||||
ARGS ?=
|
||||
|
||||
TARGETS=$(subst .json,, $(shell ls configs/coins))
|
||||
|
@ -10,28 +11,28 @@ TARGETS=$(subst .json,, $(shell ls configs/coins))
|
|||
.PHONY: build build-debug test deb
|
||||
|
||||
build: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build ARGS="$(ARGS)"
|
||||
|
||||
build-debug: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
|
||||
|
||||
test: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
|
||||
|
||||
test-integration: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
|
||||
|
||||
test-all: .bin-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
|
||||
|
||||
deb-backend-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS)
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS)
|
||||
|
||||
deb-blockbook-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS)
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS)
|
||||
|
||||
deb-%: .deb-image
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS)
|
||||
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS)
|
||||
|
||||
deb-blockbook-all: clean-deb $(addprefix deb-blockbook-, $(TARGETS))
|
||||
|
||||
|
@ -44,8 +45,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)..."; \
|
||||
docker build --no-cache=$(NO_CACHE) -t $(BIN_IMAGE) build/docker/bin; \
|
||||
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; \
|
||||
else \
|
||||
echo "Image $(BIN_IMAGE) is up to date"; \
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
[![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,74 +1,57 @@
|
|||
[![Go Report Card](https://goreportcard.com/badge/trezor/blockbook)](https://goreportcard.com/report/trezor/blockbook)
|
||||
# Fork
|
||||
Fork of Trezor Blockbook.
|
||||
|
||||
# Blockbook
|
||||
|
||||
**Blockbook** is back-end service for Trezor wallet. Main features of **Blockbook** are:
|
||||
The differences:
|
||||
|
||||
- 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
|
||||
* Just for Ethereum.
|
||||
|
||||
## Build and installation instructions
|
||||
* Use existing `geth --full` server.
|
||||
|
||||
Officially supported platform is **Debian Linux** and **AMD64** architecture.
|
||||
* Don't require `backend-*` package.
|
||||
|
||||
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.
|
||||
* Minimal UI, dark theme.
|
||||
|
||||
User installation guide is [here](https://wiki.trezor.io/User_manual:Running_a_local_instance_of_Trezor_Wallet_backend_(Blockbook)).
|
||||
* Listen only on localhost, no SSL.
|
||||
|
||||
Developer build guide is [here](/docs/build.md).
|
||||
* Use spacecruft repos, not github.
|
||||
|
||||
Contribution guide is [here](CONTRIBUTING.md).
|
||||
* Don't use CDN.
|
||||
|
||||
## Implemented coins
|
||||
# Install
|
||||
|
||||
Blockbook currently supports over 30 coins. The Trezor team implemented
|
||||
```
|
||||
# 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
|
||||
```
|
||||
|
||||
- Bitcoin, Bitcoin Cash, Zcash, Dash, Litecoin, Bitcoin Gold, Ethereum, Ethereum Classic, Dogecoin, Namecoin, Vertcoin, DigiByte, Liquid
|
||||
Edit config:
|
||||
```
|
||||
vim /opt/coins/blockbook/ethereum/config/blockchaincfg.json
|
||||
```
|
||||
|
||||
the rest of coins were implemented by the community.
|
||||
XXX Hardcoded into systemd script, set `geth` node:
|
||||
|
||||
Testnets for some coins are also supported, for example:
|
||||
- Bitcoin Testnet, Bitcoin Cash Testnet, ZCash Testnet, Ethereum Testnet Ropsten
|
||||
```
|
||||
vim /lib/systemd/system/blockbook-ethereum.service
|
||||
systemctl daemon-reload
|
||||
```
|
||||
|
||||
List of all implemented coins is in [the registry of ports](/docs/ports.md).
|
||||
Start:
|
||||
```
|
||||
systemctl start blockbook-ethereum.service
|
||||
```
|
||||
|
||||
## Common issues when running Blockbook or implementing additional coins
|
||||
Logs:
|
||||
```
|
||||
tail -f /opt/coins/blockbook/ethereum/logs/blockbook.INFO
|
||||
```
|
||||
|
||||
#### Out of memory when doing initial synchronization
|
||||
# Upstream
|
||||
Fork of Trezor Blockbook. See `README-upstream.md`.
|
||||
|
||||
How to reduce memory footprint of the initial sync:
|
||||
* https://github.com/trezor/blockbook
|
||||
|
||||
- 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,14 +1,16 @@
|
|||
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)
|
||||
|
@ -169,11 +171,12 @@ type TokenTransfer struct {
|
|||
|
||||
// EthereumSpecific contains ethereum specific transaction data
|
||||
type EthereumSpecific struct {
|
||||
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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Tx holds information about a transaction
|
||||
|
@ -193,8 +196,7 @@ type Tx struct {
|
|||
FeesSat *Amount `json:"fees,omitempty"`
|
||||
Hex string `json:"hex,omitempty"`
|
||||
Rbf bool `json:"rbf,omitempty"`
|
||||
CoinSpecificData interface{} `json:"-"`
|
||||
CoinSpecificJSON json.RawMessage `json:"-"`
|
||||
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"`
|
||||
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
|
||||
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
|
||||
}
|
||||
|
@ -224,6 +226,8 @@ 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
|
||||
|
@ -299,12 +303,13 @@ 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"`
|
||||
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"`
|
||||
SentToSelfSat *Amount `json:"sentToSelf"`
|
||||
FiatRates map[string]float64 `json:"rates,omitempty"`
|
||||
Txid string `json:"txid,omitempty"`
|
||||
}
|
||||
|
||||
// BalanceHistories is array of BalanceHistory
|
||||
|
@ -326,8 +331,9 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
|||
bhs := make(BalanceHistories, 0)
|
||||
if len(a) > 0 {
|
||||
bha := BalanceHistory{
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &Amount{},
|
||||
}
|
||||
sort.Sort(a)
|
||||
for i := range a {
|
||||
|
@ -340,17 +346,19 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
|||
bhs = append(bhs, bha)
|
||||
}
|
||||
bha = BalanceHistory{
|
||||
Time: time,
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
Time: time,
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &Amount{},
|
||||
}
|
||||
}
|
||||
if bha.Txid != bh.Txid {
|
||||
bha.Txs += bh.Txs
|
||||
bha.Txid = bh.Txid
|
||||
}
|
||||
(*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat))
|
||||
(*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))
|
||||
}
|
||||
if bha.Txs > 0 {
|
||||
bha.Txid = ""
|
||||
|
@ -368,19 +376,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 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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Block contains information about block
|
||||
|
@ -413,26 +421,10 @@ 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 *BackendInfo `json:"backend"`
|
||||
Blockbook *BlockbookInfo `json:"blockbook"`
|
||||
Backend *common.BackendInfo `json:"backend"`
|
||||
}
|
||||
|
||||
// MempoolTxid contains information about a transaction in mempool
|
||||
|
|
|
@ -67,20 +67,22 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
|||
name: "one",
|
||||
a: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||
Time: 1521514812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
groupByTime: 3600,
|
||||
want: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -88,67 +90,76 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
|||
name: "aggregate",
|
||||
a: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||
SentSat: (*Amount)(big.NewInt(2)),
|
||||
Time: 1521504812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
Txs: 1,
|
||||
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(3)),
|
||||
SentSat: (*Amount)(big.NewInt(4)),
|
||||
Time: 1521504812,
|
||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||
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(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521514812,
|
||||
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(7)),
|
||||
SentSat: (*Amount)(big.NewInt(8)),
|
||||
Time: 1521504812,
|
||||
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(9)),
|
||||
SentSat: (*Amount)(big.NewInt(10)),
|
||||
Time: 1521534812,
|
||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||
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(11)),
|
||||
SentSat: (*Amount)(big.NewInt(12)),
|
||||
Time: 1521534812,
|
||||
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(12)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521534812,
|
||||
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
||||
Txs: 1,
|
||||
},
|
||||
},
|
||||
groupByTime: 3600,
|
||||
want: []BalanceHistory{
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(14)),
|
||||
Time: 1521504000,
|
||||
Txs: 2,
|
||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||
SentSat: (*Amount)(big.NewInt(14)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(5)),
|
||||
Time: 1521504000,
|
||||
Txs: 2,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||
SentSat: (*Amount)(big.NewInt(6)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||
Time: 1521514800,
|
||||
Txs: 1,
|
||||
},
|
||||
{
|
||||
ReceivedSat: (*Amount)(big.NewInt(20)),
|
||||
SentSat: (*Amount)(big.NewInt(22)),
|
||||
Time: 1521532800,
|
||||
Txs: 2,
|
||||
ReceivedSat: (*Amount)(big.NewInt(20)),
|
||||
SentSat: (*Amount)(big.NewInt(22)),
|
||||
SentToSelfSat: (*Amount)(big.NewInt(11)),
|
||||
Time: 1521532800,
|
||||
Txs: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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,10 +1,6 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/eth"
|
||||
"blockbook/common"
|
||||
"blockbook/db"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -18,6 +14,10 @@ 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,32 +253,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
|||
if err != nil {
|
||||
glog.Errorf("GetErc20FromTx error %v, %v", err, bchainTx)
|
||||
}
|
||||
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,
|
||||
}
|
||||
}
|
||||
tokens = w.getTokensFromErc20(ets)
|
||||
ethTxData := eth.GetEthereumTxData(bchainTx)
|
||||
// mempool txs do not have fees yet
|
||||
if ethTxData.GasUsed != nil {
|
||||
|
@ -293,12 +268,14 @@ 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
|
||||
if specificJSON {
|
||||
// return CoinSpecificData for all mempool transactions or if requested
|
||||
if specificJSON || bchainTx.Confirmations == 0 {
|
||||
sj, err = w.chain.GetTransactionSpecific(bchainTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -323,14 +300,140 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
|||
Rbf: rbf,
|
||||
Vin: vins,
|
||||
Vout: vouts,
|
||||
CoinSpecificData: bchainTx.CoinSpecificData,
|
||||
CoinSpecificJSON: sj,
|
||||
CoinSpecificData: sj,
|
||||
TokenTransfers: tokens,
|
||||
EthereumSpecific: ethSpecific,
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// GetTransactionFromMempoolTx converts bchain.MempoolTx to Tx, with limited amount of data
|
||||
// it is not doing any request to backend or to db
|
||||
func (w *Worker) GetTransactionFromMempoolTx(mempoolTx *bchain.MempoolTx) (*Tx, error) {
|
||||
var err error
|
||||
var valInSat, valOutSat, feesSat big.Int
|
||||
var pValInSat *big.Int
|
||||
var tokens []TokenTransfer
|
||||
var ethSpecific *EthereumSpecific
|
||||
vins := make([]Vin, len(mempoolTx.Vin))
|
||||
rbf := false
|
||||
for i := range mempoolTx.Vin {
|
||||
bchainVin := &mempoolTx.Vin[i]
|
||||
vin := &vins[i]
|
||||
vin.Txid = bchainVin.Txid
|
||||
vin.N = i
|
||||
vin.Vout = bchainVin.Vout
|
||||
vin.Sequence = int64(bchainVin.Sequence)
|
||||
// detect explicit Replace-by-Fee transactions as defined by BIP125
|
||||
if bchainVin.Sequence < 0xffffffff-1 {
|
||||
rbf = true
|
||||
}
|
||||
vin.Hex = bchainVin.ScriptSig.Hex
|
||||
vin.Coinbase = bchainVin.Coinbase
|
||||
if w.chainType == bchain.ChainBitcoinType {
|
||||
// bchainVin.Txid=="" is coinbase transaction
|
||||
if bchainVin.Txid != "" {
|
||||
vin.ValueSat = (*Amount)(&bchainVin.ValueSat)
|
||||
vin.AddrDesc = bchainVin.AddrDesc
|
||||
vin.Addresses, vin.IsAddress, _ = w.chainParser.GetAddressesFromAddrDesc(vin.AddrDesc)
|
||||
if vin.ValueSat != nil {
|
||||
valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat))
|
||||
}
|
||||
}
|
||||
} else if w.chainType == bchain.ChainEthereumType {
|
||||
if len(bchainVin.Addresses) > 0 {
|
||||
vin.AddrDesc, err = w.chainParser.GetAddrDescFromAddress(bchainVin.Addresses[0])
|
||||
if err != nil {
|
||||
glog.Errorf("GetAddrDescFromAddress error %v, tx %v, bchainVin %v", err, mempoolTx.Txid, bchainVin)
|
||||
}
|
||||
vin.Addresses = bchainVin.Addresses
|
||||
vin.IsAddress = true
|
||||
}
|
||||
}
|
||||
}
|
||||
vouts := make([]Vout, len(mempoolTx.Vout))
|
||||
for i := range mempoolTx.Vout {
|
||||
bchainVout := &mempoolTx.Vout[i]
|
||||
vout := &vouts[i]
|
||||
vout.N = i
|
||||
vout.ValueSat = (*Amount)(&bchainVout.ValueSat)
|
||||
valOutSat.Add(&valOutSat, &bchainVout.ValueSat)
|
||||
vout.Hex = bchainVout.ScriptPubKey.Hex
|
||||
vout.AddrDesc, vout.Addresses, vout.IsAddress, err = w.getAddressesFromVout(bchainVout)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("getAddressesFromVout error %v, %v, output %v", err, mempoolTx.Txid, bchainVout.N)
|
||||
}
|
||||
}
|
||||
if w.chainType == bchain.ChainBitcoinType {
|
||||
// for coinbase transactions valIn is 0
|
||||
feesSat.Sub(&valInSat, &valOutSat)
|
||||
if feesSat.Sign() == -1 {
|
||||
feesSat.SetUint64(0)
|
||||
}
|
||||
pValInSat = &valInSat
|
||||
} else if w.chainType == bchain.ChainEthereumType {
|
||||
if len(mempoolTx.Vout) > 0 {
|
||||
valOutSat = mempoolTx.Vout[0].ValueSat
|
||||
}
|
||||
tokens = w.getTokensFromErc20(mempoolTx.Erc20)
|
||||
ethTxData := eth.GetEthereumTxDataFromSpecificData(mempoolTx.CoinSpecificData)
|
||||
ethSpecific = &EthereumSpecific{
|
||||
GasLimit: ethTxData.GasLimit,
|
||||
GasPrice: (*Amount)(ethTxData.GasPrice),
|
||||
GasUsed: ethTxData.GasUsed,
|
||||
Nonce: ethTxData.Nonce,
|
||||
Status: ethTxData.Status,
|
||||
Data: ethTxData.Data,
|
||||
}
|
||||
}
|
||||
r := &Tx{
|
||||
Blocktime: mempoolTx.Blocktime,
|
||||
FeesSat: (*Amount)(&feesSat),
|
||||
Locktime: mempoolTx.LockTime,
|
||||
Txid: mempoolTx.Txid,
|
||||
ValueInSat: (*Amount)(pValInSat),
|
||||
ValueOutSat: (*Amount)(&valOutSat),
|
||||
Version: mempoolTx.Version,
|
||||
Hex: mempoolTx.Hex,
|
||||
Rbf: rbf,
|
||||
Vin: vins,
|
||||
Vout: vouts,
|
||||
TokenTransfers: tokens,
|
||||
EthereumSpecific: ethSpecific,
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (w *Worker) getTokensFromErc20(erc20 []bchain.Erc20Transfer) []TokenTransfer {
|
||||
tokens := make([]TokenTransfer, len(erc20))
|
||||
for i := range erc20 {
|
||||
e := &erc20[i]
|
||||
cd, err := w.chainParser.GetAddrDescFromAddress(e.Contract)
|
||||
if err != nil {
|
||||
glog.Errorf("GetAddrDescFromAddress error %v, contract %v", err, e.Contract)
|
||||
continue
|
||||
}
|
||||
erc20c, err := w.chain.EthereumTypeGetErc20ContractInfo(cd)
|
||||
if err != nil {
|
||||
glog.Errorf("GetErc20ContractInfo error %v, contract %v", err, e.Contract)
|
||||
}
|
||||
if erc20c == nil {
|
||||
erc20c = &bchain.Erc20Contract{Name: e.Contract}
|
||||
}
|
||||
tokens[i] = TokenTransfer{
|
||||
Type: ERC20TokenType,
|
||||
Token: e.Contract,
|
||||
From: e.From,
|
||||
To: e.To,
|
||||
Decimals: erc20c.Decimals,
|
||||
Value: (*Amount)(&e.Tokens),
|
||||
Name: erc20c.Name,
|
||||
Symbol: erc20c.Symbol,
|
||||
}
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool, filter *AddressFilter, maxResults int) ([]string, error) {
|
||||
var err error
|
||||
txids := make([]string, 0, 4)
|
||||
|
@ -400,6 +503,19 @@ 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
|
||||
|
@ -496,6 +612,44 @@ 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
|
||||
|
@ -514,6 +668,13 @@ 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),
|
||||
|
@ -525,13 +686,6 @@ 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
|
||||
|
@ -543,43 +697,26 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||
// filter only transactions of this contract
|
||||
filter.Vout = i + 1
|
||||
}
|
||||
validContract := true
|
||||
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(c.Contract)
|
||||
t, err := w.getEthereumToken(i+1, addrDesc, c.Contract, details, int(c.Txs))
|
||||
if err != nil {
|
||||
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),
|
||||
return nil, nil, nil, 0, 0, 0, err
|
||||
}
|
||||
tokens[j] = *t
|
||||
j++
|
||||
}
|
||||
tokens = tokens[: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]
|
||||
}
|
||||
}
|
||||
ci, err = w.chain.EthereumTypeGetErc20ContractInfo(addrDesc)
|
||||
if err != nil {
|
||||
|
@ -593,6 +730,8 @@ 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)
|
||||
|
@ -603,6 +742,16 @@ 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
|
||||
}
|
||||
|
@ -619,7 +768,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail
|
|||
if ta == nil {
|
||||
glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses")
|
||||
// as fallback, get tx from backend
|
||||
tx, err = w.GetTransaction(txid, false, true)
|
||||
tx, err = w.GetTransaction(txid, false, false)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
||||
}
|
||||
|
@ -638,7 +787,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail
|
|||
tx = w.txFromTxAddress(txid, ta, blockInfo, bestheight)
|
||||
}
|
||||
} else {
|
||||
tx, err = w.GetTransaction(txid, false, true)
|
||||
tx, err = w.GetTransaction(txid, false, false)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
||||
}
|
||||
|
@ -727,7 +876,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
|
|||
return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc)
|
||||
}
|
||||
for _, txid := range txm {
|
||||
tx, err := w.GetTransaction(txid, false, false)
|
||||
tx, err := w.GetTransaction(txid, false, true)
|
||||
// mempool transaction may fail
|
||||
if err != nil || tx == nil {
|
||||
glog.Warning("GetTransaction in mempool: ", err)
|
||||
|
@ -736,7 +885,12 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
|
|||
if tx.Confirmations == 0 {
|
||||
unconfirmedTxs++
|
||||
uBalSat.Add(&uBalSat, tx.getAddrVoutValue(addrDesc))
|
||||
uBalSat.Sub(&uBalSat, tx.getAddrVinValue(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))
|
||||
}
|
||||
if page == 0 {
|
||||
if option == AccountDetailsTxidHistory {
|
||||
txids = append(txids, tx.Txid)
|
||||
|
@ -749,7 +903,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 {
|
||||
if option >= AccountDetailsTxidHistory && filter.Vout != AddressFilterVoutQueryNotNecessary {
|
||||
txc, err := w.getAddressTxids(addrDesc, false, filter, (page+1)*txsOnPage)
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "getAddressTxids %v false", addrDesc)
|
||||
|
@ -820,7 +974,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) (*BalanceHistory, error) {
|
||||
func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32, selfAddrDesc map[string]struct{}) (*BalanceHistory, error) {
|
||||
var time uint32
|
||||
var err error
|
||||
var ta *db.TxAddresses
|
||||
|
@ -853,17 +1007,30 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
return nil, nil
|
||||
}
|
||||
bh := BalanceHistory{
|
||||
Time: time,
|
||||
Txs: 1,
|
||||
SentSat: &Amount{},
|
||||
ReceivedSat: &Amount{},
|
||||
Txid: txid,
|
||||
Time: time,
|
||||
Txs: 1,
|
||||
ReceivedSat: &Amount{},
|
||||
SentSat: &Amount{},
|
||||
SentToSelfSat: &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 {
|
||||
|
@ -871,12 +1038,17 @@ 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 transactions
|
||||
if ethTxData.Status == 1 {
|
||||
// add received amount only for OK or unknown status (old) transactions
|
||||
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||
if len(bchainTx.Vout) > 0 {
|
||||
bchainVout := &bchainTx.Vout[0]
|
||||
value = bchainVout.ValueSat
|
||||
|
@ -888,6 +1060,9 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -899,9 +1074,14 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
|||
return nil, err
|
||||
}
|
||||
if bytes.Equal(addrDesc, txAddrDesc) {
|
||||
// add sent amount only for OK transactions, however fees always
|
||||
if ethTxData.Status == 1 {
|
||||
// add received amount only for OK or unknown status (old) transactions, fees always
|
||||
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||
(*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
|
||||
|
@ -962,8 +1142,9 @@ 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)
|
||||
bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix, selfAddrDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1593,7 +1774,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
|||
DbColumns: columnStats,
|
||||
About: Text.BlockbookAbout,
|
||||
}
|
||||
backendInfo := &BackendInfo{
|
||||
backendInfo := &common.BackendInfo{
|
||||
BackendError: backendError,
|
||||
BestBlockHash: ci.Bestblockhash,
|
||||
Blocks: ci.Blocks,
|
||||
|
@ -1606,7 +1787,9 @@ 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,8 +1,6 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/db"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
|
@ -11,6 +9,8 @@ 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, false)
|
||||
tx, err = w.GetTransaction(txid.txid, false, true)
|
||||
// mempool transaction may fail
|
||||
if err != nil || tx == nil {
|
||||
glog.Warning("GetTransaction in mempool: ", err)
|
||||
|
@ -606,12 +606,18 @@ 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)
|
||||
bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix, selfAddrDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package bchain
|
|||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type addrIndex struct {
|
||||
|
@ -27,6 +28,7 @@ type BaseMempool struct {
|
|||
txEntries map[string]txEntry
|
||||
addrDescToTx map[string][]Outpoint
|
||||
OnNewTxAddr OnNewTxAddrFunc
|
||||
OnNewTx OnNewTxFunc
|
||||
}
|
||||
|
||||
// GetTransactions returns slice of mempool transactions for given address
|
||||
|
@ -113,3 +115,22 @@ 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,6 +9,7 @@ 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
|
||||
|
@ -39,9 +40,9 @@ func (p *BaseParser) GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescri
|
|||
|
||||
const zeros = "0000000000000000000000000000000000000000"
|
||||
|
||||
// AmountToBigInt converts amount in json.Number (string) to big.Int
|
||||
// AmountToBigInt converts amount in common.JSONNumber (string) to big.Int
|
||||
// it uses string operations to avoid problems with rounding
|
||||
func (p *BaseParser) AmountToBigInt(n json.Number) (big.Int, error) {
|
||||
func (p *BaseParser) AmountToBigInt(n common.JSONNumber) (big.Int, error) {
|
||||
var r big.Int
|
||||
s := string(n)
|
||||
i := strings.IndexByte(s, '.')
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
// +build unittest
|
||||
|
||||
package bchain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/common"
|
||||
)
|
||||
|
||||
func NewBaseParser(adp int) *BaseParser {
|
||||
|
@ -44,7 +47,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(json.Number(tt.s))
|
||||
got, err := NewBaseParser(tt.adp).AmountToBigInt(common.JSONNumber(tt.s))
|
||||
if err != nil {
|
||||
t.Errorf("BaseParser.AmountToBigInt() error = %v", err)
|
||||
return
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"fmt"
|
||||
|
||||
"github.com/martinboehm/bchutil"
|
||||
|
@ -10,6 +8,8 @@ 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,8 +3,6 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,8 +1,6 @@
|
|||
package bch
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
@ -10,6 +8,8 @@ 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,10 +1,9 @@
|
|||
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,8 +3,6 @@
|
|||
package bellcoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,14 +3,15 @@
|
|||
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,11 +1,12 @@
|
|||
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.
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
// +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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
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,45 +1,6 @@
|
|||
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/omotenashicoin"
|
||||
"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"
|
||||
|
@ -49,6 +10,48 @@ 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)
|
||||
|
@ -59,14 +62,17 @@ 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
|
||||
|
@ -84,6 +90,7 @@ 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
|
||||
|
@ -91,7 +98,7 @@ func init() {
|
|||
BlockChainFactories["PIVX"] = pivx.NewPivXRPC
|
||||
BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC
|
||||
BlockChainFactories["Polis"] = polis.NewPolisRPC
|
||||
BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC
|
||||
BlockChainFactories["Firo"] = firo.NewFiroRPC
|
||||
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
|
||||
BlockChainFactories["Flo"] = flo.NewFloRPC
|
||||
BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC
|
||||
|
@ -107,9 +114,12 @@ 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
|
||||
|
@ -181,8 +191,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) error {
|
||||
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr)
|
||||
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr, onNewTx)
|
||||
}
|
||||
|
||||
func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
@ -16,8 +15,25 @@ 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)
|
||||
|
||||
|
@ -63,6 +79,8 @@ func GetChainParams(chain string) *chaincfg.Params {
|
|||
return &chaincfg.TestNet3Params
|
||||
case "regtest":
|
||||
return &chaincfg.RegressionNetParams
|
||||
case "signet":
|
||||
return &SigNetParams
|
||||
}
|
||||
return &chaincfg.MainNetParams
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -11,6 +10,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -259,10 +259,11 @@ func TestGetAddressesFromAddrDesc(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
testTx1, testTx2 bchain.Tx
|
||||
testTx1, testTx2, testTx3 bchain.Tx
|
||||
|
||||
testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700"
|
||||
testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000"
|
||||
testTxPacked3 = "00003d818bfda9aa3e02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -335,6 +336,54 @@ 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) {
|
||||
|
@ -372,6 +421,17 @@ 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) {
|
||||
|
@ -420,6 +480,16 @@ 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,7 +1,6 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
@ -17,6 +16,8 @@ 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.
|
||||
|
@ -154,12 +155,13 @@ 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) error {
|
||||
func (b *BitcoinRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) 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 {
|
||||
|
@ -237,13 +239,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 json.Number `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 common.JSONNumber `json:"difficulty"`
|
||||
SizeOnDisk int64 `json:"size_on_disk"`
|
||||
Warnings string `json:"warnings"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -256,11 +258,11 @@ type CmdGetNetworkInfo struct {
|
|||
type ResGetNetworkInfo struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result struct {
|
||||
Version json.Number `json:"version"`
|
||||
Subversion json.Number `json:"subversion"`
|
||||
ProtocolVersion json.Number `json:"protocolversion"`
|
||||
Timeoffset float64 `json:"timeoffset"`
|
||||
Warnings string `json:"warnings"`
|
||||
Version common.JSONNumber `json:"version"`
|
||||
Subversion common.JSONNumber `json:"subversion"`
|
||||
ProtocolVersion common.JSONNumber `json:"protocolversion"`
|
||||
Timeoffset float64 `json:"timeoffset"`
|
||||
Warnings string `json:"warnings"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -358,8 +360,8 @@ type CmdEstimateSmartFee struct {
|
|||
type ResEstimateSmartFee struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result struct {
|
||||
Feerate json.Number `json:"feerate"`
|
||||
Blocks int `json:"blocks"`
|
||||
Feerate common.JSONNumber `json:"feerate"`
|
||||
Blocks int `json:"blocks"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -373,8 +375,8 @@ type CmdEstimateFee struct {
|
|||
}
|
||||
|
||||
type ResEstimateFee struct {
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result json.Number `json:"result"`
|
||||
Error *bchain.RPCError `json:"error"`
|
||||
Result common.JSONNumber `json:"result"`
|
||||
}
|
||||
|
||||
// sendrawtransaction
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package btc
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -12,8 +11,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
)
|
||||
|
||||
// https://whatthefee.io returns
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package btg
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
@ -11,6 +8,9 @@ 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,7 +3,6 @@
|
|||
package btg
|
||||
|
||||
import (
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -13,6 +12,7 @@ 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,10 +1,9 @@
|
|||
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,11 +1,10 @@
|
|||
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,10 +1,8 @@
|
|||
// build unittest
|
||||
// +build unittest
|
||||
|
||||
package dash
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -13,6 +11,9 @@ 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,18 +9,19 @@ 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"
|
||||
"github.com/decred/dcrd/hdkeychain"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
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/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 (
|
||||
|
@ -65,9 +66,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
|
||||
}
|
||||
|
@ -203,7 +204,10 @@ func (p *DecredParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressD
|
|||
return nil, err
|
||||
}
|
||||
|
||||
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(txscript.DefaultScriptVersion, script, p.netConfig)
|
||||
const scriptVersion = 0
|
||||
const treasuryEnabled = true
|
||||
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(scriptVersion, script,
|
||||
p.netConfig, treasuryEnabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -241,7 +245,9 @@ func (p *DecredParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|||
}
|
||||
|
||||
func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
|
||||
var addr, err = extKey.Address(p.netConfig)
|
||||
pk := extKey.SerializedPubKey()
|
||||
hash := dcrutil.Hash160(pk)
|
||||
addr, err := dcrutil.NewAddressPubKeyHash(hash, p.netConfig, dcrec.STEcdsaSecp256k1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -252,7 +258,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)
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -283,7 +289,7 @@ func (p *DecredParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32
|
|||
if toIndex <= fromIndex {
|
||||
return nil, errors.New("toIndex<=fromIndex")
|
||||
}
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
||||
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
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,7 +1,6 @@
|
|||
package dcr
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -16,11 +15,12 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"blockbook/bchain/coins/btc"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson"
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
"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 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"`
|
||||
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"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
type GetBlockHeaderResult struct {
|
||||
Error Error `json:"error"`
|
||||
Result struct {
|
||||
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"`
|
||||
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"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
|
@ -297,8 +297,8 @@ type EstimateSmartFeeResult struct {
|
|||
}
|
||||
|
||||
type EstimateFeeResult struct {
|
||||
Error Error `json:"error"`
|
||||
Result json.Number `json:"result"`
|
||||
Error Error `json:"error"`
|
||||
Result common.JSONNumber `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: json.Number(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
|
||||
Difficulty: common.JSONNumber(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
|
||||
Txids: block.Result.Tx,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
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,8 +3,6 @@
|
|||
package deeponion
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,20 +1,21 @@
|
|||
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() {
|
||||
|
@ -23,6 +24,12 @@ 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
|
||||
|
@ -30,18 +37,27 @@ type DigiByteParser struct {
|
|||
*btc.BitcoinParser
|
||||
}
|
||||
|
||||
// NewDigiByteParser returns new VertcoinParser instance
|
||||
// NewDigiByteParser returns new DigiByteParser 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)
|
||||
}
|
||||
}
|
||||
return &MainNetParams
|
||||
switch chain {
|
||||
case "test":
|
||||
return &TestNetParams
|
||||
default:
|
||||
return &MainNetParams
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
package digibyte
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,20 +1,18 @@
|
|||
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,8 +3,6 @@
|
|||
package divi
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -16,6 +14,8 @@ 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,8 +3,6 @@
|
|||
package dogecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -16,6 +14,8 @@ 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,7 +1,6 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
@ -13,6 +12,7 @@ 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,24 +145,26 @@ func parseErc20StringProperty(contractDesc bchain.AddressDescriptor, data string
|
|||
n := parseErc20NumericProperty(contractDesc, data[64:128])
|
||||
if n != nil {
|
||||
l := n.Uint64()
|
||||
if 2*int(l) <= len(data)-128 {
|
||||
if l > 0 && 2*int(l) <= len(data)-128 {
|
||||
b, err := hex.DecodeString(data[128 : 128+2*l])
|
||||
if err == nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
if glog.V(1) {
|
||||
|
@ -181,18 +183,26 @@ func (b *EthereumRPC) EthereumTypeGetErc20ContractInfo(contractDesc bchain.Addre
|
|||
address := EIP55Address(contractDesc)
|
||||
data, err := b.ethCall(erc20NameSignature, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// 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)
|
||||
}
|
||||
name := parseErc20StringProperty(contractDesc, data)
|
||||
if name != "" {
|
||||
data, err = b.ethCall(erc20SymbolSignature, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
glog.Warning(errors.Annotatef(err, "erc20SymbolSignature %v", address))
|
||||
return nil, nil
|
||||
// return nil, errors.Annotatef(err, "erc20SymbolSignature %v", address)
|
||||
}
|
||||
symbol := parseErc20StringProperty(contractDesc, data)
|
||||
data, err = b.ethCall(erc20DecimalsSignature, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
glog.Warning(errors.Annotatef(err, "erc20DecimalsSignature %v", address))
|
||||
// return nil, errors.Annotatef(err, "erc20DecimalsSignature %v", address)
|
||||
}
|
||||
contract = &bchain.Erc20Contract{
|
||||
Contract: address,
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/tests/dbtestdata"
|
||||
fmt "fmt"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
|
||||
)
|
||||
|
||||
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
|
||||
|
@ -138,6 +139,16 @@ 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,7 +1,6 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
@ -9,6 +8,7 @@ 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"
|
||||
)
|
||||
|
||||
|
@ -311,8 +311,14 @@ func (p *EthereumParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) (
|
|||
if pt.Receipt.GasUsed, err = hexDecodeBig(r.Receipt.GasUsed); err != nil {
|
||||
return nil, errors.Annotatef(err, "GasUsed %v", r.Receipt.GasUsed)
|
||||
}
|
||||
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
|
||||
return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status)
|
||||
if r.Receipt.Status != "" {
|
||||
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
|
||||
return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status)
|
||||
}
|
||||
} else {
|
||||
// unknown status, use 'U' as status bytes
|
||||
// there is a potential for conflict with value 0x55 but this is not used by any chain at this moment
|
||||
pt.Receipt.Status = []byte{'U'}
|
||||
}
|
||||
ptLogs := make([]*ProtoCompleteTransaction_ReceiptType_LogType, len(r.Receipt.Logs))
|
||||
for i, l := range r.Receipt.Logs {
|
||||
|
@ -379,9 +385,14 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|||
Topics: topics,
|
||||
}
|
||||
}
|
||||
status := ""
|
||||
// handle a special value []byte{'U'} as unknown state
|
||||
if len(pt.Receipt.Status) != 1 || pt.Receipt.Status[0] != 'U' {
|
||||
status = hexEncodeBig(pt.Receipt.Status)
|
||||
}
|
||||
rr = &rpcReceipt{
|
||||
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
|
||||
Status: hexEncodeBig(pt.Receipt.Status),
|
||||
Status: status,
|
||||
Logs: logs,
|
||||
}
|
||||
}
|
||||
|
@ -461,40 +472,51 @@ 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 = iota - 2
|
||||
txStatusPending
|
||||
txStatusFailure
|
||||
txStatusOK
|
||||
TxStatusUnknown = TxStatus(iota - 2)
|
||||
TxStatusPending
|
||||
TxStatusFailure
|
||||
TxStatusOK
|
||||
)
|
||||
|
||||
// EthereumTxData contains ethereum specific transaction data
|
||||
type EthereumTxData struct {
|
||||
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending, -2 unknown
|
||||
Status TxStatus `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 {
|
||||
etd := EthereumTxData{Status: txStatusPending}
|
||||
csd, ok := tx.CoinSpecificData.(completeTransaction)
|
||||
return GetEthereumTxDataFromSpecificData(tx.CoinSpecificData)
|
||||
}
|
||||
|
||||
// GetEthereumTxDataFromSpecificData returns EthereumTxData from coinSpecificData
|
||||
func GetEthereumTxDataFromSpecificData(coinSpecificData interface{}) *EthereumTxData {
|
||||
etd := EthereumTxData{Status: TxStatusPending}
|
||||
csd, ok := 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,13 +3,14 @@
|
|||
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) {
|
||||
|
@ -67,7 +68,7 @@ func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var testTx1, testTx2 bchain.Tx
|
||||
var testTx1, testTx2, testTx1Failed, testTx1NoStatus bchain.Tx
|
||||
|
||||
func init() {
|
||||
|
||||
|
@ -155,6 +156,83 @@ func init() {
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
testTx1Failed = bchain.Tx{
|
||||
Blocktime: 1534858022,
|
||||
Time: 1534858022,
|
||||
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(1999622000000000000),
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
|
||||
},
|
||||
},
|
||||
},
|
||||
CoinSpecificData: completeTransaction{
|
||||
Tx: &rpcTransaction{
|
||||
AccountNonce: "0xb26c",
|
||||
GasPrice: "0x430e23400",
|
||||
GasLimit: "0x5208",
|
||||
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
|
||||
Value: "0x1bc0159d530e6000",
|
||||
Payload: "0x",
|
||||
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
||||
BlockNumber: "0x41eee8",
|
||||
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
|
||||
TransactionIndex: "0xa",
|
||||
},
|
||||
Receipt: &rpcReceipt{
|
||||
GasUsed: "0x5208",
|
||||
Status: "0x0",
|
||||
Logs: []*rpcLog{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testTx1NoStatus = bchain.Tx{
|
||||
Blocktime: 1534858022,
|
||||
Time: 1534858022,
|
||||
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(1999622000000000000),
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
|
||||
},
|
||||
},
|
||||
},
|
||||
CoinSpecificData: completeTransaction{
|
||||
Tx: &rpcTransaction{
|
||||
AccountNonce: "0xb26c",
|
||||
GasPrice: "0x430e23400",
|
||||
GasLimit: "0x5208",
|
||||
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
|
||||
Value: "0x1bc0159d530e6000",
|
||||
Payload: "0x",
|
||||
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
|
||||
BlockNumber: "0x41eee8",
|
||||
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
|
||||
TransactionIndex: "0xa",
|
||||
},
|
||||
Receipt: &rpcReceipt{
|
||||
GasUsed: "0x5208",
|
||||
Status: "",
|
||||
Logs: []*rpcLog{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestEthereumParser_PackTx(t *testing.T) {
|
||||
|
@ -188,6 +266,24 @@ func TestEthereumParser_PackTx(t *testing.T) {
|
|||
},
|
||||
want: dbtestdata.EthTx2Packed,
|
||||
},
|
||||
{
|
||||
name: "3",
|
||||
args: args{
|
||||
tx: &testTx1Failed,
|
||||
height: 4321000,
|
||||
blockTime: 1534858022,
|
||||
},
|
||||
want: dbtestdata.EthTx1FailedPacked,
|
||||
},
|
||||
{
|
||||
name: "4",
|
||||
args: args{
|
||||
tx: &testTx1NoStatus,
|
||||
height: 4321000,
|
||||
blockTime: 1534858022,
|
||||
},
|
||||
want: dbtestdata.EthTx1NoStatusPacked,
|
||||
},
|
||||
}
|
||||
p := NewEthereumParser(1)
|
||||
for _, tt := range tests {
|
||||
|
@ -229,6 +325,18 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
|
|||
want: &testTx2,
|
||||
want1: 4321000,
|
||||
},
|
||||
{
|
||||
name: "3",
|
||||
args: args{hex: dbtestdata.EthTx1FailedPacked},
|
||||
want: &testTx1Failed,
|
||||
want1: 4321000,
|
||||
},
|
||||
{
|
||||
name: "4",
|
||||
args: args{hex: dbtestdata.EthTx1NoStatusPacked},
|
||||
want: &testTx1NoStatus,
|
||||
want1: 4321000,
|
||||
},
|
||||
}
|
||||
p := NewEthereumParser(1)
|
||||
for _, tt := range tests {
|
||||
|
@ -265,3 +373,30 @@ 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,7 +1,6 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -12,11 +11,14 @@ 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
|
||||
|
@ -27,6 +29,8 @@ 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
|
||||
|
@ -158,6 +162,9 @@ 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)
|
||||
}
|
||||
|
@ -176,7 +183,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) error {
|
||||
func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||
if b.Mempool == nil {
|
||||
return errors.New("Mempool not created")
|
||||
}
|
||||
|
@ -191,6 +198,7 @@ func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOu
|
|||
}
|
||||
|
||||
b.Mempool.OnNewTxAddr = onNewTxAddr
|
||||
b.Mempool.OnNewTx = onNewTx
|
||||
|
||||
if err = b.subscribeEvents(); err != nil {
|
||||
return err
|
||||
|
@ -332,19 +340,15 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ver, protocol string
|
||||
var ver 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,
|
||||
ProtocolVersion: protocol,
|
||||
Blocks: int(h.Number.Int64()),
|
||||
Bestblockhash: h.Hash().Hex(),
|
||||
Difficulty: h.Difficulty.String(),
|
||||
Version: ver,
|
||||
}
|
||||
idi := int(id.Uint64())
|
||||
if idi == 1 {
|
||||
|
@ -569,8 +573,8 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
|||
}
|
||||
return &bchain.BlockInfo{
|
||||
BlockHeader: *bch,
|
||||
Difficulty: json.Number(head.Difficulty),
|
||||
Nonce: json.Number(head.Nonce),
|
||||
Difficulty: common.JSONNumber(head.Difficulty),
|
||||
Nonce: common.JSONNumber(head.Nonce),
|
||||
Txids: txs.Transactions,
|
||||
}, nil
|
||||
}
|
||||
|
@ -720,6 +724,18 @@ 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: tx.proto
|
||||
// source: bchain/coins/eth/ethtx.proto
|
||||
|
||||
/*
|
||||
Package eth is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
tx.proto
|
||||
bchain/coins/eth/ethtx.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ProtoCompleteTransaction
|
||||
|
@ -228,33 +228,34 @@ func init() {
|
|||
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
|
||||
func init() { proto.RegisterFile("bchain/coins/eth/ethtx.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 393 bytes of a gzipped FileDescriptorProto
|
||||
// 409 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x8a, 0xd4, 0x30,
|
||||
0x14, 0xc6, 0xe9, 0x9f, 0xf9, 0xb3, 0xa7, 0x55, 0x24, 0x88, 0x84, 0xe2, 0x45, 0x59, 0xbc, 0xa8,
|
||||
0x5e, 0x14, 0x5c, 0x7d, 0x81, 0x75, 0xc4, 0x55, 0x18, 0xd6, 0x21, 0x46, 0xef, 0xb3, 0x69, 0xd8,
|
||||
0x29, 0xb6, 0x4d, 0x69, 0x52, 0xe8, 0xbe, 0x91, 0x2f, 0xe4, 0xbb, 0x78, 0x29, 0x39, 0x4d, 0xd7,
|
||||
0x11, 0x51, 0xbc, 0x3b, 0xbf, 0x6f, 0xce, 0x37, 0xf9, 0xbe, 0xa4, 0xb0, 0xb5, 0x53, 0xd9, 0x0f,
|
||||
0xda, 0x6a, 0x12, 0x29, 0x7b, 0x3c, 0xff, 0xb6, 0x02, 0x7a, 0x70, 0xb8, 0xd3, 0x6d, 0xdf, 0x28,
|
||||
0xab, 0xf8, 0x20, 0x3a, 0x23, 0xa4, 0xad, 0x75, 0x47, 0x72, 0x48, 0xde, 0x34, 0x5a, 0x7e, 0xbd,
|
||||
0x1e, 0xdb, 0x1b, 0x35, 0xd0, 0x20, 0x0f, 0x8a, 0x07, 0xec, 0x54, 0x22, 0x4f, 0xe1, 0x0c, 0x91,
|
||||
0xd7, 0xad, 0xa2, 0x61, 0x1e, 0x14, 0x31, 0xfb, 0x25, 0x90, 0xd7, 0x10, 0xf2, 0x89, 0x46, 0x79,
|
||||
0x50, 0x24, 0x17, 0xcf, 0x4a, 0x65, 0x8f, 0xe5, 0xdf, 0x8e, 0x2a, 0xf9, 0xc4, 0xef, 0x7a, 0xc5,
|
||||
0x42, 0x3e, 0x91, 0x1d, 0x6c, 0x98, 0x92, 0xaa, 0xee, 0x2d, 0x8d, 0xd1, 0xfa, 0xfc, 0xdf, 0x56,
|
||||
0xbf, 0x8c, 0xfe, 0xc5, 0x99, 0xfd, 0x08, 0x60, 0x3d, 0xff, 0x27, 0x39, 0x87, 0xf4, 0x52, 0x4a,
|
||||
0x3d, 0x76, 0xf6, 0x5a, 0x77, 0x52, 0x61, 0x8d, 0x98, 0xfd, 0xa6, 0x91, 0x0c, 0xb6, 0x57, 0xc2,
|
||||
0x1c, 0x86, 0x5a, 0xce, 0x35, 0x52, 0x76, 0xcf, 0xfe, 0xb7, 0x7d, 0xdd, 0xd6, 0x16, 0xbb, 0xc4,
|
||||
0xec, 0x9e, 0xc9, 0x63, 0x58, 0x7d, 0x11, 0xcd, 0xa8, 0x30, 0x69, 0xca, 0x66, 0x20, 0x14, 0x36,
|
||||
0x07, 0x71, 0xd7, 0x68, 0x51, 0xd1, 0x15, 0xea, 0x0b, 0x12, 0x02, 0xf1, 0x7b, 0x61, 0x8e, 0x74,
|
||||
0x8d, 0x32, 0xce, 0xe4, 0x21, 0x84, 0x5c, 0xd3, 0x0d, 0x2a, 0x21, 0xd7, 0x6e, 0xe7, 0xdd, 0xa0,
|
||||
0x5b, 0xba, 0x9d, 0x77, 0xdc, 0x4c, 0x5e, 0xc0, 0xa3, 0x93, 0xca, 0x1f, 0xba, 0x4a, 0x4d, 0xf4,
|
||||
0x0c, 0x9f, 0xe3, 0x0f, 0x3d, 0xfb, 0x1e, 0x40, 0x72, 0x72, 0x27, 0x2e, 0xcd, 0x95, 0x30, 0x9f,
|
||||
0x8d, 0xaa, 0xb0, 0x7a, 0xca, 0x16, 0x24, 0x4f, 0x60, 0xfd, 0xc9, 0x0a, 0x3b, 0x1a, 0xdf, 0xd9,
|
||||
0x13, 0xd9, 0x41, 0xb4, 0xd7, 0xb7, 0x34, 0xca, 0xa3, 0x22, 0xb9, 0x78, 0xf9, 0xdf, 0xb7, 0x5f,
|
||||
0xee, 0xf5, 0x2d, 0xbe, 0x82, 0x73, 0x67, 0x1f, 0x61, 0xe3, 0xd9, 0x25, 0xb8, 0xac, 0xaa, 0x41,
|
||||
0x19, 0xb3, 0x24, 0xf0, 0xe8, 0xba, 0xbe, 0x15, 0x56, 0xf8, 0xf3, 0x71, 0x76, 0xa9, 0xb8, 0xee,
|
||||
0x6b, 0x69, 0x30, 0x40, 0xca, 0x3c, 0xdd, 0xac, 0xf1, 0xb3, 0x7d, 0xf5, 0x33, 0x00, 0x00, 0xff,
|
||||
0xff, 0xde, 0xd5, 0x28, 0xa3, 0xc2, 0x02, 0x00, 0x00,
|
||||
0x18, 0xc5, 0xe9, 0x9f, 0x99, 0xd9, 0xfd, 0xa6, 0x8a, 0x04, 0x91, 0x30, 0xec, 0x45, 0x59, 0xbc,
|
||||
0x18, 0xbd, 0xe8, 0xe2, 0xea, 0x0b, 0xac, 0x23, 0xae, 0xc2, 0xb0, 0x0e, 0x31, 0x7a, 0x9f, 0x49,
|
||||
0xc3, 0x36, 0x38, 0x6d, 0x4a, 0x93, 0x42, 0xf7, 0x8d, 0x7c, 0x21, 0xdf, 0xc5, 0x4b, 0xc9, 0xd7,
|
||||
0x74, 0x1d, 0x11, 0x65, 0x2f, 0x0a, 0xf9, 0x9d, 0x7e, 0xa7, 0x39, 0x27, 0x29, 0x9c, 0xed, 0x65,
|
||||
0x25, 0x74, 0x73, 0x21, 0x8d, 0x6e, 0xec, 0x85, 0x72, 0x95, 0x7f, 0xdc, 0x50, 0xb4, 0x9d, 0x71,
|
||||
0x86, 0x24, 0xca, 0x55, 0xe7, 0xdf, 0x67, 0x40, 0x77, 0x1e, 0x37, 0xa6, 0x6e, 0x0f, 0xca, 0x29,
|
||||
0xde, 0x89, 0xc6, 0x0a, 0xe9, 0xb4, 0x69, 0x48, 0x0e, 0xcb, 0xb7, 0x07, 0x23, 0xbf, 0xdd, 0xf4,
|
||||
0xf5, 0x5e, 0x75, 0x34, 0xca, 0xa3, 0xf5, 0x23, 0x76, 0x2c, 0x91, 0x33, 0x38, 0x45, 0xe4, 0xba,
|
||||
0x56, 0x34, 0xce, 0xa3, 0x75, 0xca, 0x7e, 0x0b, 0xe4, 0x0d, 0xc4, 0x7c, 0xa0, 0x49, 0x1e, 0xad,
|
||||
0x97, 0x97, 0xcf, 0x0b, 0xe5, 0xaa, 0xe2, 0x5f, 0x5b, 0x15, 0x7c, 0xe0, 0x77, 0xad, 0x62, 0x31,
|
||||
0x1f, 0xc8, 0x06, 0x16, 0x4c, 0x49, 0xa5, 0x5b, 0x47, 0x53, 0xb4, 0xbe, 0xf8, 0xbf, 0x35, 0x0c,
|
||||
0xa3, 0x7f, 0x72, 0xae, 0x7e, 0x46, 0x30, 0x1f, 0xbf, 0x49, 0xce, 0x21, 0xbb, 0x92, 0xd2, 0xf4,
|
||||
0x8d, 0xbb, 0x31, 0x8d, 0x54, 0x58, 0x23, 0x65, 0x7f, 0x68, 0x64, 0x05, 0x27, 0xd7, 0xc2, 0xee,
|
||||
0x3a, 0x2d, 0xc7, 0x1a, 0x19, 0xbb, 0xe7, 0xf0, 0x6e, 0xab, 0x6b, 0xed, 0xb0, 0x4b, 0xca, 0xee,
|
||||
0x99, 0x3c, 0x85, 0xd9, 0x57, 0x71, 0xe8, 0x15, 0x26, 0xcd, 0xd8, 0x08, 0x84, 0xc2, 0x62, 0x27,
|
||||
0xee, 0x0e, 0x46, 0x94, 0x74, 0x86, 0xfa, 0x84, 0x84, 0x40, 0xfa, 0x41, 0xd8, 0x8a, 0xce, 0x51,
|
||||
0xc6, 0x35, 0x79, 0x0c, 0x31, 0x37, 0x74, 0x81, 0x4a, 0xcc, 0x8d, 0x9f, 0x79, 0xdf, 0x99, 0x9a,
|
||||
0x9e, 0x8c, 0x33, 0x7e, 0x4d, 0x5e, 0xc2, 0x93, 0xa3, 0xca, 0x1f, 0x9b, 0x52, 0x0d, 0xf4, 0x14,
|
||||
0xaf, 0xe3, 0x2f, 0x7d, 0xf5, 0x23, 0x82, 0xe5, 0xd1, 0x99, 0xf8, 0x34, 0xd7, 0xc2, 0x7e, 0xb1,
|
||||
0xaa, 0xc4, 0xea, 0x19, 0x9b, 0x90, 0x3c, 0x83, 0xf9, 0x67, 0x27, 0x5c, 0x6f, 0x43, 0xe7, 0x40,
|
||||
0x64, 0x03, 0xc9, 0xd6, 0xdc, 0xd2, 0x24, 0x4f, 0xd6, 0xcb, 0xcb, 0x57, 0x0f, 0x3e, 0xfd, 0x62,
|
||||
0x6b, 0x6e, 0xf1, 0x16, 0xbc, 0x7b, 0xf5, 0x09, 0x16, 0x81, 0x7d, 0x82, 0xab, 0xb2, 0xec, 0x94,
|
||||
0xb5, 0x53, 0x82, 0x80, 0xbe, 0xeb, 0x3b, 0xe1, 0x44, 0xd8, 0x1f, 0xd7, 0x3e, 0x15, 0x37, 0xad,
|
||||
0x96, 0x16, 0x03, 0x64, 0x2c, 0xd0, 0x7e, 0x8e, 0xbf, 0xed, 0xeb, 0x5f, 0x01, 0x00, 0x00, 0xff,
|
||||
0xff, 0xc2, 0x69, 0x8d, 0xdf, 0xd6, 0x02, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
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,8 +1,6 @@
|
|||
package xzc
|
||||
package firo
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
|
@ -11,13 +9,18 @@ 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"
|
||||
)
|
||||
|
||||
const (
|
||||
OpZeroCoinMint = 0xc1
|
||||
OpZeroCoinSpend = 0xc2
|
||||
OpSigmaMint = 0xc3
|
||||
OpSigmaSpend = 0xc4
|
||||
OpZeroCoinMint = 0xc1
|
||||
OpZeroCoinSpend = 0xc2
|
||||
OpSigmaMint = 0xc3
|
||||
OpSigmaSpend = 0xc4
|
||||
OpLelantusMint = 0xc5
|
||||
OpLelantusJMint = 0xc6
|
||||
OpLelantusJoinSplit = 0xc7
|
||||
|
||||
MainnetMagic wire.BitcoinNet = 0xe3d9fef1
|
||||
TestnetMagic wire.BitcoinNet = 0xcffcbeea
|
||||
|
@ -28,6 +31,8 @@ const (
|
|||
MTPL = 64
|
||||
|
||||
SpendTxID = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
TransactionQuorumCommitmentType = 6
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -58,21 +63,21 @@ func init() {
|
|||
RegtestParams.Net = RegtestMagic
|
||||
}
|
||||
|
||||
// ZcoinParser handle
|
||||
type ZcoinParser struct {
|
||||
// FiroParser handle
|
||||
type FiroParser struct {
|
||||
*btc.BitcoinParser
|
||||
}
|
||||
|
||||
// NewZcoinParser returns new ZcoinParser instance
|
||||
func NewZcoinParser(params *chaincfg.Params, c *btc.Configuration) *ZcoinParser {
|
||||
return &ZcoinParser{
|
||||
// NewFiroParser returns new FiroParser instance
|
||||
func NewFiroParser(params *chaincfg.Params, c *btc.Configuration) *FiroParser {
|
||||
return &FiroParser{
|
||||
BitcoinParser: btc.NewBitcoinParser(params, c),
|
||||
}
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main Zcoin network,
|
||||
// the regression test Zcoin network, the test Zcoin network and
|
||||
// the simulation test Zcoin network, in this order
|
||||
// GetChainParams contains network parameters for the main Firo network,
|
||||
// the regression test Firo network, the test Firo network and
|
||||
// the simulation test Firo network, in this order
|
||||
func GetChainParams(chain string) *chaincfg.Params {
|
||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||
err := chaincfg.Register(&MainNetParams)
|
||||
|
@ -97,7 +102,7 @@ func GetChainParams(chain string) *chaincfg.Params {
|
|||
}
|
||||
|
||||
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
|
||||
func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
|
||||
func (p *FiroParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
|
||||
|
||||
if len(addrDesc) > 0 {
|
||||
switch addrDesc[0] {
|
||||
|
@ -109,6 +114,12 @@ func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor
|
|||
return []string{"Sigmamint"}, false, nil
|
||||
case OpSigmaSpend:
|
||||
return []string{"Sigmaspend"}, false, nil
|
||||
case OpLelantusMint:
|
||||
return []string{"LelantusMint"}, false, nil
|
||||
case OpLelantusJMint:
|
||||
return []string{"LelantusJMint"}, false, nil
|
||||
case OpLelantusJoinSplit:
|
||||
return []string{"LelantusJoinSplit"}, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,17 +127,27 @@ func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor
|
|||
}
|
||||
|
||||
// PackTx packs transaction to byte array using protobuf
|
||||
func (p *ZcoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
|
||||
func (p *FiroParser) 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 *ZcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
func (p *FiroParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
return p.BaseParser.UnpackTx(buf)
|
||||
}
|
||||
|
||||
// TxFromFiroMsgTx converts bitcoin wire Tx to bchain.Tx
|
||||
func (p *FiroParser) TxFromFiroMsgTx(t *FiroMsgTx, parseAddresses bool) bchain.Tx {
|
||||
btx := p.TxFromMsgTx(&t.MsgTx, parseAddresses)
|
||||
|
||||
// NOTE: wire.MsgTx.TxHash() doesn't include extra
|
||||
btx.Txid = t.TxHash().String()
|
||||
|
||||
return btx
|
||||
}
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
func (p *FiroParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
reader := bytes.NewReader(b)
|
||||
|
||||
// parse standard block header first
|
||||
|
@ -181,16 +202,37 @@ func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
|||
txs := make([]bchain.Tx, ntx)
|
||||
|
||||
for i := uint64(0); i < ntx; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
tx := FiroMsgTx{}
|
||||
|
||||
err := tx.BtcDecode(reader, 0, wire.WitnessEncoding)
|
||||
if err != nil {
|
||||
// read version and seek back
|
||||
var version uint32 = 0
|
||||
if err = binary.Read(reader, binary.LittleEndian, &version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btx := p.TxFromMsgTx(&tx, false)
|
||||
if _, err = reader.Seek(-4, io.SeekCurrent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.parseZcoinTx(&btx)
|
||||
txVersion := version & 0xffff
|
||||
txType := (version >> 16) & 0xffff
|
||||
|
||||
enc := wire.WitnessEncoding
|
||||
|
||||
// transaction quorum commitment could not be parsed with witness flag
|
||||
if txVersion == 3 && txType == TransactionQuorumCommitmentType {
|
||||
enc = wire.BaseEncoding
|
||||
}
|
||||
|
||||
if err = tx.FiroDecode(reader, 0, enc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btx := p.TxFromFiroMsgTx(&tx, false)
|
||||
|
||||
if err = p.parseFiroTx(&btx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txs[i] = btx
|
||||
}
|
||||
|
@ -205,7 +247,7 @@ func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
|||
}
|
||||
|
||||
// ParseTxFromJson parses JSON message containing transaction and returns Tx struct
|
||||
func (p *ZcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
|
||||
func (p *FiroParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
|
||||
var tx bchain.Tx
|
||||
err := json.Unmarshal(msg, &tx)
|
||||
if err != nil {
|
||||
|
@ -222,12 +264,12 @@ func (p *ZcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
|
|||
vout.JsonValue = ""
|
||||
}
|
||||
|
||||
p.parseZcoinTx(&tx)
|
||||
p.parseFiroTx(&tx)
|
||||
|
||||
return &tx, nil
|
||||
}
|
||||
|
||||
func (p *ZcoinParser) parseZcoinTx(tx *bchain.Tx) error {
|
||||
func (p *FiroParser) parseFiroTx(tx *bchain.Tx) error {
|
||||
for i := range tx.Vin {
|
||||
vin := &tx.Vin[i]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// +build unittest
|
||||
|
||||
package xzc
|
||||
package firo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -13,17 +13,18 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
testTx1, testTx2, testTx3, testTx4 bchain.Tx
|
||||
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4 string
|
||||
rawBlock1, rawBlock2 string
|
||||
jsonTx json.RawMessage
|
||||
testTx1, testTx2, testTx3, testTx4, testTx5, testTx6 bchain.Tx
|
||||
rawTestTx1, rawTestTx2, rawTestTx3, rawTestTx4, rawTestTx5, rawTestTx6 string
|
||||
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4, testTxPacked5, testTxPacked6 string
|
||||
rawBlock1, rawBlock2, rawBlock3 string
|
||||
jsonTx json.RawMessage
|
||||
)
|
||||
|
||||
func readHexs(path string) []string {
|
||||
|
@ -40,12 +41,15 @@ func init() {
|
|||
rawBlocks := readHexs("./testdata/rawblock.hex")
|
||||
rawBlock1 = rawBlocks[0]
|
||||
rawBlock2 = rawBlocks[1]
|
||||
rawBlock3 = rawBlocks[2]
|
||||
|
||||
hextxs := readHexs("./testdata/txs.hex")
|
||||
rawTestTx1 := hextxs[0]
|
||||
rawTestTx2 := hextxs[1]
|
||||
rawTestTx3 := hextxs[2]
|
||||
rawTestTx4 := hextxs[3]
|
||||
rawTestTx1 = hextxs[0]
|
||||
rawTestTx2 = hextxs[1]
|
||||
rawTestTx3 = hextxs[2]
|
||||
rawTestTx4 = hextxs[3]
|
||||
rawTestTx5 = hextxs[4]
|
||||
rawTestTx6 = hextxs[5]
|
||||
|
||||
rawSpendHex := readHexs("./testdata/rawspend.hex")[0]
|
||||
|
||||
|
@ -60,13 +64,15 @@ func init() {
|
|||
testTxPacked2 = testTxPackeds[1]
|
||||
testTxPacked3 = testTxPackeds[2]
|
||||
testTxPacked4 = testTxPackeds[3]
|
||||
testTxPacked5 = testTxPackeds[4]
|
||||
testTxPacked6 = testTxPackeds[5]
|
||||
|
||||
testTx1 = bchain.Tx{
|
||||
Hex: rawTestTx1,
|
||||
Blocktime: 1533980594,
|
||||
Time: 1533980594,
|
||||
Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23",
|
||||
LockTime: 0,
|
||||
LockTime: 99688,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
|
@ -79,14 +85,14 @@ func init() {
|
|||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(18188266638),
|
||||
ValueSat: *big.NewInt(100000000),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(18188266638),
|
||||
ValueSat: *big.NewInt(871824000),
|
||||
N: 1,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac",
|
||||
|
@ -106,9 +112,7 @@ func init() {
|
|||
LockTime: 0,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
ScriptSig: bchain.ScriptSig{
|
||||
Hex: rawSpendHex,
|
||||
},
|
||||
Coinbase: rawSpendHex,
|
||||
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
Vout: 4294967295,
|
||||
Sequence: 2,
|
||||
|
@ -227,7 +231,7 @@ func init() {
|
|||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac",
|
||||
Addresses: []string{
|
||||
"a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3",
|
||||
"aQ18FBVFtnueucZKeVg4srhmzbpAeb1KoN",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -251,6 +255,103 @@ func init() {
|
|||
},
|
||||
},
|
||||
},
|
||||
// TODO: test segwit
|
||||
},
|
||||
}
|
||||
|
||||
testTx5 = bchain.Tx{
|
||||
Hex: rawTestTx5,
|
||||
Blocktime: 1591752749,
|
||||
Time: 1591752749,
|
||||
Txid: "8d1f32f35c32d2c127a7400dc1ec52049fbf0b8bcdf284cfaa3da59b6169a22d",
|
||||
LockTime: 0,
|
||||
Vin: []bchain.Vin{},
|
||||
Vout: []bchain.Vout{},
|
||||
}
|
||||
|
||||
testTx6 = bchain.Tx{
|
||||
Hex: rawTestTx6,
|
||||
Blocktime: 1591762049,
|
||||
Time: 1591762049,
|
||||
Txid: "e5767d3606230a65f150837a6f28b4f0e4c2702a683045df3883d57702739c61",
|
||||
LockTime: 0,
|
||||
Vin: []bchain.Vin{
|
||||
{
|
||||
Coinbase: "02b4140101",
|
||||
Sequence: 4294967295,
|
||||
},
|
||||
},
|
||||
Vout: []bchain.Vout{
|
||||
{
|
||||
ValueSat: *big.NewInt(1400000000),
|
||||
N: 0,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "2103fb09a216761d5e7f248294970c2370f7f84ce1ad564b8e7096b1e19116af1d52ac",
|
||||
Addresses: []string{
|
||||
"TAn9Ghkp31myXRgejCj11wWVHT14Lsj349",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(50000000),
|
||||
N: 1,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914296134d2415bf1f2b518b3f673816d7e603b160088ac",
|
||||
Addresses: []string{
|
||||
"TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(50000000),
|
||||
N: 2,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914e1e1dc06a889c1b6d3eb00eef7a96f6a7cfb884888ac",
|
||||
Addresses: []string{
|
||||
"TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(50000000),
|
||||
N: 3,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a914ab03ecfddee6330497be894d16c29ae341c123aa88ac",
|
||||
Addresses: []string{
|
||||
"TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(150000000),
|
||||
N: 4,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a9144281a58a1d5b2d3285e00cb45a8492debbdad4c588ac",
|
||||
Addresses: []string{
|
||||
"TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(50000000),
|
||||
N: 5,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a9141fd264c0bb53bd9fef18e2248ddf1383d6e811ae88ac",
|
||||
Addresses: []string{
|
||||
"TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ValueSat: *big.NewInt(750000000),
|
||||
N: 6,
|
||||
ScriptPubKey: bchain.ScriptPubKey{
|
||||
Hex: "76a91471a3892d164ffa3829078bf9ad5f114a3908ce5588ac",
|
||||
Addresses: []string{
|
||||
"TLL5GQULX4uBfz7yXL6VcZyvzdKVv1RGxm",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -264,32 +365,32 @@ func TestMain(m *testing.M) {
|
|||
func TestGetAddrDesc(t *testing.T) {
|
||||
type args struct {
|
||||
tx bchain.Tx
|
||||
parser *ZcoinParser
|
||||
parser *FiroParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "xzc-1",
|
||||
name: "firo-1",
|
||||
args: args{
|
||||
tx: testTx1,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
},
|
||||
// FIXME: work around handle zerocoin spend as coinbase
|
||||
// {
|
||||
// name: "xzc-2",
|
||||
// name: "firo-2",
|
||||
// args: args{
|
||||
// tx: testTx2,
|
||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// },
|
||||
// },
|
||||
{
|
||||
name: "xzc-3",
|
||||
name: "firo-3",
|
||||
args: args{
|
||||
tx: testTx3,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -347,7 +448,7 @@ func TestGetAddrDescFromVoutForMint(t *testing.T) {
|
|||
wantErr: false,
|
||||
},
|
||||
}
|
||||
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
|
||||
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -397,7 +498,7 @@ func TestGetAddressesFromAddrDescForMint(t *testing.T) {
|
|||
wantErr: false,
|
||||
},
|
||||
}
|
||||
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
|
||||
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -422,7 +523,7 @@ func TestPackTx(t *testing.T) {
|
|||
tx bchain.Tx
|
||||
height uint32
|
||||
blockTime int64
|
||||
parser *ZcoinParser
|
||||
parser *FiroParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -431,50 +532,72 @@ func TestPackTx(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "xzc-1",
|
||||
name: "firo-1",
|
||||
args: args{
|
||||
tx: testTx1,
|
||||
height: 100002,
|
||||
blockTime: 1533980594,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked1,
|
||||
wantErr: false,
|
||||
},
|
||||
// FIXME: work around handle zerocoin spend as coinbase
|
||||
// {
|
||||
// name: "xzc-2",
|
||||
// name: "firo-2",
|
||||
// args: args{
|
||||
// tx: testTx2,
|
||||
// height: 11002,
|
||||
// blockTime: 1481277009,
|
||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// },
|
||||
// want: testTxPacked2,
|
||||
// wantErr: true,
|
||||
// },
|
||||
{
|
||||
name: "xzc-3",
|
||||
name: "firo-3",
|
||||
args: args{
|
||||
tx: testTx3,
|
||||
height: 126202,
|
||||
blockTime: 1547091829,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "xzc-coinbase",
|
||||
name: "firo-coinbase",
|
||||
args: args{
|
||||
tx: testTx4,
|
||||
height: 100001,
|
||||
blockTime: 1533977563,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked4,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "firo-quorum-commitment-tx",
|
||||
args: args{
|
||||
tx: testTx5,
|
||||
height: 5268,
|
||||
blockTime: 1591752749,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked5,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "firo-special-coinbase-tx",
|
||||
args: args{
|
||||
tx: testTx6,
|
||||
height: 5300,
|
||||
blockTime: 1591762049,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTxPacked6,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -496,7 +619,7 @@ func TestPackTx(t *testing.T) {
|
|||
func TestUnpackTx(t *testing.T) {
|
||||
type args struct {
|
||||
packedTx string
|
||||
parser *ZcoinParser
|
||||
parser *FiroParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -506,10 +629,10 @@ func TestUnpackTx(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "xzc-1",
|
||||
name: "firo-1",
|
||||
args: args{
|
||||
packedTx: testTxPacked1,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx1,
|
||||
want1: 100002,
|
||||
|
@ -517,35 +640,55 @@ func TestUnpackTx(t *testing.T) {
|
|||
},
|
||||
// FIXME: work around handle zerocoin spend as coinbase
|
||||
// {
|
||||
// name: "xzc-2",
|
||||
// name: "firo-2",
|
||||
// args: args{
|
||||
// packedTx: testTxPacked2,
|
||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
// },
|
||||
// want: &testTx2,
|
||||
// want1: 11002,
|
||||
// wantErr: true,
|
||||
// },
|
||||
{
|
||||
name: "xzc-3",
|
||||
name: "firo-3",
|
||||
args: args{
|
||||
packedTx: testTxPacked3,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx3,
|
||||
want1: 126202,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "xzc-coinbase",
|
||||
name: "firo-coinbase",
|
||||
args: args{
|
||||
packedTx: testTxPacked4,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx4,
|
||||
want1: 100001,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "firo-special-tx",
|
||||
args: args{
|
||||
packedTx: testTxPacked5,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx5,
|
||||
want1: 5268,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "firo-special-coinbase-tx",
|
||||
args: args{
|
||||
packedTx: testTxPacked6,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: &testTx6,
|
||||
want1: 5300,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -571,7 +714,7 @@ func TestUnpackTx(t *testing.T) {
|
|||
func TestParseBlock(t *testing.T) {
|
||||
type args struct {
|
||||
rawBlock string
|
||||
parser *ZcoinParser
|
||||
parser *FiroParser
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -584,7 +727,7 @@ func TestParseBlock(t *testing.T) {
|
|||
name: "normal-block",
|
||||
args: args{
|
||||
rawBlock: rawBlock1,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
|
@ -599,7 +742,7 @@ func TestParseBlock(t *testing.T) {
|
|||
name: "spend-block",
|
||||
args: args{
|
||||
rawBlock: rawBlock2,
|
||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
|
@ -610,6 +753,21 @@ func TestParseBlock(t *testing.T) {
|
|||
wantTxs: 4,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "special-tx-block",
|
||||
args: args{
|
||||
rawBlock: rawBlock3,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
Size: 200062,
|
||||
Time: 1591752749,
|
||||
},
|
||||
},
|
||||
wantTxs: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -633,3 +791,191 @@ func TestParseBlock(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeTransaction(t *testing.T) {
|
||||
type args struct {
|
||||
enc wire.MessageEncoding
|
||||
rawTransaction string
|
||||
parser *FiroParser
|
||||
privacyType byte // 0 as non privacy
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bchain.Tx
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "normal-transaction",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx1,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTx1,
|
||||
},
|
||||
{
|
||||
name: "coinbase-firospend",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx2,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
privacyType: OpSigmaSpend,
|
||||
},
|
||||
want: testTx2,
|
||||
},
|
||||
{
|
||||
name: "normal-transaction-2",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx3,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTx3,
|
||||
},
|
||||
{
|
||||
name: "coinbase-transaction",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx4,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTx4,
|
||||
},
|
||||
{
|
||||
name: "quorum-commitment-transaction",
|
||||
args: args{
|
||||
enc: wire.BaseEncoding,
|
||||
rawTransaction: rawTestTx5,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTx5,
|
||||
},
|
||||
{
|
||||
name: "quorum-commitment-transaction-witness",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx5,
|
||||
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "special-coinbase",
|
||||
args: args{
|
||||
enc: wire.WitnessEncoding,
|
||||
rawTransaction: rawTestTx6,
|
||||
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
|
||||
},
|
||||
want: testTx6,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, _ := hex.DecodeString(tt.args.rawTransaction)
|
||||
r := bytes.NewReader(b)
|
||||
|
||||
msg := FiroMsgTx{}
|
||||
err := msg.FiroDecode(r, 0, tt.args.enc)
|
||||
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("Want error")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got := tt.args.parser.TxFromFiroMsgTx(&msg, true)
|
||||
if pErr := tt.args.parser.parseFiroTx(&got); pErr != nil {
|
||||
t.Fatal(pErr)
|
||||
}
|
||||
|
||||
if r.Len() != 0 {
|
||||
t.Errorf("Expected EOF but there are remaining %d bytes to read", r.Len())
|
||||
}
|
||||
|
||||
if len(got.Vin) != len(tt.want.Vin) {
|
||||
t.Errorf("Check vin size, got %v, want %v", len(got.Vin), len(tt.want.Vin))
|
||||
}
|
||||
|
||||
for i := 0; i != len(got.Vin); i++ {
|
||||
if !reflect.DeepEqual(got.Vin[i].Addresses, tt.want.Vin[i].Addresses) {
|
||||
t.Errorf("Check Addresses at input %d, got %v, want %v",
|
||||
i, got.Vin[i].Addresses, tt.want.Vin[i].Addresses)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase) {
|
||||
t.Errorf("Check Coinbase at input %d, got %v, want %v",
|
||||
i, got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig) {
|
||||
t.Errorf("Check ScriptSig at input %d, got %v, want %v",
|
||||
i, got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vin[i].Sequence, tt.want.Vin[i].Sequence) {
|
||||
t.Errorf("Check Sequence at input %d, got %v, want %v",
|
||||
i, got.Vin[i].Sequence, tt.want.Vin[i].Sequence)
|
||||
}
|
||||
|
||||
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Txid, tt.want.Vin[i].Txid) {
|
||||
t.Errorf("Check Txid at input %d, got %v, want %v",
|
||||
i, got.Vin[i].Txid, tt.want.Vin[i].Txid)
|
||||
}
|
||||
|
||||
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Vout, tt.want.Vin[i].Vout) {
|
||||
t.Errorf("Check Vout at input %d, got %v, want %v",
|
||||
i, got.Vin[i].Vout, tt.want.Vin[i].Vout)
|
||||
}
|
||||
}
|
||||
|
||||
if len(got.Vout) != len(tt.want.Vout) {
|
||||
t.Errorf("Check vout size, got %v, want %v", len(got.Vout), len(tt.want.Vout))
|
||||
}
|
||||
|
||||
for i := 0; i != len(got.Vout); i++ {
|
||||
if !reflect.DeepEqual(got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue) {
|
||||
t.Errorf("Check JsonValue at output %d, got %v, want %v",
|
||||
i, got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vout[i].N, tt.want.Vout[i].N) {
|
||||
t.Errorf("Check N at output %d, got %v, want %v",
|
||||
i, got.Vout[i].N, tt.want.Vout[i].N)
|
||||
}
|
||||
|
||||
// empty addresses and null should be the same
|
||||
if !((len(got.Vout[i].ScriptPubKey.Addresses) == 0 && len(got.Vout[i].ScriptPubKey.Addresses) == len(tt.want.Vout[i].ScriptPubKey.Addresses)) ||
|
||||
reflect.DeepEqual(got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)) {
|
||||
t.Errorf("Check ScriptPubKey.Addresses at output %d, got %v, want %v",
|
||||
i, got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex) {
|
||||
t.Errorf("Check ScriptPubKey.Hex at output %d, got %v, want %v",
|
||||
i, got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat) {
|
||||
t.Errorf("Check ValueSat at output %d, got %v, want %v",
|
||||
i, got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat)
|
||||
}
|
||||
}
|
||||
|
||||
if got.LockTime != tt.want.LockTime {
|
||||
t.Errorf("Check LockTime, got %v, want %v", got.LockTime, tt.want.LockTime)
|
||||
}
|
||||
|
||||
if got.Txid != tt.want.Txid {
|
||||
t.Errorf("Check TxId, got %v, want %v", got.Txid, tt.want.Txid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,28 +1,28 @@
|
|||
package xzc
|
||||
package firo
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
type ZcoinRPC struct {
|
||||
type FiroRPC struct {
|
||||
*btc.BitcoinRPC
|
||||
}
|
||||
|
||||
func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||
func NewFiroRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||
// init base implementation
|
||||
bc, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// init zcoin implementation
|
||||
zc := &ZcoinRPC{
|
||||
// init firo implementation
|
||||
zc := &FiroRPC{
|
||||
BitcoinRPC: bc.(*btc.BitcoinRPC),
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationTyp
|
|||
return zc, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) Initialize() error {
|
||||
func (zc *FiroRPC) Initialize() error {
|
||||
ci, err := zc.GetChainInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -45,7 +45,7 @@ func (zc *ZcoinRPC) Initialize() error {
|
|||
params := GetChainParams(chainName)
|
||||
|
||||
// always create parser
|
||||
zc.Parser = NewZcoinParser(params, zc.ChainConfig)
|
||||
zc.Parser = NewFiroParser(params, zc.ChainConfig)
|
||||
|
||||
// parameters for getInfo request
|
||||
if params.Net == MainnetMagic {
|
||||
|
@ -61,7 +61,7 @@ func (zc *ZcoinRPC) Initialize() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
|
||||
func (zc *FiroRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
|
||||
var err error
|
||||
|
||||
if hash == "" {
|
||||
|
@ -96,7 +96,7 @@ func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error)
|
|||
return block, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||
func (zc *FiroRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||
glog.V(1).Info("rpc: getblock (verbosity=true) ", hash)
|
||||
|
||||
res := btc.ResGetBlockInfo{}
|
||||
|
@ -117,7 +117,7 @@ func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
|||
return &res.Result, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.Block, error) {
|
||||
func (zc *FiroRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.Block, error) {
|
||||
data, err := zc.GetBlockRaw(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -134,7 +134,7 @@ func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.B
|
|||
return block, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
|
||||
func (zc *FiroRPC) GetBlockRaw(hash string) ([]byte, error) {
|
||||
glog.V(1).Info("rpc: getblock (verbosity=false) ", hash)
|
||||
|
||||
res := btc.ResGetBlockRaw{}
|
||||
|
@ -155,7 +155,7 @@ func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
|
|||
return hex.DecodeString(res.Result)
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||
func (zc *FiroRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||
glog.V(1).Info("rpc: getrawtransaction nonverbose ", txid)
|
||||
|
||||
res := btc.ResGetRawTransactionNonverbose{}
|
||||
|
@ -183,7 +183,7 @@ func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
|||
return tx, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
||||
func (zc *FiroRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
||||
r, err := zc.getRawTransaction(txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -198,14 +198,14 @@ func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
|||
return tx, nil
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) {
|
||||
func (zc *FiroRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) {
|
||||
if csd, ok := tx.CoinSpecificData.(json.RawMessage); ok {
|
||||
return csd, nil
|
||||
}
|
||||
return zc.getRawTransaction(tx.Txid)
|
||||
}
|
||||
|
||||
func (zc *ZcoinRPC) getRawTransaction(txid string) (json.RawMessage, error) {
|
||||
func (zc *FiroRPC) getRawTransaction(txid string) (json.RawMessage, error) {
|
||||
glog.V(1).Info("rpc: getrawtransaction ", txid)
|
||||
|
||||
res := btc.ResGetRawTransaction{}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,11 +1,10 @@
|
|||
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,13 +1,12 @@
|
|||
package flo
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||
)
|
||||
|
||||
// FloRPC is an interface to JSON-RPC bitcoind service.
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
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,8 +3,6 @@
|
|||
package fujicoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,10 +1,9 @@
|
|||
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,8 +3,6 @@
|
|||
package gamecredits
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,12 +1,11 @@
|
|||
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,8 +3,6 @@
|
|||
package grs
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
@ -13,6 +11,8 @@ 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,11 +1,10 @@
|
|||
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,8 +3,6 @@
|
|||
package koto
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
@ -13,6 +11,8 @@ 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,16 +1,15 @@
|
|||
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,8 +3,6 @@
|
|||
package liquid
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,10 +1,9 @@
|
|||
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,8 +3,6 @@
|
|||
package litecoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,10 +1,9 @@
|
|||
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,8 +3,6 @@
|
|||
package monacoin
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,18 +1,17 @@
|
|||
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,8 +3,6 @@
|
|||
package monetaryunit
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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,8 +3,6 @@
|
|||
package myriad
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -12,6 +10,8 @@ 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.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue