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
|
docker/blockbook
|
||||||
build/pkg-defs
|
build/pkg-defs
|
||||||
build/blockbook
|
build/blockbook
|
||||||
|
build/blockchaincfg.json
|
||||||
build/ldb
|
build/ldb
|
||||||
build/sst_dump
|
build/sst_dump
|
||||||
build/*.deb
|
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
|
BIN_IMAGE = blockbook-build
|
||||||
DEB_IMAGE = blockbook-build-deb
|
DEB_IMAGE = blockbook-build-deb
|
||||||
PACKAGER = $(shell id -u):$(shell id -g)
|
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
|
NO_CACHE = false
|
||||||
UPDATE_VENDOR = 1
|
TCMALLOC =
|
||||||
ARGS ?=
|
ARGS ?=
|
||||||
|
|
||||||
TARGETS=$(subst .json,, $(shell ls configs/coins))
|
TARGETS=$(subst .json,, $(shell ls configs/coins))
|
||||||
|
@ -10,28 +11,28 @@ TARGETS=$(subst .json,, $(shell ls configs/coins))
|
||||||
.PHONY: build build-debug test deb
|
.PHONY: build build-debug test deb
|
||||||
|
|
||||||
build: .bin-image
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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))
|
deb-blockbook-all: clean-deb $(addprefix deb-blockbook-, $(TARGETS))
|
||||||
|
|
||||||
|
@ -44,8 +45,8 @@ build-images: clean-images
|
||||||
|
|
||||||
.bin-image:
|
.bin-image:
|
||||||
@if [ $$(build/tools/image_status.sh $(BIN_IMAGE):latest build/docker) != "ok" ]; then \
|
@if [ $$(build/tools/image_status.sh $(BIN_IMAGE):latest build/docker) != "ok" ]; then \
|
||||||
echo "Building image $(BIN_IMAGE)..."; \
|
echo "Building image $(BIN_IMAGE) from $(BASE_IMAGE)"; \
|
||||||
docker build --no-cache=$(NO_CACHE) -t $(BIN_IMAGE) build/docker/bin; \
|
docker build --no-cache=$(NO_CACHE) --build-arg TCMALLOC=$(TCMALLOC) --build-arg BASE_IMAGE=$(BASE_IMAGE) -t $(BIN_IMAGE) build/docker/bin; \
|
||||||
else \
|
else \
|
||||||
echo "Image $(BIN_IMAGE) is up to date"; \
|
echo "Image $(BIN_IMAGE) is up to date"; \
|
||||||
fi
|
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
|
* Just for Ethereum.
|
||||||
- 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
|
* 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.
|
* Minimal UI, dark theme.
|
||||||
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)).
|
* 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
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/common"
|
|
||||||
"blockbook/db"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"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)
|
const maxUint32 = ^uint32(0)
|
||||||
|
@ -169,11 +171,12 @@ type TokenTransfer struct {
|
||||||
|
|
||||||
// EthereumSpecific contains ethereum specific transaction data
|
// EthereumSpecific contains ethereum specific transaction data
|
||||||
type EthereumSpecific struct {
|
type EthereumSpecific struct {
|
||||||
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending
|
Status eth.TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending
|
||||||
Nonce uint64 `json:"nonce"`
|
Nonce uint64 `json:"nonce"`
|
||||||
GasLimit *big.Int `json:"gasLimit"`
|
GasLimit *big.Int `json:"gasLimit"`
|
||||||
GasUsed *big.Int `json:"gasUsed"`
|
GasUsed *big.Int `json:"gasUsed"`
|
||||||
GasPrice *Amount `json:"gasPrice"`
|
GasPrice *Amount `json:"gasPrice"`
|
||||||
|
Data string `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tx holds information about a transaction
|
// Tx holds information about a transaction
|
||||||
|
@ -193,8 +196,7 @@ type Tx struct {
|
||||||
FeesSat *Amount `json:"fees,omitempty"`
|
FeesSat *Amount `json:"fees,omitempty"`
|
||||||
Hex string `json:"hex,omitempty"`
|
Hex string `json:"hex,omitempty"`
|
||||||
Rbf bool `json:"rbf,omitempty"`
|
Rbf bool `json:"rbf,omitempty"`
|
||||||
CoinSpecificData interface{} `json:"-"`
|
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"`
|
||||||
CoinSpecificJSON json.RawMessage `json:"-"`
|
|
||||||
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
|
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
|
||||||
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
|
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -224,6 +226,8 @@ const (
|
||||||
AddressFilterVoutInputs = -2
|
AddressFilterVoutInputs = -2
|
||||||
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
||||||
AddressFilterVoutOutputs = -3
|
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 - return only tokens with nonzero balance
|
||||||
TokensToReturnNonzeroBalance TokensToReturn = 0
|
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
|
// BalanceHistory contains info about one point in time of balance history
|
||||||
type BalanceHistory struct {
|
type BalanceHistory struct {
|
||||||
Time uint32 `json:"time"`
|
Time uint32 `json:"time"`
|
||||||
Txs uint32 `json:"txs"`
|
Txs uint32 `json:"txs"`
|
||||||
ReceivedSat *Amount `json:"received"`
|
ReceivedSat *Amount `json:"received"`
|
||||||
SentSat *Amount `json:"sent"`
|
SentSat *Amount `json:"sent"`
|
||||||
FiatRates map[string]float64 `json:"rates,omitempty"`
|
SentToSelfSat *Amount `json:"sentToSelf"`
|
||||||
Txid string `json:"txid,omitempty"`
|
FiatRates map[string]float64 `json:"rates,omitempty"`
|
||||||
|
Txid string `json:"txid,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceHistories is array of BalanceHistory
|
// BalanceHistories is array of BalanceHistory
|
||||||
|
@ -326,8 +331,9 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
||||||
bhs := make(BalanceHistories, 0)
|
bhs := make(BalanceHistories, 0)
|
||||||
if len(a) > 0 {
|
if len(a) > 0 {
|
||||||
bha := BalanceHistory{
|
bha := BalanceHistory{
|
||||||
SentSat: &Amount{},
|
ReceivedSat: &Amount{},
|
||||||
ReceivedSat: &Amount{},
|
SentSat: &Amount{},
|
||||||
|
SentToSelfSat: &Amount{},
|
||||||
}
|
}
|
||||||
sort.Sort(a)
|
sort.Sort(a)
|
||||||
for i := range a {
|
for i := range a {
|
||||||
|
@ -340,17 +346,19 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
|
||||||
bhs = append(bhs, bha)
|
bhs = append(bhs, bha)
|
||||||
}
|
}
|
||||||
bha = BalanceHistory{
|
bha = BalanceHistory{
|
||||||
Time: time,
|
Time: time,
|
||||||
SentSat: &Amount{},
|
ReceivedSat: &Amount{},
|
||||||
ReceivedSat: &Amount{},
|
SentSat: &Amount{},
|
||||||
|
SentToSelfSat: &Amount{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bha.Txid != bh.Txid {
|
if bha.Txid != bh.Txid {
|
||||||
bha.Txs += bh.Txs
|
bha.Txs += bh.Txs
|
||||||
bha.Txid = bh.Txid
|
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.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 {
|
if bha.Txs > 0 {
|
||||||
bha.Txid = ""
|
bha.Txid = ""
|
||||||
|
@ -368,19 +376,19 @@ type Blocks struct {
|
||||||
|
|
||||||
// BlockInfo contains extended block header data and a list of block txids
|
// BlockInfo contains extended block header data and a list of block txids
|
||||||
type BlockInfo struct {
|
type BlockInfo struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Prev string `json:"previousBlockHash,omitempty"`
|
Prev string `json:"previousBlockHash,omitempty"`
|
||||||
Next string `json:"nextBlockHash,omitempty"`
|
Next string `json:"nextBlockHash,omitempty"`
|
||||||
Height uint32 `json:"height"`
|
Height uint32 `json:"height"`
|
||||||
Confirmations int `json:"confirmations"`
|
Confirmations int `json:"confirmations"`
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
Time int64 `json:"time,omitempty"`
|
Time int64 `json:"time,omitempty"`
|
||||||
Version json.Number `json:"version"`
|
Version common.JSONNumber `json:"version"`
|
||||||
MerkleRoot string `json:"merkleRoot"`
|
MerkleRoot string `json:"merkleRoot"`
|
||||||
Nonce string `json:"nonce"`
|
Nonce string `json:"nonce"`
|
||||||
Bits string `json:"bits"`
|
Bits string `json:"bits"`
|
||||||
Difficulty string `json:"difficulty"`
|
Difficulty string `json:"difficulty"`
|
||||||
Txids []string `json:"tx,omitempty"`
|
Txids []string `json:"tx,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block contains information about block
|
// Block contains information about block
|
||||||
|
@ -413,26 +421,10 @@ type BlockbookInfo struct {
|
||||||
About string `json:"about"`
|
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
|
// SystemInfo contains information about the running blockbook and backend instance
|
||||||
type SystemInfo struct {
|
type SystemInfo struct {
|
||||||
Blockbook *BlockbookInfo `json:"blockbook"`
|
Blockbook *BlockbookInfo `json:"blockbook"`
|
||||||
Backend *BackendInfo `json:"backend"`
|
Backend *common.BackendInfo `json:"backend"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MempoolTxid contains information about a transaction in mempool
|
// MempoolTxid contains information about a transaction in mempool
|
||||||
|
|
|
@ -67,20 +67,22 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
||||||
name: "one",
|
name: "one",
|
||||||
a: []BalanceHistory{
|
a: []BalanceHistory{
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||||
SentSat: (*Amount)(big.NewInt(2)),
|
SentSat: (*Amount)(big.NewInt(2)),
|
||||||
Time: 1521514812,
|
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
Time: 1521514812,
|
||||||
Txs: 1,
|
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
groupByTime: 3600,
|
groupByTime: 3600,
|
||||||
want: []BalanceHistory{
|
want: []BalanceHistory{
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||||
SentSat: (*Amount)(big.NewInt(2)),
|
SentSat: (*Amount)(big.NewInt(2)),
|
||||||
Time: 1521514800,
|
SentToSelfSat: (*Amount)(big.NewInt(1)),
|
||||||
Txs: 1,
|
Time: 1521514800,
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -88,67 +90,76 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
|
||||||
name: "aggregate",
|
name: "aggregate",
|
||||||
a: []BalanceHistory{
|
a: []BalanceHistory{
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(1)),
|
ReceivedSat: (*Amount)(big.NewInt(1)),
|
||||||
SentSat: (*Amount)(big.NewInt(2)),
|
SentSat: (*Amount)(big.NewInt(2)),
|
||||||
Time: 1521504812,
|
SentToSelfSat: (*Amount)(big.NewInt(0)),
|
||||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
Time: 1521504812,
|
||||||
Txs: 1,
|
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(3)),
|
ReceivedSat: (*Amount)(big.NewInt(3)),
|
||||||
SentSat: (*Amount)(big.NewInt(4)),
|
SentSat: (*Amount)(big.NewInt(4)),
|
||||||
Time: 1521504812,
|
SentToSelfSat: (*Amount)(big.NewInt(2)),
|
||||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
Time: 1521504812,
|
||||||
Txs: 1,
|
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||||
SentSat: (*Amount)(big.NewInt(6)),
|
SentSat: (*Amount)(big.NewInt(6)),
|
||||||
Time: 1521514812,
|
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
Time: 1521514812,
|
||||||
Txs: 1,
|
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(7)),
|
ReceivedSat: (*Amount)(big.NewInt(7)),
|
||||||
SentSat: (*Amount)(big.NewInt(8)),
|
SentSat: (*Amount)(big.NewInt(8)),
|
||||||
Time: 1521504812,
|
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||||
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
Time: 1521504812,
|
||||||
Txs: 1,
|
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(9)),
|
ReceivedSat: (*Amount)(big.NewInt(9)),
|
||||||
SentSat: (*Amount)(big.NewInt(10)),
|
SentSat: (*Amount)(big.NewInt(10)),
|
||||||
Time: 1521534812,
|
SentToSelfSat: (*Amount)(big.NewInt(5)),
|
||||||
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
Time: 1521534812,
|
||||||
Txs: 1,
|
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||||
SentSat: (*Amount)(big.NewInt(12)),
|
SentSat: (*Amount)(big.NewInt(12)),
|
||||||
Time: 1521534812,
|
SentToSelfSat: (*Amount)(big.NewInt(6)),
|
||||||
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
Time: 1521534812,
|
||||||
Txs: 1,
|
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
groupByTime: 3600,
|
groupByTime: 3600,
|
||||||
want: []BalanceHistory{
|
want: []BalanceHistory{
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(11)),
|
ReceivedSat: (*Amount)(big.NewInt(11)),
|
||||||
SentSat: (*Amount)(big.NewInt(14)),
|
SentSat: (*Amount)(big.NewInt(14)),
|
||||||
Time: 1521504000,
|
SentToSelfSat: (*Amount)(big.NewInt(5)),
|
||||||
Txs: 2,
|
Time: 1521504000,
|
||||||
|
Txs: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(5)),
|
ReceivedSat: (*Amount)(big.NewInt(5)),
|
||||||
SentSat: (*Amount)(big.NewInt(6)),
|
SentSat: (*Amount)(big.NewInt(6)),
|
||||||
Time: 1521514800,
|
SentToSelfSat: (*Amount)(big.NewInt(3)),
|
||||||
Txs: 1,
|
Time: 1521514800,
|
||||||
|
Txs: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReceivedSat: (*Amount)(big.NewInt(20)),
|
ReceivedSat: (*Amount)(big.NewInt(20)),
|
||||||
SentSat: (*Amount)(big.NewInt(22)),
|
SentSat: (*Amount)(big.NewInt(22)),
|
||||||
Time: 1521532800,
|
SentToSelfSat: (*Amount)(big.NewInt(11)),
|
||||||
Txs: 2,
|
Time: 1521532800,
|
||||||
|
Txs: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScriptSigV1 is used for legacy api v1
|
// ScriptSigV1 is used for legacy api v1
|
||||||
|
|
363
api/worker.go
363
api/worker.go
|
@ -1,10 +1,6 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/eth"
|
|
||||||
"blockbook/common"
|
|
||||||
"blockbook/db"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -18,6 +14,10 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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
|
// Worker is handle to api worker
|
||||||
|
@ -253,32 +253,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("GetErc20FromTx error %v, %v", err, bchainTx)
|
glog.Errorf("GetErc20FromTx error %v, %v", err, bchainTx)
|
||||||
}
|
}
|
||||||
tokens = make([]TokenTransfer, len(ets))
|
tokens = w.getTokensFromErc20(ets)
|
||||||
for i := range ets {
|
|
||||||
e := &ets[i]
|
|
||||||
cd, err := w.chainParser.GetAddrDescFromAddress(e.Contract)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("GetAddrDescFromAddress error %v, contract %v", err, e.Contract)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
erc20c, err := w.chain.EthereumTypeGetErc20ContractInfo(cd)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("GetErc20ContractInfo error %v, contract %v", err, e.Contract)
|
|
||||||
}
|
|
||||||
if erc20c == nil {
|
|
||||||
erc20c = &bchain.Erc20Contract{Name: e.Contract}
|
|
||||||
}
|
|
||||||
tokens[i] = TokenTransfer{
|
|
||||||
Type: ERC20TokenType,
|
|
||||||
Token: e.Contract,
|
|
||||||
From: e.From,
|
|
||||||
To: e.To,
|
|
||||||
Decimals: erc20c.Decimals,
|
|
||||||
Value: (*Amount)(&e.Tokens),
|
|
||||||
Name: erc20c.Name,
|
|
||||||
Symbol: erc20c.Symbol,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ethTxData := eth.GetEthereumTxData(bchainTx)
|
ethTxData := eth.GetEthereumTxData(bchainTx)
|
||||||
// mempool txs do not have fees yet
|
// mempool txs do not have fees yet
|
||||||
if ethTxData.GasUsed != nil {
|
if ethTxData.GasUsed != nil {
|
||||||
|
@ -293,12 +268,14 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
||||||
GasUsed: ethTxData.GasUsed,
|
GasUsed: ethTxData.GasUsed,
|
||||||
Nonce: ethTxData.Nonce,
|
Nonce: ethTxData.Nonce,
|
||||||
Status: ethTxData.Status,
|
Status: ethTxData.Status,
|
||||||
|
Data: ethTxData.Data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for now do not return size, we would have to compute vsize of segwit transactions
|
// for now do not return size, we would have to compute vsize of segwit transactions
|
||||||
// size:=len(bchainTx.Hex) / 2
|
// size:=len(bchainTx.Hex) / 2
|
||||||
var sj json.RawMessage
|
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)
|
sj, err = w.chain.GetTransactionSpecific(bchainTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -323,14 +300,140 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
|
||||||
Rbf: rbf,
|
Rbf: rbf,
|
||||||
Vin: vins,
|
Vin: vins,
|
||||||
Vout: vouts,
|
Vout: vouts,
|
||||||
CoinSpecificData: bchainTx.CoinSpecificData,
|
CoinSpecificData: sj,
|
||||||
CoinSpecificJSON: sj,
|
|
||||||
TokenTransfers: tokens,
|
TokenTransfers: tokens,
|
||||||
EthereumSpecific: ethSpecific,
|
EthereumSpecific: ethSpecific,
|
||||||
}
|
}
|
||||||
return r, nil
|
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) {
|
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool, filter *AddressFilter, maxResults int) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
txids := make([]string, 0, 4)
|
txids := make([]string, 0, 4)
|
||||||
|
@ -400,6 +503,19 @@ func (t *Tx) getAddrVoutValue(addrDesc bchain.AddressDescriptor) *big.Int {
|
||||||
}
|
}
|
||||||
return &val
|
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 {
|
func (t *Tx) getAddrVinValue(addrDesc bchain.AddressDescriptor) *big.Int {
|
||||||
var val big.Int
|
var val big.Int
|
||||||
|
@ -496,6 +612,44 @@ func computePaging(count, page, itemsOnPage int) (Paging, int, int, int) {
|
||||||
}, from, to, page
|
}, 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) {
|
func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescriptor, details AccountDetails, filter *AddressFilter) (*db.AddrBalance, []Token, *bchain.Erc20Contract, uint64, int, int, error) {
|
||||||
var (
|
var (
|
||||||
ba *db.AddrBalance
|
ba *db.AddrBalance
|
||||||
|
@ -514,6 +668,13 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetBalance %v", addrDesc)
|
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 {
|
if ca != nil {
|
||||||
ba = &db.AddrBalance{
|
ba = &db.AddrBalance{
|
||||||
Txs: uint32(ca.TotalTxs),
|
Txs: uint32(ca.TotalTxs),
|
||||||
|
@ -525,13 +686,6 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetNonce %v", addrDesc)
|
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 {
|
if details > AccountDetailsBasic {
|
||||||
tokens = make([]Token, len(ca.Contracts))
|
tokens = make([]Token, len(ca.Contracts))
|
||||||
var j int
|
var j int
|
||||||
|
@ -543,43 +697,26 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
||||||
// filter only transactions of this contract
|
// filter only transactions of this contract
|
||||||
filter.Vout = i + 1
|
filter.Vout = i + 1
|
||||||
}
|
}
|
||||||
validContract := true
|
t, err := w.getEthereumToken(i+1, addrDesc, c.Contract, details, int(c.Txs))
|
||||||
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(c.Contract)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", c.Contract)
|
return nil, nil, nil, 0, 0, 0, err
|
||||||
}
|
|
||||||
if ci == nil {
|
|
||||||
ci = &bchain.Erc20Contract{}
|
|
||||||
addresses, _, _ := w.chainParser.GetAddressesFromAddrDesc(c.Contract)
|
|
||||||
if len(addresses) > 0 {
|
|
||||||
ci.Contract = addresses[0]
|
|
||||||
ci.Name = addresses[0]
|
|
||||||
}
|
|
||||||
validContract = false
|
|
||||||
}
|
|
||||||
// do not read contract balances etc in case of Basic option
|
|
||||||
if details >= AccountDetailsTokenBalances && validContract {
|
|
||||||
b, err = w.chain.EthereumTypeGetErc20ContractBalance(addrDesc, c.Contract)
|
|
||||||
if err != nil {
|
|
||||||
// return nil, nil, nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractBalance %v %v", addrDesc, c.Contract)
|
|
||||||
glog.Warningf("EthereumTypeGetErc20ContractBalance addr %v, contract %v, %v", addrDesc, c.Contract, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b = nil
|
|
||||||
}
|
|
||||||
tokens[j] = Token{
|
|
||||||
Type: ERC20TokenType,
|
|
||||||
BalanceSat: (*Amount)(b),
|
|
||||||
Contract: ci.Contract,
|
|
||||||
Name: ci.Name,
|
|
||||||
Symbol: ci.Symbol,
|
|
||||||
Transfers: int(c.Txs),
|
|
||||||
Decimals: ci.Decimals,
|
|
||||||
ContractIndex: strconv.Itoa(i + 1),
|
|
||||||
}
|
}
|
||||||
|
tokens[j] = *t
|
||||||
j++
|
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)
|
ci, err = w.chain.EthereumTypeGetErc20ContractInfo(addrDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -593,6 +730,8 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
||||||
totalResults = int(ca.NonContractTxs)
|
totalResults = int(ca.NonContractTxs)
|
||||||
} else if filter.Vout > 0 && filter.Vout-1 < len(ca.Contracts) {
|
} else if filter.Vout > 0 && filter.Vout-1 < len(ca.Contracts) {
|
||||||
totalResults = int(ca.Contracts[filter.Vout-1].Txs)
|
totalResults = int(ca.Contracts[filter.Vout-1].Txs)
|
||||||
|
} else if filter.Vout == AddressFilterVoutQueryNotNecessary {
|
||||||
|
totalResults = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nonContractTxs = int(ca.NonContractTxs)
|
nonContractTxs = int(ca.NonContractTxs)
|
||||||
|
@ -603,6 +742,16 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
||||||
BalanceSat: *b,
|
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
|
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 {
|
if ta == nil {
|
||||||
glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses")
|
glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses")
|
||||||
// as fallback, get tx from backend
|
// as fallback, get tx from backend
|
||||||
tx, err = w.GetTransaction(txid, false, true)
|
tx, err = w.GetTransaction(txid, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
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)
|
tx = w.txFromTxAddress(txid, ta, blockInfo, bestheight)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tx, err = w.GetTransaction(txid, false, true)
|
tx, err = w.GetTransaction(txid, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
|
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)
|
return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc)
|
||||||
}
|
}
|
||||||
for _, txid := range txm {
|
for _, txid := range txm {
|
||||||
tx, err := w.GetTransaction(txid, false, false)
|
tx, err := w.GetTransaction(txid, false, true)
|
||||||
// mempool transaction may fail
|
// mempool transaction may fail
|
||||||
if err != nil || tx == nil {
|
if err != nil || tx == nil {
|
||||||
glog.Warning("GetTransaction in mempool: ", err)
|
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 {
|
if tx.Confirmations == 0 {
|
||||||
unconfirmedTxs++
|
unconfirmedTxs++
|
||||||
uBalSat.Add(&uBalSat, tx.getAddrVoutValue(addrDesc))
|
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 page == 0 {
|
||||||
if option == AccountDetailsTxidHistory {
|
if option == AccountDetailsTxidHistory {
|
||||||
txids = append(txids, tx.Txid)
|
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
|
// 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)
|
txc, err := w.getAddressTxids(addrDesc, false, filter, (page+1)*txsOnPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "getAddressTxids %v false", addrDesc)
|
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
|
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 time uint32
|
||||||
var err error
|
var err error
|
||||||
var ta *db.TxAddresses
|
var ta *db.TxAddresses
|
||||||
|
@ -853,17 +1007,30 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
bh := BalanceHistory{
|
bh := BalanceHistory{
|
||||||
Time: time,
|
Time: time,
|
||||||
Txs: 1,
|
Txs: 1,
|
||||||
SentSat: &Amount{},
|
ReceivedSat: &Amount{},
|
||||||
ReceivedSat: &Amount{},
|
SentSat: &Amount{},
|
||||||
Txid: txid,
|
SentToSelfSat: &Amount{},
|
||||||
|
Txid: txid,
|
||||||
}
|
}
|
||||||
|
countSentToSelf := false
|
||||||
if w.chainType == bchain.ChainBitcoinType {
|
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 {
|
for i := range ta.Inputs {
|
||||||
tai := &ta.Inputs[i]
|
tai := &ta.Inputs[i]
|
||||||
|
if _, found := selfAddrDesc[string(tai.AddrDesc)]; found {
|
||||||
|
if ownInputIndex < 0 {
|
||||||
|
ownInputIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
if bytes.Equal(addrDesc, tai.AddrDesc) {
|
if bytes.Equal(addrDesc, tai.AddrDesc) {
|
||||||
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat)
|
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat)
|
||||||
|
if ownInputIndex == i {
|
||||||
|
countSentToSelf = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range ta.Outputs {
|
for i := range ta.Outputs {
|
||||||
|
@ -871,12 +1038,17 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
||||||
if bytes.Equal(addrDesc, tao.AddrDesc) {
|
if bytes.Equal(addrDesc, tao.AddrDesc) {
|
||||||
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat)
|
(*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 {
|
} else if w.chainType == bchain.ChainEthereumType {
|
||||||
var value big.Int
|
var value big.Int
|
||||||
ethTxData := eth.GetEthereumTxData(bchainTx)
|
ethTxData := eth.GetEthereumTxData(bchainTx)
|
||||||
// add received amount only for OK transactions
|
// add received amount only for OK or unknown status (old) transactions
|
||||||
if ethTxData.Status == 1 {
|
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||||
if len(bchainTx.Vout) > 0 {
|
if len(bchainTx.Vout) > 0 {
|
||||||
bchainVout := &bchainTx.Vout[0]
|
bchainVout := &bchainTx.Vout[0]
|
||||||
value = bchainVout.ValueSat
|
value = bchainVout.ValueSat
|
||||||
|
@ -888,6 +1060,9 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
|
||||||
if bytes.Equal(addrDesc, txAddrDesc) {
|
if bytes.Equal(addrDesc, txAddrDesc) {
|
||||||
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &value)
|
(*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
|
return nil, err
|
||||||
}
|
}
|
||||||
if bytes.Equal(addrDesc, txAddrDesc) {
|
if bytes.Equal(addrDesc, txAddrDesc) {
|
||||||
// add sent amount only for OK transactions, however fees always
|
// add received amount only for OK or unknown status (old) transactions, fees always
|
||||||
if ethTxData.Status == 1 {
|
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
|
||||||
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &value)
|
(*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
|
var feesSat big.Int
|
||||||
// mempool txs do not have fees yet
|
// mempool txs do not have fees yet
|
||||||
|
@ -962,8 +1142,9 @@ func (w *Worker) GetBalanceHistory(address string, fromTimestamp, toTimestamp in
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
selfAddrDesc := map[string]struct{}{string(addrDesc): {}}
|
||||||
for txi := len(txs) - 1; txi >= 0; txi-- {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1593,7 +1774,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
||||||
DbColumns: columnStats,
|
DbColumns: columnStats,
|
||||||
About: Text.BlockbookAbout,
|
About: Text.BlockbookAbout,
|
||||||
}
|
}
|
||||||
backendInfo := &BackendInfo{
|
backendInfo := &common.BackendInfo{
|
||||||
BackendError: backendError,
|
BackendError: backendError,
|
||||||
BestBlockHash: ci.Bestblockhash,
|
BestBlockHash: ci.Bestblockhash,
|
||||||
Blocks: ci.Blocks,
|
Blocks: ci.Blocks,
|
||||||
|
@ -1606,7 +1787,9 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
||||||
Timeoffset: ci.Timeoffset,
|
Timeoffset: ci.Timeoffset,
|
||||||
Version: ci.Version,
|
Version: ci.Version,
|
||||||
Warnings: ci.Warnings,
|
Warnings: ci.Warnings,
|
||||||
|
Consensus: ci.Consensus,
|
||||||
}
|
}
|
||||||
|
w.is.SetBackendInfo(backendInfo)
|
||||||
glog.Info("GetSystemInfo finished in ", time.Since(start))
|
glog.Info("GetSystemInfo finished in ", time.Since(start))
|
||||||
return &SystemInfo{blockbookInfo, backendInfo}, nil
|
return &SystemInfo{blockbookInfo, backendInfo}, nil
|
||||||
}
|
}
|
||||||
|
|
14
api/xpub.go
14
api/xpub.go
|
@ -1,8 +1,6 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/db"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -11,6 +9,8 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultAddressesGap = 20
|
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
|
// the same tx can have multiple addresses from the same xpub, get it from backend it only once
|
||||||
tx, foundTx := txmMap[txid.txid]
|
tx, foundTx := txmMap[txid.txid]
|
||||||
if !foundTx {
|
if !foundTx {
|
||||||
tx, err = w.GetTransaction(txid.txid, false, false)
|
tx, err = w.GetTransaction(txid.txid, false, true)
|
||||||
// mempool transaction may fail
|
// mempool transaction may fail
|
||||||
if err != nil || tx == nil {
|
if err != nil || tx == nil {
|
||||||
glog.Warning("GetTransaction in mempool: ", err)
|
glog.Warning("GetTransaction in mempool: ", err)
|
||||||
|
@ -606,12 +606,18 @@ func (w *Worker) GetXpubBalanceHistory(xpub string, fromTimestamp, toTimestamp i
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
||||||
for i := range da {
|
for i := range da {
|
||||||
ad := &da[i]
|
ad := &da[i]
|
||||||
txids := ad.txids
|
txids := ad.txids
|
||||||
for txi := len(txids) - 1; txi >= 0; txi-- {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package bchain
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type addrIndex struct {
|
type addrIndex struct {
|
||||||
|
@ -27,6 +28,7 @@ type BaseMempool struct {
|
||||||
txEntries map[string]txEntry
|
txEntries map[string]txEntry
|
||||||
addrDescToTx map[string][]Outpoint
|
addrDescToTx map[string][]Outpoint
|
||||||
OnNewTxAddr OnNewTxAddrFunc
|
OnNewTxAddr OnNewTxAddrFunc
|
||||||
|
OnNewTx OnNewTxFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactions returns slice of mempool transactions for given address
|
// GetTransactions returns slice of mempool transactions for given address
|
||||||
|
@ -113,3 +115,22 @@ func (m *BaseMempool) GetTransactionTime(txid string) uint32 {
|
||||||
}
|
}
|
||||||
return e.time
|
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/gogo/protobuf/proto"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseParser implements data parsing/handling functionality base for all other parsers
|
// 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"
|
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
|
// 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
|
var r big.Int
|
||||||
s := string(n)
|
s := string(n)
|
||||||
i := strings.IndexByte(s, '.')
|
i := strings.IndexByte(s, '.')
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
// +build unittest
|
||||||
|
|
||||||
package bchain
|
package bchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBaseParser(adp int) *BaseParser {
|
func NewBaseParser(adp int) *BaseParser {
|
||||||
|
@ -44,7 +47,7 @@ func TestBaseParser_AmountToDecimalString(t *testing.T) {
|
||||||
func TestBaseParser_AmountToBigInt(t *testing.T) {
|
func TestBaseParser_AmountToBigInt(t *testing.T) {
|
||||||
for _, tt := range amounts {
|
for _, tt := range amounts {
|
||||||
t.Run(tt.s, func(t *testing.T) {
|
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 {
|
if err != nil {
|
||||||
t.Errorf("BaseParser.AmountToBigInt() error = %v", err)
|
t.Errorf("BaseParser.AmountToBigInt() error = %v", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package bch
|
package bch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/martinboehm/bchutil"
|
"github.com/martinboehm/bchutil"
|
||||||
|
@ -10,6 +8,8 @@ import (
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
"github.com/martinboehm/btcutil/txscript"
|
"github.com/martinboehm/btcutil/txscript"
|
||||||
"github.com/schancel/cashaddr-converter/address"
|
"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
|
// AddressFormat type is used to specify different formats of address
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package bch
|
package bch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package bch
|
package bch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -10,6 +8,8 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
"github.com/martinboehm/bchutil"
|
"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.
|
// BCashRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package bellcoin
|
package bellcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package bellcoin
|
package bellcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package bellcoin
|
package bellcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// BellcoinRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package bitcore
|
package bitcore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -3,14 +3,15 @@
|
||||||
package bitcore
|
package bitcore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package bitcore
|
package bitcore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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.
|
// 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
|
package coins
|
||||||
|
|
||||||
import (
|
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"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -49,6 +10,48 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"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)
|
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() {
|
func init() {
|
||||||
BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC
|
BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC
|
||||||
BlockChainFactories["Testnet"] = btc.NewBitcoinRPC
|
BlockChainFactories["Testnet"] = btc.NewBitcoinRPC
|
||||||
|
BlockChainFactories["Signet"] = btc.NewBitcoinRPC
|
||||||
BlockChainFactories["Zcash"] = zec.NewZCashRPC
|
BlockChainFactories["Zcash"] = zec.NewZCashRPC
|
||||||
BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC
|
BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC
|
||||||
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
|
||||||
|
BlockChainFactories["Ethereum Testnet Goerli"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Bcash"] = bch.NewBCashRPC
|
BlockChainFactories["Bcash"] = bch.NewBCashRPC
|
||||||
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
|
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
|
||||||
BlockChainFactories["Bgold"] = btg.NewBGoldRPC
|
BlockChainFactories["Bgold"] = btg.NewBGoldRPC
|
||||||
|
BlockChainFactories["Bgold Testnet"] = btg.NewBGoldRPC
|
||||||
BlockChainFactories["Dash"] = dash.NewDashRPC
|
BlockChainFactories["Dash"] = dash.NewDashRPC
|
||||||
BlockChainFactories["Dash Testnet"] = dash.NewDashRPC
|
BlockChainFactories["Dash Testnet"] = dash.NewDashRPC
|
||||||
BlockChainFactories["Decred"] = dcr.NewDecredRPC
|
BlockChainFactories["Decred"] = dcr.NewDecredRPC
|
||||||
|
@ -84,6 +90,7 @@ func init() {
|
||||||
BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC
|
BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC
|
||||||
BlockChainFactories["MonetaryUnit"] = monetaryunit.NewMonetaryUnitRPC
|
BlockChainFactories["MonetaryUnit"] = monetaryunit.NewMonetaryUnitRPC
|
||||||
BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC
|
BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC
|
||||||
|
BlockChainFactories["DigiByte Testnet"] = digibyte.NewDigiByteRPC
|
||||||
BlockChainFactories["Myriad"] = myriad.NewMyriadRPC
|
BlockChainFactories["Myriad"] = myriad.NewMyriadRPC
|
||||||
BlockChainFactories["Liquid"] = liquid.NewLiquidRPC
|
BlockChainFactories["Liquid"] = liquid.NewLiquidRPC
|
||||||
BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC
|
BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC
|
||||||
|
@ -91,7 +98,7 @@ func init() {
|
||||||
BlockChainFactories["PIVX"] = pivx.NewPivXRPC
|
BlockChainFactories["PIVX"] = pivx.NewPivXRPC
|
||||||
BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC
|
BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC
|
||||||
BlockChainFactories["Polis"] = polis.NewPolisRPC
|
BlockChainFactories["Polis"] = polis.NewPolisRPC
|
||||||
BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC
|
BlockChainFactories["Firo"] = firo.NewFiroRPC
|
||||||
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
|
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
|
||||||
BlockChainFactories["Flo"] = flo.NewFloRPC
|
BlockChainFactories["Flo"] = flo.NewFloRPC
|
||||||
BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC
|
BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC
|
||||||
|
@ -107,9 +114,12 @@ func init() {
|
||||||
BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC
|
BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC
|
||||||
BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC
|
BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC
|
||||||
BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC
|
BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC
|
||||||
|
BlockChainFactories["SnowGem"] = snowgem.NewSnowGemRPC
|
||||||
BlockChainFactories["Bitcore"] = bitcore.NewBitcoreRPC
|
BlockChainFactories["Bitcore"] = bitcore.NewBitcoreRPC
|
||||||
BlockChainFactories["Omotenashicoin"] = omotenashicoin.NewOmotenashiCoinRPC
|
BlockChainFactories["Omotenashicoin"] = omotenashicoin.NewOmotenashiCoinRPC
|
||||||
BlockChainFactories["Omotenashicoin Testnet"] = 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
|
// 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)
|
return c.b.CreateMempool(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
|
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
|
||||||
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr)
|
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr, onNewTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error {
|
func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package btc
|
package btc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -16,8 +15,25 @@ import (
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
"github.com/martinboehm/btcutil/hdkeychain"
|
"github.com/martinboehm/btcutil/hdkeychain"
|
||||||
"github.com/martinboehm/btcutil/txscript"
|
"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
|
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
|
||||||
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
|
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
|
||||||
|
|
||||||
|
@ -63,6 +79,8 @@ func GetChainParams(chain string) *chaincfg.Params {
|
||||||
return &chaincfg.TestNet3Params
|
return &chaincfg.TestNet3Params
|
||||||
case "regtest":
|
case "regtest":
|
||||||
return &chaincfg.RegressionNetParams
|
return &chaincfg.RegressionNetParams
|
||||||
|
case "signet":
|
||||||
|
return &SigNetParams
|
||||||
}
|
}
|
||||||
return &chaincfg.MainNetParams
|
return &chaincfg.MainNetParams
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
package btc
|
package btc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -11,6 +10,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
@ -259,10 +259,11 @@ func TestGetAddressesFromAddrDesc(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testTx1, testTx2 bchain.Tx
|
testTx1, testTx2, testTx3 bchain.Tx
|
||||||
|
|
||||||
testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700"
|
testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700"
|
||||||
testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000"
|
testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000"
|
||||||
|
testTxPacked3 = "00003d818bfda9aa3e02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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) {
|
func TestPackTx(t *testing.T) {
|
||||||
|
@ -372,6 +421,17 @@ func TestPackTx(t *testing.T) {
|
||||||
want: testTxPacked2,
|
want: testTxPacked2,
|
||||||
wantErr: false,
|
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 {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -420,6 +480,16 @@ func TestUnpackTx(t *testing.T) {
|
||||||
want1: 510234,
|
want1: 510234,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "signet-1",
|
||||||
|
args: args{
|
||||||
|
packedTx: testTxPacked3,
|
||||||
|
parser: NewBitcoinParser(GetChainParams("signet"), &Configuration{}),
|
||||||
|
},
|
||||||
|
want: &testTx3,
|
||||||
|
want1: 15745,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package btc
|
package btc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -17,6 +16,8 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BitcoinRPC is an interface to JSON-RPC bitcoind service.
|
// 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
|
// 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 {
|
if b.Mempool == nil {
|
||||||
return errors.New("Mempool not created")
|
return errors.New("Mempool not created")
|
||||||
}
|
}
|
||||||
b.Mempool.AddrDescForOutpoint = addrDescForOutpoint
|
b.Mempool.AddrDescForOutpoint = addrDescForOutpoint
|
||||||
b.Mempool.OnNewTxAddr = onNewTxAddr
|
b.Mempool.OnNewTxAddr = onNewTxAddr
|
||||||
|
b.Mempool.OnNewTx = onNewTx
|
||||||
if b.mq == nil {
|
if b.mq == nil {
|
||||||
mq, err := bchain.NewMQ(b.ChainConfig.MessageQueueBinding, b.pushHandler)
|
mq, err := bchain.NewMQ(b.ChainConfig.MessageQueueBinding, b.pushHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -237,13 +239,13 @@ type CmdGetBlockChainInfo struct {
|
||||||
type ResGetBlockChainInfo struct {
|
type ResGetBlockChainInfo struct {
|
||||||
Error *bchain.RPCError `json:"error"`
|
Error *bchain.RPCError `json:"error"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Chain string `json:"chain"`
|
Chain string `json:"chain"`
|
||||||
Blocks int `json:"blocks"`
|
Blocks int `json:"blocks"`
|
||||||
Headers int `json:"headers"`
|
Headers int `json:"headers"`
|
||||||
Bestblockhash string `json:"bestblockhash"`
|
Bestblockhash string `json:"bestblockhash"`
|
||||||
Difficulty json.Number `json:"difficulty"`
|
Difficulty common.JSONNumber `json:"difficulty"`
|
||||||
SizeOnDisk int64 `json:"size_on_disk"`
|
SizeOnDisk int64 `json:"size_on_disk"`
|
||||||
Warnings string `json:"warnings"`
|
Warnings string `json:"warnings"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,11 +258,11 @@ type CmdGetNetworkInfo struct {
|
||||||
type ResGetNetworkInfo struct {
|
type ResGetNetworkInfo struct {
|
||||||
Error *bchain.RPCError `json:"error"`
|
Error *bchain.RPCError `json:"error"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Version json.Number `json:"version"`
|
Version common.JSONNumber `json:"version"`
|
||||||
Subversion json.Number `json:"subversion"`
|
Subversion common.JSONNumber `json:"subversion"`
|
||||||
ProtocolVersion json.Number `json:"protocolversion"`
|
ProtocolVersion common.JSONNumber `json:"protocolversion"`
|
||||||
Timeoffset float64 `json:"timeoffset"`
|
Timeoffset float64 `json:"timeoffset"`
|
||||||
Warnings string `json:"warnings"`
|
Warnings string `json:"warnings"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,8 +360,8 @@ type CmdEstimateSmartFee struct {
|
||||||
type ResEstimateSmartFee struct {
|
type ResEstimateSmartFee struct {
|
||||||
Error *bchain.RPCError `json:"error"`
|
Error *bchain.RPCError `json:"error"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Feerate json.Number `json:"feerate"`
|
Feerate common.JSONNumber `json:"feerate"`
|
||||||
Blocks int `json:"blocks"`
|
Blocks int `json:"blocks"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,8 +375,8 @@ type CmdEstimateFee struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResEstimateFee struct {
|
type ResEstimateFee struct {
|
||||||
Error *bchain.RPCError `json:"error"`
|
Error *bchain.RPCError `json:"error"`
|
||||||
Result json.Number `json:"result"`
|
Result common.JSONNumber `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendrawtransaction
|
// sendrawtransaction
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package btc
|
package btc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -12,8 +11,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://whatthefee.io returns
|
// https://whatthefee.io returns
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package btg
|
package btg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"blockbook/bchain/coins/utils"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
@ -11,6 +8,9 @@ import (
|
||||||
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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 (
|
const (
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
package btg
|
package btg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -13,6 +12,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package btg
|
package btg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// BGoldRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package cpuchain
|
package cpuchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package cpuchain
|
package cpuchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// CPUchainRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package dash
|
package dash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
// build unittest
|
// +build unittest
|
||||||
|
|
||||||
package dash
|
package dash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -13,6 +11,9 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testBlock struct {
|
type testBlock struct {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package dash
|
package dash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const firstBlockWithSpecialTransactions = 1028160
|
const firstBlockWithSpecialTransactions = 1028160
|
||||||
|
|
|
@ -9,18 +9,19 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"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/chaincfg/chainhash"
|
||||||
"github.com/decred/dcrd/hdkeychain"
|
cfg "github.com/decred/dcrd/chaincfg/v3"
|
||||||
"github.com/decred/dcrd/txscript"
|
"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/juju/errors"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/base58"
|
"github.com/martinboehm/btcutil/base58"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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 (
|
const (
|
||||||
|
@ -65,9 +66,9 @@ func NewDecredParser(params *chaincfg.Params, c *btc.Configuration) *DecredParse
|
||||||
|
|
||||||
switch d.BitcoinParser.Params.Name {
|
switch d.BitcoinParser.Params.Name {
|
||||||
case "testnet3":
|
case "testnet3":
|
||||||
d.netConfig = &cfg.TestNet3Params
|
d.netConfig = cfg.TestNet3Params()
|
||||||
default:
|
default:
|
||||||
d.netConfig = &cfg.MainNetParams
|
d.netConfig = cfg.MainNetParams()
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
@ -203,7 +204,10 @@ func (p *DecredParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressD
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -252,7 +258,7 @@ func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchai
|
||||||
// listed indexes
|
// listed indexes
|
||||||
func (p *DecredParser) DeriveAddressDescriptors(xpub string, change uint32,
|
func (p *DecredParser) DeriveAddressDescriptors(xpub string, change uint32,
|
||||||
indexes []uint32) ([]bchain.AddressDescriptor, error) {
|
indexes []uint32) ([]bchain.AddressDescriptor, error) {
|
||||||
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -283,7 +289,7 @@ func (p *DecredParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32
|
||||||
if toIndex <= fromIndex {
|
if toIndex <= fromIndex {
|
||||||
return nil, errors.New("toIndex<=fromIndex")
|
return nil, errors.New("toIndex<=fromIndex")
|
||||||
}
|
}
|
||||||
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
package dcr
|
package dcr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package dcr
|
package dcr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -16,11 +15,12 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"blockbook/bchain/coins/btc"
|
"github.com/decred/dcrd/dcrjson/v3"
|
||||||
|
|
||||||
"github.com/decred/dcrd/dcrjson"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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
|
// voteBitYes defines the vote bit set when a given block validates the previous
|
||||||
|
@ -168,61 +168,61 @@ type GetBlockHashResult struct {
|
||||||
type GetBlockResult struct {
|
type GetBlockResult struct {
|
||||||
Error Error `json:"error"`
|
Error Error `json:"error"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Confirmations int64 `json:"confirmations"`
|
Confirmations int64 `json:"confirmations"`
|
||||||
Size int32 `json:"size"`
|
Size int32 `json:"size"`
|
||||||
Height uint32 `json:"height"`
|
Height uint32 `json:"height"`
|
||||||
Version json.Number `json:"version"`
|
Version common.JSONNumber `json:"version"`
|
||||||
MerkleRoot string `json:"merkleroot"`
|
MerkleRoot string `json:"merkleroot"`
|
||||||
StakeRoot string `json:"stakeroot"`
|
StakeRoot string `json:"stakeroot"`
|
||||||
RawTx []RawTx `json:"rawtx"`
|
RawTx []RawTx `json:"rawtx"`
|
||||||
Tx []string `json:"tx,omitempty"`
|
Tx []string `json:"tx,omitempty"`
|
||||||
STx []string `json:"stx,omitempty"`
|
STx []string `json:"stx,omitempty"`
|
||||||
Time int64 `json:"time"`
|
Time int64 `json:"time"`
|
||||||
Nonce json.Number `json:"nonce"`
|
Nonce common.JSONNumber `json:"nonce"`
|
||||||
VoteBits uint16 `json:"votebits"`
|
VoteBits uint16 `json:"votebits"`
|
||||||
FinalState string `json:"finalstate"`
|
FinalState string `json:"finalstate"`
|
||||||
Voters uint16 `json:"voters"`
|
Voters uint16 `json:"voters"`
|
||||||
FreshStake uint8 `json:"freshstake"`
|
FreshStake uint8 `json:"freshstake"`
|
||||||
Revocations uint8 `json:"revocations"`
|
Revocations uint8 `json:"revocations"`
|
||||||
PoolSize uint32 `json:"poolsize"`
|
PoolSize uint32 `json:"poolsize"`
|
||||||
Bits string `json:"bits"`
|
Bits string `json:"bits"`
|
||||||
SBits float64 `json:"sbits"`
|
SBits float64 `json:"sbits"`
|
||||||
ExtraData string `json:"extradata"`
|
ExtraData string `json:"extradata"`
|
||||||
StakeVersion uint32 `json:"stakeversion"`
|
StakeVersion uint32 `json:"stakeversion"`
|
||||||
Difficulty float64 `json:"difficulty"`
|
Difficulty float64 `json:"difficulty"`
|
||||||
ChainWork string `json:"chainwork"`
|
ChainWork string `json:"chainwork"`
|
||||||
PreviousHash string `json:"previousblockhash"`
|
PreviousHash string `json:"previousblockhash"`
|
||||||
NextHash string `json:"nextblockhash,omitempty"`
|
NextHash string `json:"nextblockhash,omitempty"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetBlockHeaderResult struct {
|
type GetBlockHeaderResult struct {
|
||||||
Error Error `json:"error"`
|
Error Error `json:"error"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Confirmations int64 `json:"confirmations"`
|
Confirmations int64 `json:"confirmations"`
|
||||||
Version json.Number `json:"version"`
|
Version common.JSONNumber `json:"version"`
|
||||||
MerkleRoot string `json:"merkleroot"`
|
MerkleRoot string `json:"merkleroot"`
|
||||||
StakeRoot string `json:"stakeroot"`
|
StakeRoot string `json:"stakeroot"`
|
||||||
VoteBits uint16 `json:"votebits"`
|
VoteBits uint16 `json:"votebits"`
|
||||||
FinalState string `json:"finalstate"`
|
FinalState string `json:"finalstate"`
|
||||||
Voters uint16 `json:"voters"`
|
Voters uint16 `json:"voters"`
|
||||||
FreshStake uint8 `json:"freshstake"`
|
FreshStake uint8 `json:"freshstake"`
|
||||||
Revocations uint8 `json:"revocations"`
|
Revocations uint8 `json:"revocations"`
|
||||||
PoolSize uint32 `json:"poolsize"`
|
PoolSize uint32 `json:"poolsize"`
|
||||||
Bits string `json:"bits"`
|
Bits string `json:"bits"`
|
||||||
SBits float64 `json:"sbits"`
|
SBits float64 `json:"sbits"`
|
||||||
Height uint32 `json:"height"`
|
Height uint32 `json:"height"`
|
||||||
Size uint32 `json:"size"`
|
Size uint32 `json:"size"`
|
||||||
Time int64 `json:"time"`
|
Time int64 `json:"time"`
|
||||||
Nonce uint32 `json:"nonce"`
|
Nonce uint32 `json:"nonce"`
|
||||||
ExtraData string `json:"extradata"`
|
ExtraData string `json:"extradata"`
|
||||||
StakeVersion uint32 `json:"stakeversion"`
|
StakeVersion uint32 `json:"stakeversion"`
|
||||||
Difficulty float64 `json:"difficulty"`
|
Difficulty float64 `json:"difficulty"`
|
||||||
ChainWork string `json:"chainwork"`
|
ChainWork string `json:"chainwork"`
|
||||||
PreviousHash string `json:"previousblockhash,omitempty"`
|
PreviousHash string `json:"previousblockhash,omitempty"`
|
||||||
NextHash string `json:"nextblockhash,omitempty"`
|
NextHash string `json:"nextblockhash,omitempty"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +297,8 @@ type EstimateSmartFeeResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type EstimateFeeResult struct {
|
type EstimateFeeResult struct {
|
||||||
Error Error `json:"error"`
|
Error Error `json:"error"`
|
||||||
Result json.Number `json:"result"`
|
Result common.JSONNumber `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SendRawTransactionResult struct {
|
type SendRawTransactionResult struct {
|
||||||
|
@ -637,7 +637,7 @@ func (d *DecredRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||||
Version: block.Result.Version,
|
Version: block.Result.Version,
|
||||||
Nonce: block.Result.Nonce,
|
Nonce: block.Result.Nonce,
|
||||||
Bits: block.Result.Bits,
|
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,
|
Txids: block.Result.Tx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package deeponion
|
package deeponion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package deeponion
|
package deeponion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package deeponion
|
package deeponion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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.
|
// DeepOnionRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package digibyte
|
package digibyte
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// MainnetMagic is mainnet network constant
|
// MainnetMagic is mainnet network constant
|
||||||
MainnetMagic wire.BitcoinNet = 0xdab6c3fa
|
MainnetMagic wire.BitcoinNet = 0xdab6c3fa
|
||||||
|
TestnetMagic wire.BitcoinNet = 0xddbdc8fd
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// MainNetParams are parser parameters for mainnet
|
// MainNetParams are parser parameters for mainnet
|
||||||
MainNetParams chaincfg.Params
|
MainNetParams chaincfg.Params
|
||||||
|
TestNetParams chaincfg.Params
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -23,6 +24,12 @@ func init() {
|
||||||
MainNetParams.PubKeyHashAddrID = []byte{30}
|
MainNetParams.PubKeyHashAddrID = []byte{30}
|
||||||
MainNetParams.ScriptHashAddrID = []byte{63}
|
MainNetParams.ScriptHashAddrID = []byte{63}
|
||||||
MainNetParams.Bech32HRPSegwit = "dgb"
|
MainNetParams.Bech32HRPSegwit = "dgb"
|
||||||
|
|
||||||
|
TestNetParams = chaincfg.TestNet3Params
|
||||||
|
TestNetParams.Net = TestnetMagic
|
||||||
|
TestNetParams.PubKeyHashAddrID = []byte{126}
|
||||||
|
TestNetParams.ScriptHashAddrID = []byte{140}
|
||||||
|
TestNetParams.Bech32HRPSegwit = "dgbt"
|
||||||
}
|
}
|
||||||
|
|
||||||
// DigiByteParser handle
|
// DigiByteParser handle
|
||||||
|
@ -30,18 +37,27 @@ type DigiByteParser struct {
|
||||||
*btc.BitcoinParser
|
*btc.BitcoinParser
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDigiByteParser returns new VertcoinParser instance
|
// NewDigiByteParser returns new DigiByteParser instance
|
||||||
func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser {
|
func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser {
|
||||||
return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
|
return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetChainParams contains network parameters for the main DigiByte network
|
// GetChainParams contains network parameters for the main DigiByte network
|
||||||
|
// and the DigiByte Testnet network
|
||||||
func GetChainParams(chain string) *chaincfg.Params {
|
func GetChainParams(chain string) *chaincfg.Params {
|
||||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||||
err := chaincfg.Register(&MainNetParams)
|
err := chaincfg.Register(&MainNetParams)
|
||||||
|
if err == nil {
|
||||||
|
err = chaincfg.Register(&TestNetParams)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &MainNetParams
|
switch chain {
|
||||||
|
case "test":
|
||||||
|
return &TestNetParams
|
||||||
|
default:
|
||||||
|
return &MainNetParams
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package digibyte
|
package digibyte
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package digibyte
|
package digibyte
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// DigiByteRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
package divi
|
package divi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"blockbook/bchain/coins/utils"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
|
||||||
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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 (
|
const (
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package divi
|
package divi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -16,6 +14,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package divi
|
package divi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// DivicoinRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package dogecoin
|
package dogecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"blockbook/bchain/coins/utils"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package dogecoin
|
package dogecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -16,6 +14,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dogecoin
|
package dogecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// DogecoinRPC is an interface to JSON-RPC dogecoind service.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -13,6 +12,7 @@ import (
|
||||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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"},
|
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])
|
n := parseErc20NumericProperty(contractDesc, data[64:128])
|
||||||
if n != nil {
|
if n != nil {
|
||||||
l := n.Uint64()
|
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])
|
b, err := hex.DecodeString(data[128 : 128+2*l])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if len(data) == 64 {
|
}
|
||||||
// allow string properties as 32 bytes of UTF-8 data
|
// allow string properties as UTF-8 data
|
||||||
b, err := hex.DecodeString(data)
|
b, err := hex.DecodeString(data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
i := bytes.Index(b, []byte{0})
|
i := bytes.Index(b, []byte{0})
|
||||||
if i > 0 {
|
if i > 32 {
|
||||||
b = b[:i]
|
i = 32
|
||||||
}
|
}
|
||||||
if utf8.Valid(b) {
|
if i > 0 {
|
||||||
return string(b)
|
b = b[:i]
|
||||||
}
|
}
|
||||||
|
if utf8.Valid(b) {
|
||||||
|
return string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if glog.V(1) {
|
if glog.V(1) {
|
||||||
|
@ -181,18 +183,26 @@ func (b *EthereumRPC) EthereumTypeGetErc20ContractInfo(contractDesc bchain.Addre
|
||||||
address := EIP55Address(contractDesc)
|
address := EIP55Address(contractDesc)
|
||||||
data, err := b.ethCall(erc20NameSignature, address)
|
data, err := b.ethCall(erc20NameSignature, address)
|
||||||
if err != nil {
|
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)
|
name := parseErc20StringProperty(contractDesc, data)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
data, err = b.ethCall(erc20SymbolSignature, address)
|
data, err = b.ethCall(erc20SymbolSignature, address)
|
||||||
if err != nil {
|
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)
|
symbol := parseErc20StringProperty(contractDesc, data)
|
||||||
data, err = b.ethCall(erc20DecimalsSignature, address)
|
data, err = b.ethCall(erc20DecimalsSignature, address)
|
||||||
if err != nil {
|
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 = &bchain.Erc20Contract{
|
||||||
Contract: address,
|
Contract: address,
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
"fmt"
|
||||||
"blockbook/tests/dbtestdata"
|
|
||||||
fmt "fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
|
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
|
||||||
|
@ -138,6 +139,16 @@ func TestErc20_parseErc20StringProperty(t *testing.T) {
|
||||||
args: "0x44616920537461626c65636f696e2076312e3020444444444444444444444444",
|
args: "0x44616920537461626c65636f696e2076312e3020444444444444444444444444",
|
||||||
want: "Dai Stablecoin v1.0 DDDDDDDDDDDD",
|
want: "Dai Stablecoin v1.0 DDDDDDDDDDDD",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "long",
|
||||||
|
args: "0x556e6973776170205631000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
want: "Uniswap V1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "garbage",
|
||||||
|
args: "0x2234880850896048596206002535425366538144616734015984380565810000",
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -9,6 +8,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
"golang.org/x/crypto/sha3"
|
"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 {
|
if pt.Receipt.GasUsed, err = hexDecodeBig(r.Receipt.GasUsed); err != nil {
|
||||||
return nil, errors.Annotatef(err, "GasUsed %v", r.Receipt.GasUsed)
|
return nil, errors.Annotatef(err, "GasUsed %v", r.Receipt.GasUsed)
|
||||||
}
|
}
|
||||||
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
|
if r.Receipt.Status != "" {
|
||||||
return nil, errors.Annotatef(err, "Status %v", 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))
|
ptLogs := make([]*ProtoCompleteTransaction_ReceiptType_LogType, len(r.Receipt.Logs))
|
||||||
for i, l := range 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,
|
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{
|
rr = &rpcReceipt{
|
||||||
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
|
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
|
||||||
Status: hexEncodeBig(pt.Receipt.Status),
|
Status: status,
|
||||||
Logs: logs,
|
Logs: logs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,40 +472,51 @@ func (p *EthereumParser) EthereumTypeGetErc20FromTx(tx *bchain.Tx) ([]bchain.Erc
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TxStatus is status of transaction
|
||||||
|
type TxStatus int
|
||||||
|
|
||||||
|
// statuses of transaction
|
||||||
const (
|
const (
|
||||||
txStatusUnknown = iota - 2
|
TxStatusUnknown = TxStatus(iota - 2)
|
||||||
txStatusPending
|
TxStatusPending
|
||||||
txStatusFailure
|
TxStatusFailure
|
||||||
txStatusOK
|
TxStatusOK
|
||||||
)
|
)
|
||||||
|
|
||||||
// EthereumTxData contains ethereum specific transaction data
|
// EthereumTxData contains ethereum specific transaction data
|
||||||
type EthereumTxData struct {
|
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"`
|
Nonce uint64 `json:"nonce"`
|
||||||
GasLimit *big.Int `json:"gaslimit"`
|
GasLimit *big.Int `json:"gaslimit"`
|
||||||
GasUsed *big.Int `json:"gasused"`
|
GasUsed *big.Int `json:"gasused"`
|
||||||
GasPrice *big.Int `json:"gasprice"`
|
GasPrice *big.Int `json:"gasprice"`
|
||||||
|
Data string `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEthereumTxData returns EthereumTxData from bchain.Tx
|
// GetEthereumTxData returns EthereumTxData from bchain.Tx
|
||||||
func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData {
|
func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData {
|
||||||
etd := EthereumTxData{Status: txStatusPending}
|
return GetEthereumTxDataFromSpecificData(tx.CoinSpecificData)
|
||||||
csd, ok := tx.CoinSpecificData.(completeTransaction)
|
}
|
||||||
|
|
||||||
|
// GetEthereumTxDataFromSpecificData returns EthereumTxData from coinSpecificData
|
||||||
|
func GetEthereumTxDataFromSpecificData(coinSpecificData interface{}) *EthereumTxData {
|
||||||
|
etd := EthereumTxData{Status: TxStatusPending}
|
||||||
|
csd, ok := coinSpecificData.(completeTransaction)
|
||||||
if ok {
|
if ok {
|
||||||
if csd.Tx != nil {
|
if csd.Tx != nil {
|
||||||
etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce)
|
etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce)
|
||||||
etd.GasLimit, _ = hexutil.DecodeBig(csd.Tx.GasLimit)
|
etd.GasLimit, _ = hexutil.DecodeBig(csd.Tx.GasLimit)
|
||||||
etd.GasPrice, _ = hexutil.DecodeBig(csd.Tx.GasPrice)
|
etd.GasPrice, _ = hexutil.DecodeBig(csd.Tx.GasPrice)
|
||||||
|
etd.Data = csd.Tx.Payload
|
||||||
}
|
}
|
||||||
if csd.Receipt != nil {
|
if csd.Receipt != nil {
|
||||||
switch csd.Receipt.Status {
|
switch csd.Receipt.Status {
|
||||||
case "0x1":
|
case "0x1":
|
||||||
etd.Status = txStatusOK
|
etd.Status = TxStatusOK
|
||||||
case "": // old transactions did not set status
|
case "": // old transactions did not set status
|
||||||
etd.Status = txStatusUnknown
|
etd.Status = TxStatusUnknown
|
||||||
default:
|
default:
|
||||||
etd.Status = txStatusFailure
|
etd.Status = TxStatusFailure
|
||||||
}
|
}
|
||||||
etd.GasUsed, _ = hexutil.DecodeBig(csd.Receipt.GasUsed)
|
etd.GasUsed, _ = hexutil.DecodeBig(csd.Receipt.GasUsed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/tests/dbtestdata"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
|
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() {
|
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) {
|
func TestEthereumParser_PackTx(t *testing.T) {
|
||||||
|
@ -188,6 +266,24 @@ func TestEthereumParser_PackTx(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: dbtestdata.EthTx2Packed,
|
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)
|
p := NewEthereumParser(1)
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -229,6 +325,18 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
|
||||||
want: &testTx2,
|
want: &testTx2,
|
||||||
want1: 4321000,
|
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)
|
p := NewEthereumParser(1)
|
||||||
for _, tt := range tests {
|
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
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -12,11 +11,14 @@ import (
|
||||||
|
|
||||||
ethereum "github.com/ethereum/go-ethereum"
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EthereumNet type specifies the type of ethereum network
|
// EthereumNet type specifies the type of ethereum network
|
||||||
|
@ -27,6 +29,8 @@ const (
|
||||||
MainNet EthereumNet = 1
|
MainNet EthereumNet = 1
|
||||||
// TestNet is Ropsten test network
|
// TestNet is Ropsten test network
|
||||||
TestNet EthereumNet = 3
|
TestNet EthereumNet = 3
|
||||||
|
// TestNetGoerli is Goerli test network
|
||||||
|
TestNetGoerli EthereumNet = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration represents json config file
|
// Configuration represents json config file
|
||||||
|
@ -158,6 +162,9 @@ func (b *EthereumRPC) Initialize() error {
|
||||||
b.Testnet = true
|
b.Testnet = true
|
||||||
b.Network = "testnet"
|
b.Network = "testnet"
|
||||||
break
|
break
|
||||||
|
case TestNetGoerli:
|
||||||
|
b.Testnet = true
|
||||||
|
b.Network = "goerli"
|
||||||
default:
|
default:
|
||||||
return errors.Errorf("Unknown network id %v", id)
|
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
|
// 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 {
|
if b.Mempool == nil {
|
||||||
return errors.New("Mempool not created")
|
return errors.New("Mempool not created")
|
||||||
}
|
}
|
||||||
|
@ -191,6 +198,7 @@ func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOu
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Mempool.OnNewTxAddr = onNewTxAddr
|
b.Mempool.OnNewTxAddr = onNewTxAddr
|
||||||
|
b.Mempool.OnNewTx = onNewTx
|
||||||
|
|
||||||
if err = b.subscribeEvents(); err != nil {
|
if err = b.subscribeEvents(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -332,19 +340,15 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var ver, protocol string
|
var ver string
|
||||||
if err := b.rpc.CallContext(ctx, &ver, "web3_clientVersion"); err != nil {
|
if err := b.rpc.CallContext(ctx, &ver, "web3_clientVersion"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := b.rpc.CallContext(ctx, &protocol, "eth_protocolVersion"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rv := &bchain.ChainInfo{
|
rv := &bchain.ChainInfo{
|
||||||
Blocks: int(h.Number.Int64()),
|
Blocks: int(h.Number.Int64()),
|
||||||
Bestblockhash: h.Hash().Hex(),
|
Bestblockhash: h.Hash().Hex(),
|
||||||
Difficulty: h.Difficulty.String(),
|
Difficulty: h.Difficulty.String(),
|
||||||
Version: ver,
|
Version: ver,
|
||||||
ProtocolVersion: protocol,
|
|
||||||
}
|
}
|
||||||
idi := int(id.Uint64())
|
idi := int(id.Uint64())
|
||||||
if idi == 1 {
|
if idi == 1 {
|
||||||
|
@ -569,8 +573,8 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||||
}
|
}
|
||||||
return &bchain.BlockInfo{
|
return &bchain.BlockInfo{
|
||||||
BlockHeader: *bch,
|
BlockHeader: *bch,
|
||||||
Difficulty: json.Number(head.Difficulty),
|
Difficulty: common.JSONNumber(head.Difficulty),
|
||||||
Nonce: json.Number(head.Nonce),
|
Nonce: common.JSONNumber(head.Nonce),
|
||||||
Txids: txs.Transactions,
|
Txids: txs.Transactions,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -720,6 +724,18 @@ func (b *EthereumRPC) EthereumTypeEstimateGas(params map[string]interface{}) (ui
|
||||||
if ok && len(s) > 0 {
|
if ok && len(s) > 0 {
|
||||||
msg.Data = ethcommon.FromHex(s)
|
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)
|
return b.client.EstimateGas(ctx, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// 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.
|
Package eth is a generated protocol buffer package.
|
||||||
|
|
||||||
It is generated from these files:
|
It is generated from these files:
|
||||||
tx.proto
|
bchain/coins/eth/ethtx.proto
|
||||||
|
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
ProtoCompleteTransaction
|
ProtoCompleteTransaction
|
||||||
|
@ -228,33 +228,34 @@ func init() {
|
||||||
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType")
|
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{
|
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,
|
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,
|
0x18, 0xc5, 0xe9, 0x9f, 0x99, 0xd9, 0xfd, 0xa6, 0x8a, 0x04, 0x91, 0x30, 0xec, 0x45, 0x59, 0xbc,
|
||||||
0x5e, 0x14, 0x5c, 0x7d, 0x81, 0x75, 0xc4, 0x55, 0x18, 0xd6, 0x21, 0x46, 0xef, 0xb3, 0x69, 0xd8,
|
0x18, 0xbd, 0xe8, 0xe2, 0xea, 0x0b, 0xac, 0x23, 0xae, 0xc2, 0xb0, 0x0e, 0x31, 0x7a, 0x9f, 0x49,
|
||||||
0x29, 0xb6, 0x4d, 0x69, 0x52, 0xe8, 0xbe, 0x91, 0x2f, 0xe4, 0xbb, 0x78, 0x29, 0x39, 0x4d, 0xd7,
|
0xc3, 0x36, 0x38, 0x6d, 0x4a, 0x93, 0x42, 0xf7, 0x8d, 0x7c, 0x21, 0xdf, 0xc5, 0x4b, 0xc9, 0xd7,
|
||||||
0x11, 0x51, 0xbc, 0x3b, 0xbf, 0x6f, 0xce, 0x37, 0xf9, 0xbe, 0xa4, 0xb0, 0xb5, 0x53, 0xd9, 0x0f,
|
0x74, 0x1d, 0x11, 0x65, 0x2f, 0x0a, 0xf9, 0x9d, 0x7e, 0xa7, 0x39, 0x27, 0x29, 0x9c, 0xed, 0x65,
|
||||||
0xda, 0x6a, 0x12, 0x29, 0x7b, 0x3c, 0xff, 0xb6, 0x02, 0x7a, 0x70, 0xb8, 0xd3, 0x6d, 0xdf, 0x28,
|
0x25, 0x74, 0x73, 0x21, 0x8d, 0x6e, 0xec, 0x85, 0x72, 0x95, 0x7f, 0xdc, 0x50, 0xb4, 0x9d, 0x71,
|
||||||
0xab, 0xf8, 0x20, 0x3a, 0x23, 0xa4, 0xad, 0x75, 0x47, 0x72, 0x48, 0xde, 0x34, 0x5a, 0x7e, 0xbd,
|
0x86, 0x24, 0xca, 0x55, 0xe7, 0xdf, 0x67, 0x40, 0x77, 0x1e, 0x37, 0xa6, 0x6e, 0x0f, 0xca, 0x29,
|
||||||
0x1e, 0xdb, 0x1b, 0x35, 0xd0, 0x20, 0x0f, 0x8a, 0x07, 0xec, 0x54, 0x22, 0x4f, 0xe1, 0x0c, 0x91,
|
0xde, 0x89, 0xc6, 0x0a, 0xe9, 0xb4, 0x69, 0x48, 0x0e, 0xcb, 0xb7, 0x07, 0x23, 0xbf, 0xdd, 0xf4,
|
||||||
0xd7, 0xad, 0xa2, 0x61, 0x1e, 0x14, 0x31, 0xfb, 0x25, 0x90, 0xd7, 0x10, 0xf2, 0x89, 0x46, 0x79,
|
0xf5, 0x5e, 0x75, 0x34, 0xca, 0xa3, 0xf5, 0x23, 0x76, 0x2c, 0x91, 0x33, 0x38, 0x45, 0xe4, 0xba,
|
||||||
0x50, 0x24, 0x17, 0xcf, 0x4a, 0x65, 0x8f, 0xe5, 0xdf, 0x8e, 0x2a, 0xf9, 0xc4, 0xef, 0x7a, 0xc5,
|
0x56, 0x34, 0xce, 0xa3, 0x75, 0xca, 0x7e, 0x0b, 0xe4, 0x0d, 0xc4, 0x7c, 0xa0, 0x49, 0x1e, 0xad,
|
||||||
0x42, 0x3e, 0x91, 0x1d, 0x6c, 0x98, 0x92, 0xaa, 0xee, 0x2d, 0x8d, 0xd1, 0xfa, 0xfc, 0xdf, 0x56,
|
0x97, 0x97, 0xcf, 0x0b, 0xe5, 0xaa, 0xe2, 0x5f, 0x5b, 0x15, 0x7c, 0xe0, 0x77, 0xad, 0x62, 0x31,
|
||||||
0xbf, 0x8c, 0xfe, 0xc5, 0x99, 0xfd, 0x08, 0x60, 0x3d, 0xff, 0x27, 0x39, 0x87, 0xf4, 0x52, 0x4a,
|
0x1f, 0xc8, 0x06, 0x16, 0x4c, 0x49, 0xa5, 0x5b, 0x47, 0x53, 0xb4, 0xbe, 0xf8, 0xbf, 0x35, 0x0c,
|
||||||
0x3d, 0x76, 0xf6, 0x5a, 0x77, 0x52, 0x61, 0x8d, 0x98, 0xfd, 0xa6, 0x91, 0x0c, 0xb6, 0x57, 0xc2,
|
0xa3, 0x7f, 0x72, 0xae, 0x7e, 0x46, 0x30, 0x1f, 0xbf, 0x49, 0xce, 0x21, 0xbb, 0x92, 0xd2, 0xf4,
|
||||||
0x1c, 0x86, 0x5a, 0xce, 0x35, 0x52, 0x76, 0xcf, 0xfe, 0xb7, 0x7d, 0xdd, 0xd6, 0x16, 0xbb, 0xc4,
|
0x8d, 0xbb, 0x31, 0x8d, 0x54, 0x58, 0x23, 0x65, 0x7f, 0x68, 0x64, 0x05, 0x27, 0xd7, 0xc2, 0xee,
|
||||||
0xec, 0x9e, 0xc9, 0x63, 0x58, 0x7d, 0x11, 0xcd, 0xa8, 0x30, 0x69, 0xca, 0x66, 0x20, 0x14, 0x36,
|
0x3a, 0x2d, 0xc7, 0x1a, 0x19, 0xbb, 0xe7, 0xf0, 0x6e, 0xab, 0x6b, 0xed, 0xb0, 0x4b, 0xca, 0xee,
|
||||||
0x07, 0x71, 0xd7, 0x68, 0x51, 0xd1, 0x15, 0xea, 0x0b, 0x12, 0x02, 0xf1, 0x7b, 0x61, 0x8e, 0x74,
|
0x99, 0x3c, 0x85, 0xd9, 0x57, 0x71, 0xe8, 0x15, 0x26, 0xcd, 0xd8, 0x08, 0x84, 0xc2, 0x62, 0x27,
|
||||||
0x8d, 0x32, 0xce, 0xe4, 0x21, 0x84, 0x5c, 0xd3, 0x0d, 0x2a, 0x21, 0xd7, 0x6e, 0xe7, 0xdd, 0xa0,
|
0xee, 0x0e, 0x46, 0x94, 0x74, 0x86, 0xfa, 0x84, 0x84, 0x40, 0xfa, 0x41, 0xd8, 0x8a, 0xce, 0x51,
|
||||||
0x5b, 0xba, 0x9d, 0x77, 0xdc, 0x4c, 0x5e, 0xc0, 0xa3, 0x93, 0xca, 0x1f, 0xba, 0x4a, 0x4d, 0xf4,
|
0xc6, 0x35, 0x79, 0x0c, 0x31, 0x37, 0x74, 0x81, 0x4a, 0xcc, 0x8d, 0x9f, 0x79, 0xdf, 0x99, 0x9a,
|
||||||
0x0c, 0x9f, 0xe3, 0x0f, 0x3d, 0xfb, 0x1e, 0x40, 0x72, 0x72, 0x27, 0x2e, 0xcd, 0x95, 0x30, 0x9f,
|
0x9e, 0x8c, 0x33, 0x7e, 0x4d, 0x5e, 0xc2, 0x93, 0xa3, 0xca, 0x1f, 0x9b, 0x52, 0x0d, 0xf4, 0x14,
|
||||||
0x8d, 0xaa, 0xb0, 0x7a, 0xca, 0x16, 0x24, 0x4f, 0x60, 0xfd, 0xc9, 0x0a, 0x3b, 0x1a, 0xdf, 0xd9,
|
0xaf, 0xe3, 0x2f, 0x7d, 0xf5, 0x23, 0x82, 0xe5, 0xd1, 0x99, 0xf8, 0x34, 0xd7, 0xc2, 0x7e, 0xb1,
|
||||||
0x13, 0xd9, 0x41, 0xb4, 0xd7, 0xb7, 0x34, 0xca, 0xa3, 0x22, 0xb9, 0x78, 0xf9, 0xdf, 0xb7, 0x5f,
|
0xaa, 0xc4, 0xea, 0x19, 0x9b, 0x90, 0x3c, 0x83, 0xf9, 0x67, 0x27, 0x5c, 0x6f, 0x43, 0xe7, 0x40,
|
||||||
0xee, 0xf5, 0x2d, 0xbe, 0x82, 0x73, 0x67, 0x1f, 0x61, 0xe3, 0xd9, 0x25, 0xb8, 0xac, 0xaa, 0x41,
|
0x64, 0x03, 0xc9, 0xd6, 0xdc, 0xd2, 0x24, 0x4f, 0xd6, 0xcb, 0xcb, 0x57, 0x0f, 0x3e, 0xfd, 0x62,
|
||||||
0x19, 0xb3, 0x24, 0xf0, 0xe8, 0xba, 0xbe, 0x15, 0x56, 0xf8, 0xf3, 0x71, 0x76, 0xa9, 0xb8, 0xee,
|
0x6b, 0x6e, 0xf1, 0x16, 0xbc, 0x7b, 0xf5, 0x09, 0x16, 0x81, 0x7d, 0x82, 0xab, 0xb2, 0xec, 0x94,
|
||||||
0x6b, 0x69, 0x30, 0x40, 0xca, 0x3c, 0xdd, 0xac, 0xf1, 0xb3, 0x7d, 0xf5, 0x33, 0x00, 0x00, 0xff,
|
0xb5, 0x53, 0x82, 0x80, 0xbe, 0xeb, 0x3b, 0xe1, 0x44, 0xd8, 0x1f, 0xd7, 0x3e, 0x15, 0x37, 0xad,
|
||||||
0xff, 0xde, 0xd5, 0x28, 0xa3, 0xc2, 0x02, 0x00, 0x00,
|
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 (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -11,13 +9,18 @@ import (
|
||||||
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
"github.com/martinboehm/btcd/chaincfg/chainhash"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OpZeroCoinMint = 0xc1
|
OpZeroCoinMint = 0xc1
|
||||||
OpZeroCoinSpend = 0xc2
|
OpZeroCoinSpend = 0xc2
|
||||||
OpSigmaMint = 0xc3
|
OpSigmaMint = 0xc3
|
||||||
OpSigmaSpend = 0xc4
|
OpSigmaSpend = 0xc4
|
||||||
|
OpLelantusMint = 0xc5
|
||||||
|
OpLelantusJMint = 0xc6
|
||||||
|
OpLelantusJoinSplit = 0xc7
|
||||||
|
|
||||||
MainnetMagic wire.BitcoinNet = 0xe3d9fef1
|
MainnetMagic wire.BitcoinNet = 0xe3d9fef1
|
||||||
TestnetMagic wire.BitcoinNet = 0xcffcbeea
|
TestnetMagic wire.BitcoinNet = 0xcffcbeea
|
||||||
|
@ -28,6 +31,8 @@ const (
|
||||||
MTPL = 64
|
MTPL = 64
|
||||||
|
|
||||||
SpendTxID = "0000000000000000000000000000000000000000000000000000000000000000"
|
SpendTxID = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
|
||||||
|
TransactionQuorumCommitmentType = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -58,21 +63,21 @@ func init() {
|
||||||
RegtestParams.Net = RegtestMagic
|
RegtestParams.Net = RegtestMagic
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZcoinParser handle
|
// FiroParser handle
|
||||||
type ZcoinParser struct {
|
type FiroParser struct {
|
||||||
*btc.BitcoinParser
|
*btc.BitcoinParser
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewZcoinParser returns new ZcoinParser instance
|
// NewFiroParser returns new FiroParser instance
|
||||||
func NewZcoinParser(params *chaincfg.Params, c *btc.Configuration) *ZcoinParser {
|
func NewFiroParser(params *chaincfg.Params, c *btc.Configuration) *FiroParser {
|
||||||
return &ZcoinParser{
|
return &FiroParser{
|
||||||
BitcoinParser: btc.NewBitcoinParser(params, c),
|
BitcoinParser: btc.NewBitcoinParser(params, c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetChainParams contains network parameters for the main Zcoin network,
|
// GetChainParams contains network parameters for the main Firo network,
|
||||||
// the regression test Zcoin network, the test Zcoin network and
|
// the regression test Firo network, the test Firo network and
|
||||||
// the simulation test Zcoin network, in this order
|
// the simulation test Firo network, in this order
|
||||||
func GetChainParams(chain string) *chaincfg.Params {
|
func GetChainParams(chain string) *chaincfg.Params {
|
||||||
if !chaincfg.IsRegistered(&MainNetParams) {
|
if !chaincfg.IsRegistered(&MainNetParams) {
|
||||||
err := chaincfg.Register(&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
|
// 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 {
|
if len(addrDesc) > 0 {
|
||||||
switch addrDesc[0] {
|
switch addrDesc[0] {
|
||||||
|
@ -109,6 +114,12 @@ func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor
|
||||||
return []string{"Sigmamint"}, false, nil
|
return []string{"Sigmamint"}, false, nil
|
||||||
case OpSigmaSpend:
|
case OpSigmaSpend:
|
||||||
return []string{"Sigmaspend"}, false, nil
|
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
|
// 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)
|
return p.BaseParser.PackTx(tx, height, blockTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackTx unpacks transaction from protobuf byte array
|
// 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)
|
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
|
// 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)
|
reader := bytes.NewReader(b)
|
||||||
|
|
||||||
// parse standard block header first
|
// parse standard block header first
|
||||||
|
@ -181,16 +202,37 @@ func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||||
txs := make([]bchain.Tx, ntx)
|
txs := make([]bchain.Tx, ntx)
|
||||||
|
|
||||||
for i := uint64(0); i < ntx; i++ {
|
for i := uint64(0); i < ntx; i++ {
|
||||||
tx := wire.MsgTx{}
|
tx := FiroMsgTx{}
|
||||||
|
|
||||||
err := tx.BtcDecode(reader, 0, wire.WitnessEncoding)
|
// read version and seek back
|
||||||
if err != nil {
|
var version uint32 = 0
|
||||||
|
if err = binary.Read(reader, binary.LittleEndian, &version); err != nil {
|
||||||
return nil, err
|
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
|
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
|
// 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
|
var tx bchain.Tx
|
||||||
err := json.Unmarshal(msg, &tx)
|
err := json.Unmarshal(msg, &tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -222,12 +264,12 @@ func (p *ZcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
|
||||||
vout.JsonValue = ""
|
vout.JsonValue = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
p.parseZcoinTx(&tx)
|
p.parseFiroTx(&tx)
|
||||||
|
|
||||||
return &tx, nil
|
return &tx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ZcoinParser) parseZcoinTx(tx *bchain.Tx) error {
|
func (p *FiroParser) parseFiroTx(tx *bchain.Tx) error {
|
||||||
for i := range tx.Vin {
|
for i := range tx.Vin {
|
||||||
vin := &tx.Vin[i]
|
vin := &tx.Vin[i]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// +build unittest
|
// +build unittest
|
||||||
|
|
||||||
package xzc
|
package firo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -13,17 +13,18 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"blockbook/bchain"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testTx1, testTx2, testTx3, testTx4 bchain.Tx
|
testTx1, testTx2, testTx3, testTx4, testTx5, testTx6 bchain.Tx
|
||||||
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4 string
|
rawTestTx1, rawTestTx2, rawTestTx3, rawTestTx4, rawTestTx5, rawTestTx6 string
|
||||||
rawBlock1, rawBlock2 string
|
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4, testTxPacked5, testTxPacked6 string
|
||||||
jsonTx json.RawMessage
|
rawBlock1, rawBlock2, rawBlock3 string
|
||||||
|
jsonTx json.RawMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
func readHexs(path string) []string {
|
func readHexs(path string) []string {
|
||||||
|
@ -40,12 +41,15 @@ func init() {
|
||||||
rawBlocks := readHexs("./testdata/rawblock.hex")
|
rawBlocks := readHexs("./testdata/rawblock.hex")
|
||||||
rawBlock1 = rawBlocks[0]
|
rawBlock1 = rawBlocks[0]
|
||||||
rawBlock2 = rawBlocks[1]
|
rawBlock2 = rawBlocks[1]
|
||||||
|
rawBlock3 = rawBlocks[2]
|
||||||
|
|
||||||
hextxs := readHexs("./testdata/txs.hex")
|
hextxs := readHexs("./testdata/txs.hex")
|
||||||
rawTestTx1 := hextxs[0]
|
rawTestTx1 = hextxs[0]
|
||||||
rawTestTx2 := hextxs[1]
|
rawTestTx2 = hextxs[1]
|
||||||
rawTestTx3 := hextxs[2]
|
rawTestTx3 = hextxs[2]
|
||||||
rawTestTx4 := hextxs[3]
|
rawTestTx4 = hextxs[3]
|
||||||
|
rawTestTx5 = hextxs[4]
|
||||||
|
rawTestTx6 = hextxs[5]
|
||||||
|
|
||||||
rawSpendHex := readHexs("./testdata/rawspend.hex")[0]
|
rawSpendHex := readHexs("./testdata/rawspend.hex")[0]
|
||||||
|
|
||||||
|
@ -60,13 +64,15 @@ func init() {
|
||||||
testTxPacked2 = testTxPackeds[1]
|
testTxPacked2 = testTxPackeds[1]
|
||||||
testTxPacked3 = testTxPackeds[2]
|
testTxPacked3 = testTxPackeds[2]
|
||||||
testTxPacked4 = testTxPackeds[3]
|
testTxPacked4 = testTxPackeds[3]
|
||||||
|
testTxPacked5 = testTxPackeds[4]
|
||||||
|
testTxPacked6 = testTxPackeds[5]
|
||||||
|
|
||||||
testTx1 = bchain.Tx{
|
testTx1 = bchain.Tx{
|
||||||
Hex: rawTestTx1,
|
Hex: rawTestTx1,
|
||||||
Blocktime: 1533980594,
|
Blocktime: 1533980594,
|
||||||
Time: 1533980594,
|
Time: 1533980594,
|
||||||
Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23",
|
Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23",
|
||||||
LockTime: 0,
|
LockTime: 99688,
|
||||||
Vin: []bchain.Vin{
|
Vin: []bchain.Vin{
|
||||||
{
|
{
|
||||||
ScriptSig: bchain.ScriptSig{
|
ScriptSig: bchain.ScriptSig{
|
||||||
|
@ -79,14 +85,14 @@ func init() {
|
||||||
},
|
},
|
||||||
Vout: []bchain.Vout{
|
Vout: []bchain.Vout{
|
||||||
{
|
{
|
||||||
ValueSat: *big.NewInt(18188266638),
|
ValueSat: *big.NewInt(100000000),
|
||||||
N: 0,
|
N: 0,
|
||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
|
Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ValueSat: *big.NewInt(18188266638),
|
ValueSat: *big.NewInt(871824000),
|
||||||
N: 1,
|
N: 1,
|
||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac",
|
Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac",
|
||||||
|
@ -106,9 +112,7 @@ func init() {
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
Vin: []bchain.Vin{
|
Vin: []bchain.Vin{
|
||||||
{
|
{
|
||||||
ScriptSig: bchain.ScriptSig{
|
Coinbase: rawSpendHex,
|
||||||
Hex: rawSpendHex,
|
|
||||||
},
|
|
||||||
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
|
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
Vout: 4294967295,
|
Vout: 4294967295,
|
||||||
Sequence: 2,
|
Sequence: 2,
|
||||||
|
@ -227,7 +231,7 @@ func init() {
|
||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac",
|
Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac",
|
||||||
Addresses: []string{
|
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) {
|
func TestGetAddrDesc(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
tx bchain.Tx
|
tx bchain.Tx
|
||||||
parser *ZcoinParser
|
parser *FiroParser
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args args
|
args args
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "xzc-1",
|
name: "firo-1",
|
||||||
args: args{
|
args: args{
|
||||||
tx: testTx1,
|
tx: testTx1,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// FIXME: work around handle zerocoin spend as coinbase
|
// FIXME: work around handle zerocoin spend as coinbase
|
||||||
// {
|
// {
|
||||||
// name: "xzc-2",
|
// name: "firo-2",
|
||||||
// args: args{
|
// args: args{
|
||||||
// tx: testTx2,
|
// tx: testTx2,
|
||||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
name: "xzc-3",
|
name: "firo-3",
|
||||||
args: args{
|
args: args{
|
||||||
tx: testTx3,
|
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,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
|
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -397,7 +498,7 @@ func TestGetAddressesFromAddrDescForMint(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
|
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -422,7 +523,7 @@ func TestPackTx(t *testing.T) {
|
||||||
tx bchain.Tx
|
tx bchain.Tx
|
||||||
height uint32
|
height uint32
|
||||||
blockTime int64
|
blockTime int64
|
||||||
parser *ZcoinParser
|
parser *FiroParser
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -431,50 +532,72 @@ func TestPackTx(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "xzc-1",
|
name: "firo-1",
|
||||||
args: args{
|
args: args{
|
||||||
tx: testTx1,
|
tx: testTx1,
|
||||||
height: 100002,
|
height: 100002,
|
||||||
blockTime: 1533980594,
|
blockTime: 1533980594,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: testTxPacked1,
|
want: testTxPacked1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
// FIXME: work around handle zerocoin spend as coinbase
|
// FIXME: work around handle zerocoin spend as coinbase
|
||||||
// {
|
// {
|
||||||
// name: "xzc-2",
|
// name: "firo-2",
|
||||||
// args: args{
|
// args: args{
|
||||||
// tx: testTx2,
|
// tx: testTx2,
|
||||||
// height: 11002,
|
// height: 11002,
|
||||||
// blockTime: 1481277009,
|
// blockTime: 1481277009,
|
||||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
// },
|
// },
|
||||||
// want: testTxPacked2,
|
// want: testTxPacked2,
|
||||||
// wantErr: true,
|
// wantErr: true,
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
name: "xzc-3",
|
name: "firo-3",
|
||||||
args: args{
|
args: args{
|
||||||
tx: testTx3,
|
tx: testTx3,
|
||||||
height: 126202,
|
height: 126202,
|
||||||
blockTime: 1547091829,
|
blockTime: 1547091829,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: testTxPacked3,
|
want: testTxPacked3,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "xzc-coinbase",
|
name: "firo-coinbase",
|
||||||
args: args{
|
args: args{
|
||||||
tx: testTx4,
|
tx: testTx4,
|
||||||
height: 100001,
|
height: 100001,
|
||||||
blockTime: 1533977563,
|
blockTime: 1533977563,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: testTxPacked4,
|
want: testTxPacked4,
|
||||||
wantErr: false,
|
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 {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -496,7 +619,7 @@ func TestPackTx(t *testing.T) {
|
||||||
func TestUnpackTx(t *testing.T) {
|
func TestUnpackTx(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
packedTx string
|
packedTx string
|
||||||
parser *ZcoinParser
|
parser *FiroParser
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -506,10 +629,10 @@ func TestUnpackTx(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "xzc-1",
|
name: "firo-1",
|
||||||
args: args{
|
args: args{
|
||||||
packedTx: testTxPacked1,
|
packedTx: testTxPacked1,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: &testTx1,
|
want: &testTx1,
|
||||||
want1: 100002,
|
want1: 100002,
|
||||||
|
@ -517,35 +640,55 @@ func TestUnpackTx(t *testing.T) {
|
||||||
},
|
},
|
||||||
// FIXME: work around handle zerocoin spend as coinbase
|
// FIXME: work around handle zerocoin spend as coinbase
|
||||||
// {
|
// {
|
||||||
// name: "xzc-2",
|
// name: "firo-2",
|
||||||
// args: args{
|
// args: args{
|
||||||
// packedTx: testTxPacked2,
|
// packedTx: testTxPacked2,
|
||||||
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
// },
|
// },
|
||||||
// want: &testTx2,
|
// want: &testTx2,
|
||||||
// want1: 11002,
|
// want1: 11002,
|
||||||
// wantErr: true,
|
// wantErr: true,
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
name: "xzc-3",
|
name: "firo-3",
|
||||||
args: args{
|
args: args{
|
||||||
packedTx: testTxPacked3,
|
packedTx: testTxPacked3,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: &testTx3,
|
want: &testTx3,
|
||||||
want1: 126202,
|
want1: 126202,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "xzc-coinbase",
|
name: "firo-coinbase",
|
||||||
args: args{
|
args: args{
|
||||||
packedTx: testTxPacked4,
|
packedTx: testTxPacked4,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: &testTx4,
|
want: &testTx4,
|
||||||
want1: 100001,
|
want1: 100001,
|
||||||
wantErr: false,
|
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 {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -571,7 +714,7 @@ func TestUnpackTx(t *testing.T) {
|
||||||
func TestParseBlock(t *testing.T) {
|
func TestParseBlock(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
rawBlock string
|
rawBlock string
|
||||||
parser *ZcoinParser
|
parser *FiroParser
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -584,7 +727,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
name: "normal-block",
|
name: "normal-block",
|
||||||
args: args{
|
args: args{
|
||||||
rawBlock: rawBlock1,
|
rawBlock: rawBlock1,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: &bchain.Block{
|
want: &bchain.Block{
|
||||||
BlockHeader: bchain.BlockHeader{
|
BlockHeader: bchain.BlockHeader{
|
||||||
|
@ -599,7 +742,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
name: "spend-block",
|
name: "spend-block",
|
||||||
args: args{
|
args: args{
|
||||||
rawBlock: rawBlock2,
|
rawBlock: rawBlock2,
|
||||||
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
|
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
|
||||||
},
|
},
|
||||||
want: &bchain.Block{
|
want: &bchain.Block{
|
||||||
BlockHeader: bchain.BlockHeader{
|
BlockHeader: bchain.BlockHeader{
|
||||||
|
@ -610,6 +753,21 @@ func TestParseBlock(t *testing.T) {
|
||||||
wantTxs: 4,
|
wantTxs: 4,
|
||||||
wantErr: false,
|
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 {
|
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 (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ZcoinRPC struct {
|
type FiroRPC struct {
|
||||||
*btc.BitcoinRPC
|
*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
|
// init base implementation
|
||||||
bc, err := btc.NewBitcoinRPC(config, pushHandler)
|
bc, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// init zcoin implementation
|
// init firo implementation
|
||||||
zc := &ZcoinRPC{
|
zc := &FiroRPC{
|
||||||
BitcoinRPC: bc.(*btc.BitcoinRPC),
|
BitcoinRPC: bc.(*btc.BitcoinRPC),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationTyp
|
||||||
return zc, nil
|
return zc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (zc *ZcoinRPC) Initialize() error {
|
func (zc *FiroRPC) Initialize() error {
|
||||||
ci, err := zc.GetChainInfo()
|
ci, err := zc.GetChainInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -45,7 +45,7 @@ func (zc *ZcoinRPC) Initialize() error {
|
||||||
params := GetChainParams(chainName)
|
params := GetChainParams(chainName)
|
||||||
|
|
||||||
// always create parser
|
// always create parser
|
||||||
zc.Parser = NewZcoinParser(params, zc.ChainConfig)
|
zc.Parser = NewFiroParser(params, zc.ChainConfig)
|
||||||
|
|
||||||
// parameters for getInfo request
|
// parameters for getInfo request
|
||||||
if params.Net == MainnetMagic {
|
if params.Net == MainnetMagic {
|
||||||
|
@ -61,7 +61,7 @@ func (zc *ZcoinRPC) Initialize() error {
|
||||||
return nil
|
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
|
var err error
|
||||||
|
|
||||||
if hash == "" {
|
if hash == "" {
|
||||||
|
@ -96,7 +96,7 @@ func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error)
|
||||||
return block, nil
|
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)
|
glog.V(1).Info("rpc: getblock (verbosity=true) ", hash)
|
||||||
|
|
||||||
res := btc.ResGetBlockInfo{}
|
res := btc.ResGetBlockInfo{}
|
||||||
|
@ -117,7 +117,7 @@ func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||||
return &res.Result, nil
|
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)
|
data, err := zc.GetBlockRaw(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -134,7 +134,7 @@ func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.B
|
||||||
return block, nil
|
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)
|
glog.V(1).Info("rpc: getblock (verbosity=false) ", hash)
|
||||||
|
|
||||||
res := btc.ResGetBlockRaw{}
|
res := btc.ResGetBlockRaw{}
|
||||||
|
@ -155,7 +155,7 @@ func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
|
||||||
return hex.DecodeString(res.Result)
|
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)
|
glog.V(1).Info("rpc: getrawtransaction nonverbose ", txid)
|
||||||
|
|
||||||
res := btc.ResGetRawTransactionNonverbose{}
|
res := btc.ResGetRawTransactionNonverbose{}
|
||||||
|
@ -183,7 +183,7 @@ func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||||
return tx, nil
|
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)
|
r, err := zc.getRawTransaction(txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -198,14 +198,14 @@ func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
||||||
return tx, nil
|
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 {
|
if csd, ok := tx.CoinSpecificData.(json.RawMessage); ok {
|
||||||
return csd, nil
|
return csd, nil
|
||||||
}
|
}
|
||||||
return zc.getRawTransaction(tx.Txid)
|
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)
|
glog.V(1).Info("rpc: getrawtransaction ", txid)
|
||||||
|
|
||||||
res := btc.ResGetRawTransaction{}
|
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
|
package flo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
package flo
|
package flo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package flo
|
package flo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// FloRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package fujicoin
|
package fujicoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package fujicoin
|
package fujicoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package fujicoin
|
package fujicoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// FujicoinRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package gamecredits
|
package gamecredits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package gamecredits
|
package gamecredits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package gamecredits
|
package gamecredits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// GameCreditsRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package grs
|
package grs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/base58"
|
"github.com/martinboehm/btcutil/base58"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package grs
|
package grs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -13,6 +11,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package grs
|
package grs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GroestlcoinRPC is an interface to JSON-RPC service
|
// GroestlcoinRPC is an interface to JSON-RPC service
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package koto
|
package koto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package koto
|
package koto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -13,6 +11,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package koto
|
package koto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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
|
// KotoRPC is an interface to JSON-RPC bitcoind service
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
package liquid
|
package liquid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
vlq "github.com/bsm/go-vlq"
|
vlq "github.com/bsm/go-vlq"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/txscript"
|
"github.com/martinboehm/btcd/txscript"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package liquid
|
package liquid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package liquid
|
package liquid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/juju/errors"
|
"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.
|
// LiquidRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package litecoin
|
package litecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package litecoin
|
package litecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package litecoin
|
package litecoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// LitecoinRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package monacoin
|
package monacoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// magic numbers
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package monacoin
|
package monacoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package monacoin
|
package monacoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// MonacoinRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
package monetaryunit
|
package monetaryunit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"blockbook/bchain/coins/utils"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
|
||||||
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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 (
|
const (
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package monetaryunit
|
package monetaryunit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package monetaryunit
|
package monetaryunit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// MonetaryUnitRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package myriad
|
package myriad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"blockbook/bchain/coins/utils"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/martinboehm/btcd/wire"
|
"github.com/martinboehm/btcd/wire"
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"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
|
// magic numbers
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package myriad
|
package myriad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,6 +10,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/martinboehm/btcutil/chaincfg"
|
"github.com/martinboehm/btcutil/chaincfg"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
||||||
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package myriad
|
package myriad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
|
||||||
"blockbook/bchain/coins/btc"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"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.
|
// 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