Compare commits

...

162 Commits

Author SHA1 Message Date
jebba a8595591f0 README 2021-04-05 15:16:32 -06:00
jebba cd8161a10d dark theme, minimal 2021-04-05 15:05:12 -06:00
jebba f4f7612655 more minimal 2021-04-05 14:25:58 -06:00
jebba e2a3404b06 dont pull css from cdn 2021-04-05 14:21:23 -06:00
jebba afabba64a9 minimal interface 2021-04-05 14:17:49 -06:00
jebba 473df3d139 listen on localhost, use remote host for eth 2021-04-05 13:38:29 -06:00
jebba a337163a2d deepcrayon maintainer 2021-04-05 13:31:25 -06:00
jebba 65be7edda2 just build ethereum blockbook, not backend 2021-04-05 13:31:16 -06:00
jebba 0c93f8803d no public_test.go ... 2021-04-05 13:29:13 -06:00
jebba 8fd633c6d3 dont use ssl 2021-04-05 13:08:44 -06:00
jebba 2771784113 systemd, dont want backend 2021-04-05 13:07:38 -06:00
jebba f05eff6b13 dont require backend dep 2021-04-05 13:05:55 -06:00
jebba 7ba8d7f143 s/github/spacecruft 2021-04-05 12:59:11 -06:00
jebba 14c92e8bd5 make 2021-04-05 12:59:00 -06:00
jebba 4b352b5bbc template go use spacecruft 2021-04-05 12:50:52 -06:00
jebba 124717da69 spacecruft go, not github 2021-04-05 12:19:28 -06:00
jebba 2f1c4bc3af use spacecruft repo 2021-04-05 11:55:41 -06:00
jebba 0ce520d1d5 unbrand a bit 2021-04-05 11:41:26 -06:00
jebba 8ef0a2a3d5 star favicon 2021-04-05 11:37:51 -06:00
jebba 27c9434383 about/tos 2021-04-05 11:37:06 -06:00
jebba fb64efefdc fork 2021-04-05 11:34:28 -06:00
kaladin 1f6cddd4ab
Websocket new transaction (#574) 2021-03-21 21:55:25 +01:00
CodeFace 78c8a9d499 bump Qtum 0.20.2 2021-03-21 18:23:31 +01:00
Vitalij DovhanyÄŤ d8640f4e2f
zec (+testnet): 4.2.0 → 4.3.0 (#580)
Co-authored-by: 1000101 <b1000101@pm.me>
2021-03-11 16:45:28 +01:00
vdovhanyc d588904fb3 dogecoin: 1.14.2 → 1.14.3 2021-03-11 13:37:22 +01:00
Martin Boehm e6e6e64351 Adjust ethereum backend CLI flags for geth version 1.10 2021-03-09 14:03:49 +01:00
jsimon 61c2834002 eth (+testnet): 1.9.24 → 1.10.1 2021-03-09 12:52:58 +01:00
Martin Boehm 0ae8ba57a2 Update for geth version 1.10
- remove workaround for to low maxRequestContentLength
- stop using obsolete eth_protocolVersion RPC call
2021-03-09 11:37:35 +01:00
Martin Boehm 8f3106d009 Return filtered token balance in case of an empty account #566 2021-03-04 16:17:47 +01:00
vdovhanych 099a158f8c etc: 1.11.20 → 1.11.22 2021-02-24 13:29:30 +01:00
Perlover 37c7f4fbd1 Ubuntu 20.04 doesn't work without this patch
The problem was described here:

https://github.com/trezor/blockbook/issues/568
2021-02-23 21:12:08 +01:00
Martin Boehm db597c1f66 Update build documentation 2021-02-18 09:14:58 +01:00
Martin Boehm dcbcb99055 Add possibility to build from BASE_IMAGE 2021-02-18 09:14:58 +01:00
Martin Boehm 212b767925 Add TCMALLOC option to build of rocksdb 2021-02-18 09:14:58 +01:00
WO 3fe28d185c Bump Koto to 4.2.0 2021-01-27 09:41:12 +01:00
Rikard Wissing d0a1cb29f6 Update myriad backend to 0.18.1.0 2021-01-27 09:23:50 +01:00
Martin Boehm 2be5930862 Update ports registry and copyright year #549 2021-01-21 21:43:09 +01:00
Yusaku Senga 5fdc26bc14
feat: Support Ethereum Goerli testnet (#550) 2021-01-21 21:39:37 +01:00
Martin Boehm 7e54336e0c Return info about backend in websocket getInfo request 2021-01-21 10:31:04 +01:00
Martin Boehm 7dffe2e0f9 Show consensus in explorer index page 2021-01-21 10:31:04 +01:00
Martin Boehm d992369426 Fix linting issues 2021-01-21 10:29:25 +01:00
David Hill d97b5e14e8
Update Decred (#385)
Co-authored-by: Martin <martin.boehm@1mbsoftware.net>
2021-01-21 09:25:07 +01:00
JoHnY 9df39273ea vtc (+testnet): 0.15.0.1 → 0.17.1 2021-01-18 12:37:16 +01:00
Pavol Rusnak 66c072bf25 btc (+testnet): 0.20.1 -> 0.21.0 2021-01-16 21:56:16 +01:00
Jin Eguchi 505d859f91
bitcoin_signet: 0.21.0rc2 -> 0.21.0 (#554) 2021-01-16 21:46:23 +01:00
Dehumanizer77 d631bf9265 bch (+testnet): 22.1.0 → 22.2.0 2021-01-07 19:22:59 +01:00
Martin Kuvandzhiev 295b630ec8
Adding Bitcoin Gold Testnet to the configurations (#532)
Co-authored-by: Martin <martin.boehm@1mbsoftware.net>
2020-12-29 23:19:53 +01:00
Dehumanizer77 b4149946bd zec (+testnet): 4.1.1 → 4.2.0 2020-12-29 21:21:48 +01:00
Dehumanizer77 6981222a43 etc: 1.11.18 → 1.11.20 2020-12-29 21:18:54 +01:00
Peter John Bushnell bb9fce02cb
Add Trezarcoin (TZC) (#423)
Co-authored-by: Martin <martin.boehm@1mbsoftware.net>
2020-12-29 01:39:37 +01:00
Jin Eguchi 077e637093
add bitcoin-signet (#533) 2020-12-29 00:47:50 +01:00
araarakelyan1985 15b88ef23d
Rebranding from Zcoin to Firo (#538) 2020-12-28 23:38:56 +01:00
Martin 4697d756e0 Fix display of RBF flag in tx view 2020-12-28 23:05:02 +01:00
Martin 4766110255 Add RBF info to txdetail 2020-12-28 23:05:02 +01:00
Tomas Susanka 360cac85f6 chore(static): show RBF in the transaction detail 2020-12-28 23:05:02 +01:00
jackielove4u 554041c32c Bump Groestlcoin backend version to 2.21.0 2020-12-28 22:36:30 +01:00
CodeFace d12e6551ea bump Qtum 0.20.1 2020-12-08 22:50:12 +01:00
Martin Boehm 96e8329171 Update documentation #483 2020-12-04 12:40:39 +01:00
Martin Boehm f094ee578d Merge branch 'braydonf-docs' 2020-12-04 12:09:32 +01:00
Martin Boehm 00352cb5fe Merge branch 'docs' of https://github.com/braydonf/blockbook into braydonf-docs 2020-12-04 12:08:36 +01:00
CryptoManiac c0c2dc4151 You have to link against libdl on Linux
Otherwise there will be linking error because rocksdb is importing ```dlclose```, ```dlopen``` and other functions from libdl.so.
2020-12-04 12:05:33 +01:00
Martin Boehm da1c0d762e Unify error handling of GetTransactionSpecific #395 2020-12-04 11:57:11 +01:00
Martin Boehm fc267ed2f4 Return for mempool transactions coinSpecificData #522 2020-12-04 11:57:11 +01:00
Martin Boehm 69d13e0688 Fix ETH Ropsten: websocket: read limit exceeded #490
Geth sets maxRequestContentLength to 5M.
However, Ropsten contains blocks of largers size (for example 599281).
These which cannot be fetched using API.

Fixed by hacky way of modifying the geth source before
the build of the project.
Will submit PR to go-ethereum with final fix.
2020-12-04 11:57:11 +01:00
Martin Boehm 248de3cb34 Detect fork in connectBlocks loop 2020-12-04 11:57:11 +01:00
Martin Boehm 636167c72a Store to txcache old eth transactions without status 2020-12-04 11:57:11 +01:00
Martin Boehm 24a783be50 Move websocket connection close out of channel close mutex 2020-12-04 11:57:11 +01:00
Martin Boehm 579b42cf27 Stop using mod vendor in Blockbook build 2020-12-04 11:57:11 +01:00
Martin Boehm 576b8b57b7 Upgrade to go 1.15.6, rocksdb 6.13.3 and other dependecies 2020-12-04 11:57:11 +01:00
Martin Kuvandzhiev 786047f8c2 Updating the API docs so it shows more information about the web socket communication 2020-12-04 11:53:03 +01:00
Dehumanizer77 3ccfd181b7 zcash (+testnet): 4.1.0 → 4.1.1 2020-11-23 12:00:01 +01:00
Dehumanizer77 6274f4b3d4 zcash (+testnet): 4.0.0 → 4.1.0 2020-11-16 17:06:24 +01:00
Dehumanizer77 2b786c9832 eth (+testnet): 1.9.21 → 1.9.24 2020-11-16 17:01:58 +01:00
Dehumanizer77 bc009454d0 dash (+testnet): 0.15.0.0 → 0.16.0.1 2020-11-16 16:01:37 +01:00
Dehumanizer77 5e7d0e9f75 etc: 1.11.15 → 1.11.18 2020-11-16 15:59:54 +01:00
Pavol Rusnak c915f35224
bch(+testnet): 0.22.6 -> 22.1.0 (switch to Bitcoin Cash Node)
use spoofed subversion to not confuse wallets
2020-11-16 12:26:42 +01:00
Pavol Rusnak 3369295e10
bch(+testnet): 0.22.0 -> 0.22.6 (switch to BCHN) (#511) 2020-11-16 11:43:52 +01:00
hewigovens 5534372e7c
[Zcash] Expose zcash consensus info (#508) 2020-11-12 19:56:41 +01:00
Martin Boehm fc25200ff8 Fix ineffassign errors 2020-11-12 15:41:51 +01:00
Martin Boehm 3d9954bf79 Improve locking and add panic handlers to websocket functionality 2020-11-12 15:31:59 +01:00
nezero 214d0144ef Ignore DeepOnion QT 2020-11-06 10:21:19 +01:00
Liam Alford ec79702bab Bump DeepOnion Version to v2.2 2020-11-06 10:21:19 +01:00
Scotty0448 e666e7c5a4 Bump Ritocoin backend to 2.4.2.0 2020-11-06 10:19:31 +01:00
JoHnY 4832205f45 etc: 1.11.12 -> 1.11.15 2020-10-06 14:23:07 +02:00
1000101 b05346b1a1 eth (+testnet): 1.9.20 -> 1.9.21 2020-09-15 00:51:23 +02:00
WO dcf77a5680 Bump Koto to 4.0.0 2020-09-15 00:35:17 +02:00
1000101 7f1cf09d05 zec (+testnet): 3.1.0 -> 4.0.0 2020-09-08 11:24:32 +02:00
Martin a1993173ab
Go ethereum v1.9.20 (#482) issue #481
Handle different behavior of geth from v1.9.15
Bump go-ethereum dependecy to v1.9.20
2020-09-03 10:11:37 +02:00
jackielove4u bea6b6230f Add fiat rates for Groestlcoin 2020-09-01 10:10:33 +02:00
jackielove4u 72486c606f Bump Groestlcoin backend version to 2.20.1 2020-08-26 13:28:36 +02:00
1000101 a8ee6aefb0 bch(+testnet): 0.21.10->0.22.0 2020-08-26 13:24:57 +02:00
1000101 52cbc7162d eth(+testnet): 1.9.19->1.9.20 2020-08-26 10:31:22 +02:00
Pavol Rusnak 81ce876d8b
nix: add dependencies to shell.nix 2020-08-21 16:11:21 +02:00
Braydon Fuller 7b70ee0ad0
Add blockchaincfg.json to .gitignore 2020-08-20 15:21:55 -07:00
Braydon Fuller a83cb7684f
Update build documentation 2020-08-20 15:21:23 -07:00
Pavol Rusnak 0f4eadd935
nix: add trivial shell.nix for development 2020-08-20 17:52:58 +02:00
1000101 e66fa79383 btg: 0.17.2->0.17.3 2020-08-20 10:34:33 +02:00
1000101 f99406e9cf zec(+testnet): 3.0.0->3.1.0 2020-08-20 10:34:04 +02:00
1000101 be73064223 eth(+testnet): 1.9.13->1.9.19 2020-08-20 10:24:28 +02:00
Panu 79907e7aa5
Update Zcoin transaction parser and bump binary version (#466) 2020-08-20 10:23:23 +02:00
1000101 2fb1e779c0 etc: 1.11.7->1.11.12 2020-08-20 10:15:17 +02:00
1000101 a530f5612a btc(+testnet): 0.20.0->0.20.1 2020-08-20 10:05:21 +02:00
Martin Boehm ab285c6b05 Increase max size of reorg of ETC to 10000 blocks 2020-08-06 10:27:08 +02:00
Martin Boehm 17c9080135 Include eth transactions in unknown status into balance history 2020-07-30 16:02:08 +02:00
1000101 791948623e bgold: 0.15.2->0.17.2 2020-07-16 00:46:35 +02:00
Scotty0448 af5e8f18ba Bump Ravencoin backend to 4.2.1.0 2020-07-15 23:55:12 +02:00
root 07ac3c8401 bcash (+testnet): Bump backend 0.21.0 -> 0.21.10 2020-07-07 16:56:44 +02:00
Martin Boehm 83616bce83 Fix integration tests script 2020-06-30 15:06:11 +02:00
codeface 22145d0cc2 bump Qtum 0.19.1 2020-06-29 17:35:30 +02:00
Dehumanizer77 92ae2052c3 etc: Bump backend 1.11.2->1.11.7 2020-06-29 17:17:36 +02:00
Dehumanizer77 30149e51d2 ltc (+testnet): Bump backend 0.17.1->0.18.1 2020-06-29 17:08:52 +02:00
Martin Boehm abb6453fb3 Fix dash testnet config #447 2020-06-22 18:40:54 +02:00
Martin Boehm eb4e10ac67 Bump Blockbook version to 0.3.4 2020-06-12 11:52:21 +02:00
1000101 5350027e1d btc (+testnet): Bump backend 0.19.0.1->0.20.0 2020-06-03 18:46:00 +02:00
1000101 7d6c61623e zec (+testnet): Bump backend 2.1.2->3.0.0 2020-05-29 20:03:01 +02:00
Martin Boehm 994567aed9 Add fee value to unspent transactions balance 2020-05-26 23:21:25 +02:00
Martin Boehm dd7964297d Suppress logging of MQ errors 2020-05-24 19:18:23 +02:00
Martin Boehm 3be3bb5c3d Regenerate registry of ports 2020-05-24 17:58:44 +02:00
Martin Boehm 0a3ea6e225 Send websocket notification on new tx for input addresses 2020-05-24 17:58:29 +02:00
Martin Boehm bc001ce3a3 Make logs cleaner by not logging public API errors in websocket 2020-05-22 11:19:37 +02:00
Martin Boehm 76324be8ec Modify logging 2020-05-21 22:43:18 +02:00
Martin Boehm 01d8e48e73 Unconfirmed eth balance not being updated #408 2020-05-21 18:05:16 +02:00
Martin Boehm ff607bc334 Check ERC20 contract balance if no transactions were done for address 2020-05-21 18:05:16 +02:00
Martin Boehm e60c320ae7 Allow parameters value, gasPrice and gas to be passed to ETH estimateFee 2020-05-21 18:05:16 +02:00
Martin Boehm dd2dc6b2ee Add sentToSelf to BalanceHistory 2020-05-21 18:05:16 +02:00
wakiyamap b957ed66ab Add fiat rate(monacoin) 2020-05-20 00:05:26 +02:00
Adam Collier 3ebe99edb2
Add support for DigiByte Testnet (#432) 2020-05-19 23:58:46 +02:00
v bad9f992e1 eth-like backends listen on localhost instead * 2020-05-19 23:56:35 +02:00
jackielove4u 707ac28954 Bump Groestlcoin backend version to 2.19.1 2020-05-12 21:56:47 +02:00
Martin Boehm b6961ca600 Bump Blockbook version to 0.3.3 2020-05-11 19:12:39 +02:00
Martin Boehm 5492a51534 Upgrade gorilla websocket library to v1.4.2 2020-05-11 19:10:51 +02:00
Martin Boehm a7d95a49df Use go1.14.2 to build Blockbook 2020-05-10 00:26:47 +02:00
Martin Boehm ee3217aba8 Use common.JSONNumber instead of json.Number 2020-05-10 00:14:14 +02:00
Martin Boehm c3d58f0649 Add common.JSONNumber type 2020-05-10 00:02:34 +02:00
Martin Boehm 180b5655d5 Update documentation 2020-05-09 22:54:57 +02:00
hewigovens 3ba7289587 Add data field to EthereumSpecific 2020-05-09 21:43:33 +02:00
ciripel a34ee217b5 Fixed issue with folder containing spaces in the path of the repo 2020-05-09 12:01:54 +02:00
WO 11e9de2ffe Bump Koto backend to 2.1.2 2020-05-09 11:59:05 +02:00
Martin Boehm 81a1acd6f8 Update documentation to reflect the use of go modules 2020-05-09 11:21:53 +02:00
Martin Boehm 997fa661e7 Merge branch 'master' into gomod 2020-05-09 01:50:51 +02:00
Martin Boehm 8a926a0799 Merge branch 'master' of github.com:trezor/blockbook 2020-05-02 17:25:10 +02:00
Martin Boehm 828e10b629 Parsing of ERC20 name, symbol and decimals in different format #400 2020-05-02 17:24:56 +02:00
Scotty0448 a6fd137283 Bump Ravencoin backend to 4.1.0.0 2020-05-02 00:48:17 +02:00
Dehumanizer77 f97d23590c zec (+testnet): Bump backend 2.1.1-1->2.1.2 2020-05-02 00:41:00 +02:00
Dehumanizer77 945827c330 vtc (+testnet): Bump backend 0.14.0->0.15.0.1 2020-04-30 13:13:52 +02:00
Dehumanizer77 42bc7d2ba3 eth (+testnet): Bump backend 1.9.11->1.9.13 2020-04-30 10:20:21 +02:00
Adam Collier ddd981a405 Add in xpub magic to vertcoin testnet 2020-04-16 16:29:09 +02:00
Dehumanizer77 ea6a7e0db6 etc: Bump backend 1.11.1 -> 1.11.2 2020-04-16 11:43:32 +02:00
Scotty0448 7eb4675f54 Update Ravencoin support 2020-04-16 09:55:34 +02:00
ciripel 124dee84fa
SnowGem Support (#342)
* SnowGem Support

* changed bynary_url to debian9.11 source
The Debian Source contain also the fetch_params.sh

* changed sha256 source

* Fix integration tests config file after merge

* Implemented snowgem parser

* fixed paxkedTx

* Fixed testdata tx hex

Co-authored-by: Martin <martin.boehm@1mbsoftware.net>
2020-04-11 16:34:37 +02:00
Martin Boehm 5f1957b4ff Upgrade btcd and btcutil libraries 2020-04-11 14:59:50 +02:00
Martin Boehm c43a7a4feb Merge branch 'gomod' of https://github.com/dajohi/blockbook into gomod 2020-03-21 01:17:42 +01:00
ilmango e99a8eba65
Add BitZeny (ZNY) (#383)
* Add BitZeny

* Fix test packed tx

* Fix exec command template
2020-03-21 00:39:24 +01:00
Martin Boehm 2a3c5426ca Improve remove empty map on websocket unsubscribe 2020-03-17 00:08:00 +01:00
Kirill Fomichev c2e32b0a25 Remove empty map on address unsubscribe 2020-03-16 23:58:45 +01:00
Martin Boehm 4338d10dcb Use newer version of btcd and btcutil libraries 2020-03-14 00:14:52 +01:00
TheTrunk b4bddc8c0e
update zelcash binaries to 4.0.0 (#389) 2020-03-11 16:12:14 +01:00
JoHnY c705600aae
etc: Bump backend 1.11.0-core -> 1.11.1 #391 #387 2020-03-11 15:44:44 +01:00
Martin Boehm 48584b3070 Disable downloading of fiat rates for Bitcoin and Ethereum testnet 2020-03-06 14:34:58 +01:00
David Hill 395db88a60 Adjust test scripts 2020-03-05 11:54:42 -05:00
David Hill 8f8ade727c Adjust build scripts 2020-03-05 11:54:42 -05:00
David Hill 13527bda06 build: go module support 2020-03-05 11:54:42 -05:00
261 changed files with 6731 additions and 3559 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ debug*
docker/blockbook
build/pkg-defs
build/blockbook
build/blockchaincfg.json
build/ldb
build/sst_dump
build/*.deb

298
Gopkg.lock generated
View File

@ -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

View File

@ -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"

View File

@ -1,8 +1,9 @@
BIN_IMAGE = blockbook-build
DEB_IMAGE = blockbook-build-deb
PACKAGER = $(shell id -u):$(shell id -g)
BASE_IMAGE = $$(awk -F= '$$1=="ID" { print $$2 ;}' /etc/os-release):$$(awk -F= '$$1=="VERSION_ID" { print $$2 ;}' /etc/os-release | tr -d '"')
NO_CACHE = false
UPDATE_VENDOR = 1
TCMALLOC =
ARGS ?=
TARGETS=$(subst .json,, $(shell ls configs/coins))
@ -10,28 +11,28 @@ TARGETS=$(subst .json,, $(shell ls configs/coins))
.PHONY: build build-debug test deb
build: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build ARGS="$(ARGS)"
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build ARGS="$(ARGS)"
build-debug: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(BIN_IMAGE) make build-debug ARGS="$(ARGS)"
test: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test ARGS="$(ARGS)"
test-integration: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-integration ARGS="$(ARGS)"
test-all: .bin-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" --network="host" $(BIN_IMAGE) make test-all ARGS="$(ARGS)"
deb-backend-%: .deb-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS)
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh backend $* $(ARGS)
deb-blockbook-%: .deb-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS)
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh blockbook $* $(ARGS)
deb-%: .deb-image
docker run -t --rm -e PACKAGER=$(PACKAGER) -e UPDATE_VENDOR=$(UPDATE_VENDOR) -v $(CURDIR):/src -v $(CURDIR)/build:/out $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS)
docker run -t --rm -e PACKAGER=$(PACKAGER) -v "$(CURDIR):/src" -v "$(CURDIR)/build:/out" $(DEB_IMAGE) /build/build-deb.sh all $* $(ARGS)
deb-blockbook-all: clean-deb $(addprefix deb-blockbook-, $(TARGETS))
@ -44,8 +45,8 @@ build-images: clean-images
.bin-image:
@if [ $$(build/tools/image_status.sh $(BIN_IMAGE):latest build/docker) != "ok" ]; then \
echo "Building image $(BIN_IMAGE)..."; \
docker build --no-cache=$(NO_CACHE) -t $(BIN_IMAGE) build/docker/bin; \
echo "Building image $(BIN_IMAGE) from $(BASE_IMAGE)"; \
docker build --no-cache=$(NO_CACHE) --build-arg TCMALLOC=$(TCMALLOC) --build-arg BASE_IMAGE=$(BASE_IMAGE) -t $(BIN_IMAGE) build/docker/bin; \
else \
echo "Image $(BIN_IMAGE) is up to date"; \
fi

74
README-upstream.md 100644
View File

@ -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).

View File

@ -1,74 +1,57 @@
[![Go Report Card](https://goreportcard.com/badge/trezor/blockbook)](https://goreportcard.com/report/trezor/blockbook)
# Fork
Fork of Trezor Blockbook.
# Blockbook
**Blockbook** is back-end service for Trezor wallet. Main features of **Blockbook** are:
The differences:
- index of addresses and address balances of the connected block chain
- fast searches in the indexes
- simple blockchain explorer
- websocket, API and legacy Bitcore Insight compatible socket.io interfaces
- support of multiple coins (Bitcoin and Ethereum type), with easy extensibility for other coins
- scripts for easy creation of debian packages for backend and blockbook
* Just for Ethereum.
## Build and installation instructions
* Use existing `geth --full` server.
Officially supported platform is **Debian Linux** and **AMD64** architecture.
* Don't require `backend-*` package.
Memory and disk requirements for initial synchronization of **Bitcoin mainnet** are around 32 GB RAM and over 180 GB of disk space. After initial synchronization, fully synchronized instance uses about 10 GB RAM.
Other coins should have lower requirements, depending on the size of their block chain. Note that fast SSD disks are highly
recommended.
* Minimal UI, dark theme.
User installation guide is [here](https://wiki.trezor.io/User_manual:Running_a_local_instance_of_Trezor_Wallet_backend_(Blockbook)).
* Listen only on localhost, no SSL.
Developer build guide is [here](/docs/build.md).
* Use spacecruft repos, not github.
Contribution guide is [here](CONTRIBUTING.md).
* Don't use CDN.
## Implemented coins
# Install
Blockbook currently supports over 30 coins. The Trezor team implemented
```
# Install docker, etc.
git clone https://spacecruft.org/spacecruft/blockbook
cd blockbook
make deb-blockbook-ethereum
dpkg -i build/blockbook-ethereum_0.3.4_amd64.deb
```
- Bitcoin, Bitcoin Cash, Zcash, Dash, Litecoin, Bitcoin Gold, Ethereum, Ethereum Classic, Dogecoin, Namecoin, Vertcoin, DigiByte, Liquid
Edit config:
```
vim /opt/coins/blockbook/ethereum/config/blockchaincfg.json
```
the rest of coins were implemented by the community.
XXX Hardcoded into systemd script, set `geth` node:
Testnets for some coins are also supported, for example:
- Bitcoin Testnet, Bitcoin Cash Testnet, ZCash Testnet, Ethereum Testnet Ropsten
```
vim /lib/systemd/system/blockbook-ethereum.service
systemctl daemon-reload
```
List of all implemented coins is in [the registry of ports](/docs/ports.md).
Start:
```
systemctl start blockbook-ethereum.service
```
## Common issues when running Blockbook or implementing additional coins
Logs:
```
tail -f /opt/coins/blockbook/ethereum/logs/blockbook.INFO
```
#### Out of memory when doing initial synchronization
# Upstream
Fork of Trezor Blockbook. See `README-upstream.md`.
How to reduce memory footprint of the initial sync:
* https://github.com/trezor/blockbook
- disable rocksdb cache by parameter `-dbcache=0`, the default size is 500MB
- run blockbook with parameter `-workers=1`. This disables bulk import mode, which caches a lot of data in memory (not in rocksdb cache). It will run about twice as slowly but especially for smaller blockchains it is no problem at all.
Please add your experience to this [issue](https://github.com/trezor/blockbook/issues/43).
#### Error `internalState: database is in inconsistent state and cannot be used`
Blockbook was killed during the initial import, most commonly by OOM killer. By default, Blockbook performs the initial import in bulk import mode, which for performance reasons does not store all the data immediately to the database. If Blockbook is killed during this phase, the database is left in an inconsistent state.
See above how to reduce the memory footprint, delete the database files and run the import again.
Check [this](https://github.com/trezor/blockbook/issues/89) or [this](https://github.com/trezor/blockbook/issues/147) issue for more info.
#### Running on Ubuntu
[This issue](https://github.com/trezor/blockbook/issues/45) discusses how to run Blockbook on Ubuntu. If you have some additional experience with Blockbook on Ubuntu, please add it to [this issue](https://github.com/trezor/blockbook/issues/45).
#### My coin implementation is reporting parse errors when importing blockchain
Your coin's block/transaction data may not be compatible with `BitcoinParser` `ParseBlock`/`ParseTx`, which is used by default. In that case, implement your coin in a similar way we used in case of [zcash](https://github.com/trezor/blockbook/tree/master/bchain/coins/zec) and some other coins. The principle is not to parse the block/transaction data in Blockbook but instead to get parsed transactions as json from the backend.
## Data storage in RocksDB
Blockbook stores data the key-value store RocksDB. Database format is described [here](/docs/rocksdb.md).
## API
Blockbook API is described [here](/docs/api.md).

View File

@ -1,14 +1,16 @@
package api
import (
"blockbook/bchain"
"blockbook/common"
"blockbook/db"
"encoding/json"
"errors"
"math/big"
"sort"
"time"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
"spacecruft.org/spacecruft/blockbook/common"
"spacecruft.org/spacecruft/blockbook/db"
)
const maxUint32 = ^uint32(0)
@ -169,11 +171,12 @@ type TokenTransfer struct {
// EthereumSpecific contains ethereum specific transaction data
type EthereumSpecific struct {
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending
Nonce uint64 `json:"nonce"`
GasLimit *big.Int `json:"gasLimit"`
GasUsed *big.Int `json:"gasUsed"`
GasPrice *Amount `json:"gasPrice"`
Status eth.TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending
Nonce uint64 `json:"nonce"`
GasLimit *big.Int `json:"gasLimit"`
GasUsed *big.Int `json:"gasUsed"`
GasPrice *Amount `json:"gasPrice"`
Data string `json:"data,omitempty"`
}
// Tx holds information about a transaction
@ -193,8 +196,7 @@ type Tx struct {
FeesSat *Amount `json:"fees,omitempty"`
Hex string `json:"hex,omitempty"`
Rbf bool `json:"rbf,omitempty"`
CoinSpecificData interface{} `json:"-"`
CoinSpecificJSON json.RawMessage `json:"-"`
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty"`
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty"`
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty"`
}
@ -224,6 +226,8 @@ const (
AddressFilterVoutInputs = -2
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
AddressFilterVoutOutputs = -3
// AddressFilterVoutQueryNotNecessary signals that query for transactions is not necessary as there are no transactions for specified contract filter
AddressFilterVoutQueryNotNecessary = -4
// TokensToReturnNonzeroBalance - return only tokens with nonzero balance
TokensToReturnNonzeroBalance TokensToReturn = 0
@ -299,12 +303,13 @@ func (a Utxos) Less(i, j int) bool {
// BalanceHistory contains info about one point in time of balance history
type BalanceHistory struct {
Time uint32 `json:"time"`
Txs uint32 `json:"txs"`
ReceivedSat *Amount `json:"received"`
SentSat *Amount `json:"sent"`
FiatRates map[string]float64 `json:"rates,omitempty"`
Txid string `json:"txid,omitempty"`
Time uint32 `json:"time"`
Txs uint32 `json:"txs"`
ReceivedSat *Amount `json:"received"`
SentSat *Amount `json:"sent"`
SentToSelfSat *Amount `json:"sentToSelf"`
FiatRates map[string]float64 `json:"rates,omitempty"`
Txid string `json:"txid,omitempty"`
}
// BalanceHistories is array of BalanceHistory
@ -326,8 +331,9 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
bhs := make(BalanceHistories, 0)
if len(a) > 0 {
bha := BalanceHistory{
SentSat: &Amount{},
ReceivedSat: &Amount{},
ReceivedSat: &Amount{},
SentSat: &Amount{},
SentToSelfSat: &Amount{},
}
sort.Sort(a)
for i := range a {
@ -340,17 +346,19 @@ func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories
bhs = append(bhs, bha)
}
bha = BalanceHistory{
Time: time,
SentSat: &Amount{},
ReceivedSat: &Amount{},
Time: time,
ReceivedSat: &Amount{},
SentSat: &Amount{},
SentToSelfSat: &Amount{},
}
}
if bha.Txid != bh.Txid {
bha.Txs += bh.Txs
bha.Txid = bh.Txid
}
(*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat))
(*big.Int)(bha.ReceivedSat).Add((*big.Int)(bha.ReceivedSat), (*big.Int)(bh.ReceivedSat))
(*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat))
(*big.Int)(bha.SentToSelfSat).Add((*big.Int)(bha.SentToSelfSat), (*big.Int)(bh.SentToSelfSat))
}
if bha.Txs > 0 {
bha.Txid = ""
@ -368,19 +376,19 @@ type Blocks struct {
// BlockInfo contains extended block header data and a list of block txids
type BlockInfo struct {
Hash string `json:"hash"`
Prev string `json:"previousBlockHash,omitempty"`
Next string `json:"nextBlockHash,omitempty"`
Height uint32 `json:"height"`
Confirmations int `json:"confirmations"`
Size int `json:"size"`
Time int64 `json:"time,omitempty"`
Version json.Number `json:"version"`
MerkleRoot string `json:"merkleRoot"`
Nonce string `json:"nonce"`
Bits string `json:"bits"`
Difficulty string `json:"difficulty"`
Txids []string `json:"tx,omitempty"`
Hash string `json:"hash"`
Prev string `json:"previousBlockHash,omitempty"`
Next string `json:"nextBlockHash,omitempty"`
Height uint32 `json:"height"`
Confirmations int `json:"confirmations"`
Size int `json:"size"`
Time int64 `json:"time,omitempty"`
Version common.JSONNumber `json:"version"`
MerkleRoot string `json:"merkleRoot"`
Nonce string `json:"nonce"`
Bits string `json:"bits"`
Difficulty string `json:"difficulty"`
Txids []string `json:"tx,omitempty"`
}
// Block contains information about block
@ -413,26 +421,10 @@ type BlockbookInfo struct {
About string `json:"about"`
}
// BackendInfo is used to get information about blockchain
type BackendInfo struct {
BackendError string `json:"error,omitempty"`
Chain string `json:"chain,omitempty"`
Blocks int `json:"blocks,omitempty"`
Headers int `json:"headers,omitempty"`
BestBlockHash string `json:"bestBlockHash,omitempty"`
Difficulty string `json:"difficulty,omitempty"`
SizeOnDisk int64 `json:"sizeOnDisk,omitempty"`
Version string `json:"version,omitempty"`
Subversion string `json:"subversion,omitempty"`
ProtocolVersion string `json:"protocolVersion,omitempty"`
Timeoffset float64 `json:"timeOffset,omitempty"`
Warnings string `json:"warnings,omitempty"`
}
// SystemInfo contains information about the running blockbook and backend instance
type SystemInfo struct {
Blockbook *BlockbookInfo `json:"blockbook"`
Backend *BackendInfo `json:"backend"`
Blockbook *BlockbookInfo `json:"blockbook"`
Backend *common.BackendInfo `json:"backend"`
}
// MempoolTxid contains information about a transaction in mempool

View File

@ -67,20 +67,22 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
name: "one",
a: []BalanceHistory{
{
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
Time: 1521514812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
SentToSelfSat: (*Amount)(big.NewInt(1)),
Time: 1521514812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
},
},
groupByTime: 3600,
want: []BalanceHistory{
{
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
Time: 1521514800,
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
SentToSelfSat: (*Amount)(big.NewInt(1)),
Time: 1521514800,
Txs: 1,
},
},
},
@ -88,67 +90,76 @@ func TestBalanceHistories_SortAndAggregate(t *testing.T) {
name: "aggregate",
a: []BalanceHistory{
{
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
Time: 1521504812,
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(1)),
SentSat: (*Amount)(big.NewInt(2)),
SentToSelfSat: (*Amount)(big.NewInt(0)),
Time: 1521504812,
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(3)),
SentSat: (*Amount)(big.NewInt(4)),
Time: 1521504812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(3)),
SentSat: (*Amount)(big.NewInt(4)),
SentToSelfSat: (*Amount)(big.NewInt(2)),
Time: 1521504812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(5)),
SentSat: (*Amount)(big.NewInt(6)),
Time: 1521514812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(5)),
SentSat: (*Amount)(big.NewInt(6)),
SentToSelfSat: (*Amount)(big.NewInt(3)),
Time: 1521514812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(7)),
SentSat: (*Amount)(big.NewInt(8)),
Time: 1521504812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(7)),
SentSat: (*Amount)(big.NewInt(8)),
SentToSelfSat: (*Amount)(big.NewInt(3)),
Time: 1521504812,
Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840",
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(9)),
SentSat: (*Amount)(big.NewInt(10)),
Time: 1521534812,
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(9)),
SentSat: (*Amount)(big.NewInt(10)),
SentToSelfSat: (*Amount)(big.NewInt(5)),
Time: 1521534812,
Txid: "0011223344556677889900112233445566778899001122334455667788990011",
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(11)),
SentSat: (*Amount)(big.NewInt(12)),
Time: 1521534812,
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(11)),
SentSat: (*Amount)(big.NewInt(12)),
SentToSelfSat: (*Amount)(big.NewInt(6)),
Time: 1521534812,
Txid: "1122334455667788990011223344556677889900112233445566778899001100",
Txs: 1,
},
},
groupByTime: 3600,
want: []BalanceHistory{
{
ReceivedSat: (*Amount)(big.NewInt(11)),
SentSat: (*Amount)(big.NewInt(14)),
Time: 1521504000,
Txs: 2,
ReceivedSat: (*Amount)(big.NewInt(11)),
SentSat: (*Amount)(big.NewInt(14)),
SentToSelfSat: (*Amount)(big.NewInt(5)),
Time: 1521504000,
Txs: 2,
},
{
ReceivedSat: (*Amount)(big.NewInt(5)),
SentSat: (*Amount)(big.NewInt(6)),
Time: 1521514800,
Txs: 1,
ReceivedSat: (*Amount)(big.NewInt(5)),
SentSat: (*Amount)(big.NewInt(6)),
SentToSelfSat: (*Amount)(big.NewInt(3)),
Time: 1521514800,
Txs: 1,
},
{
ReceivedSat: (*Amount)(big.NewInt(20)),
SentSat: (*Amount)(big.NewInt(22)),
Time: 1521532800,
Txs: 2,
ReceivedSat: (*Amount)(big.NewInt(20)),
SentSat: (*Amount)(big.NewInt(22)),
SentToSelfSat: (*Amount)(big.NewInt(11)),
Time: 1521532800,
Txs: 2,
},
},
},

View File

@ -1,8 +1,9 @@
package api
import (
"blockbook/bchain"
"math/big"
"spacecruft.org/spacecruft/blockbook/bchain"
)
// ScriptSigV1 is used for legacy api v1

View File

@ -1,10 +1,6 @@
package api
import (
"blockbook/bchain"
"blockbook/bchain/coins/eth"
"blockbook/common"
"blockbook/db"
"bytes"
"encoding/json"
"fmt"
@ -18,6 +14,10 @@ import (
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
"spacecruft.org/spacecruft/blockbook/common"
"spacecruft.org/spacecruft/blockbook/db"
)
// Worker is handle to api worker
@ -253,32 +253,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
if err != nil {
glog.Errorf("GetErc20FromTx error %v, %v", err, bchainTx)
}
tokens = make([]TokenTransfer, len(ets))
for i := range ets {
e := &ets[i]
cd, err := w.chainParser.GetAddrDescFromAddress(e.Contract)
if err != nil {
glog.Errorf("GetAddrDescFromAddress error %v, contract %v", err, e.Contract)
continue
}
erc20c, err := w.chain.EthereumTypeGetErc20ContractInfo(cd)
if err != nil {
glog.Errorf("GetErc20ContractInfo error %v, contract %v", err, e.Contract)
}
if erc20c == nil {
erc20c = &bchain.Erc20Contract{Name: e.Contract}
}
tokens[i] = TokenTransfer{
Type: ERC20TokenType,
Token: e.Contract,
From: e.From,
To: e.To,
Decimals: erc20c.Decimals,
Value: (*Amount)(&e.Tokens),
Name: erc20c.Name,
Symbol: erc20c.Symbol,
}
}
tokens = w.getTokensFromErc20(ets)
ethTxData := eth.GetEthereumTxData(bchainTx)
// mempool txs do not have fees yet
if ethTxData.GasUsed != nil {
@ -293,12 +268,14 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
GasUsed: ethTxData.GasUsed,
Nonce: ethTxData.Nonce,
Status: ethTxData.Status,
Data: ethTxData.Data,
}
}
// for now do not return size, we would have to compute vsize of segwit transactions
// size:=len(bchainTx.Hex) / 2
var sj json.RawMessage
if specificJSON {
// return CoinSpecificData for all mempool transactions or if requested
if specificJSON || bchainTx.Confirmations == 0 {
sj, err = w.chain.GetTransactionSpecific(bchainTx)
if err != nil {
return nil, err
@ -323,14 +300,140 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height int, spe
Rbf: rbf,
Vin: vins,
Vout: vouts,
CoinSpecificData: bchainTx.CoinSpecificData,
CoinSpecificJSON: sj,
CoinSpecificData: sj,
TokenTransfers: tokens,
EthereumSpecific: ethSpecific,
}
return r, nil
}
// GetTransactionFromMempoolTx converts bchain.MempoolTx to Tx, with limited amount of data
// it is not doing any request to backend or to db
func (w *Worker) GetTransactionFromMempoolTx(mempoolTx *bchain.MempoolTx) (*Tx, error) {
var err error
var valInSat, valOutSat, feesSat big.Int
var pValInSat *big.Int
var tokens []TokenTransfer
var ethSpecific *EthereumSpecific
vins := make([]Vin, len(mempoolTx.Vin))
rbf := false
for i := range mempoolTx.Vin {
bchainVin := &mempoolTx.Vin[i]
vin := &vins[i]
vin.Txid = bchainVin.Txid
vin.N = i
vin.Vout = bchainVin.Vout
vin.Sequence = int64(bchainVin.Sequence)
// detect explicit Replace-by-Fee transactions as defined by BIP125
if bchainVin.Sequence < 0xffffffff-1 {
rbf = true
}
vin.Hex = bchainVin.ScriptSig.Hex
vin.Coinbase = bchainVin.Coinbase
if w.chainType == bchain.ChainBitcoinType {
// bchainVin.Txid=="" is coinbase transaction
if bchainVin.Txid != "" {
vin.ValueSat = (*Amount)(&bchainVin.ValueSat)
vin.AddrDesc = bchainVin.AddrDesc
vin.Addresses, vin.IsAddress, _ = w.chainParser.GetAddressesFromAddrDesc(vin.AddrDesc)
if vin.ValueSat != nil {
valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat))
}
}
} else if w.chainType == bchain.ChainEthereumType {
if len(bchainVin.Addresses) > 0 {
vin.AddrDesc, err = w.chainParser.GetAddrDescFromAddress(bchainVin.Addresses[0])
if err != nil {
glog.Errorf("GetAddrDescFromAddress error %v, tx %v, bchainVin %v", err, mempoolTx.Txid, bchainVin)
}
vin.Addresses = bchainVin.Addresses
vin.IsAddress = true
}
}
}
vouts := make([]Vout, len(mempoolTx.Vout))
for i := range mempoolTx.Vout {
bchainVout := &mempoolTx.Vout[i]
vout := &vouts[i]
vout.N = i
vout.ValueSat = (*Amount)(&bchainVout.ValueSat)
valOutSat.Add(&valOutSat, &bchainVout.ValueSat)
vout.Hex = bchainVout.ScriptPubKey.Hex
vout.AddrDesc, vout.Addresses, vout.IsAddress, err = w.getAddressesFromVout(bchainVout)
if err != nil {
glog.V(2).Infof("getAddressesFromVout error %v, %v, output %v", err, mempoolTx.Txid, bchainVout.N)
}
}
if w.chainType == bchain.ChainBitcoinType {
// for coinbase transactions valIn is 0
feesSat.Sub(&valInSat, &valOutSat)
if feesSat.Sign() == -1 {
feesSat.SetUint64(0)
}
pValInSat = &valInSat
} else if w.chainType == bchain.ChainEthereumType {
if len(mempoolTx.Vout) > 0 {
valOutSat = mempoolTx.Vout[0].ValueSat
}
tokens = w.getTokensFromErc20(mempoolTx.Erc20)
ethTxData := eth.GetEthereumTxDataFromSpecificData(mempoolTx.CoinSpecificData)
ethSpecific = &EthereumSpecific{
GasLimit: ethTxData.GasLimit,
GasPrice: (*Amount)(ethTxData.GasPrice),
GasUsed: ethTxData.GasUsed,
Nonce: ethTxData.Nonce,
Status: ethTxData.Status,
Data: ethTxData.Data,
}
}
r := &Tx{
Blocktime: mempoolTx.Blocktime,
FeesSat: (*Amount)(&feesSat),
Locktime: mempoolTx.LockTime,
Txid: mempoolTx.Txid,
ValueInSat: (*Amount)(pValInSat),
ValueOutSat: (*Amount)(&valOutSat),
Version: mempoolTx.Version,
Hex: mempoolTx.Hex,
Rbf: rbf,
Vin: vins,
Vout: vouts,
TokenTransfers: tokens,
EthereumSpecific: ethSpecific,
}
return r, nil
}
func (w *Worker) getTokensFromErc20(erc20 []bchain.Erc20Transfer) []TokenTransfer {
tokens := make([]TokenTransfer, len(erc20))
for i := range erc20 {
e := &erc20[i]
cd, err := w.chainParser.GetAddrDescFromAddress(e.Contract)
if err != nil {
glog.Errorf("GetAddrDescFromAddress error %v, contract %v", err, e.Contract)
continue
}
erc20c, err := w.chain.EthereumTypeGetErc20ContractInfo(cd)
if err != nil {
glog.Errorf("GetErc20ContractInfo error %v, contract %v", err, e.Contract)
}
if erc20c == nil {
erc20c = &bchain.Erc20Contract{Name: e.Contract}
}
tokens[i] = TokenTransfer{
Type: ERC20TokenType,
Token: e.Contract,
From: e.From,
To: e.To,
Decimals: erc20c.Decimals,
Value: (*Amount)(&e.Tokens),
Name: erc20c.Name,
Symbol: erc20c.Symbol,
}
}
return tokens
}
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool, filter *AddressFilter, maxResults int) ([]string, error) {
var err error
txids := make([]string, 0, 4)
@ -400,6 +503,19 @@ func (t *Tx) getAddrVoutValue(addrDesc bchain.AddressDescriptor) *big.Int {
}
return &val
}
func (t *Tx) getAddrEthereumTypeMempoolInputValue(addrDesc bchain.AddressDescriptor) *big.Int {
var val big.Int
if len(t.Vin) > 0 && len(t.Vout) > 0 && bytes.Equal(t.Vin[0].AddrDesc, addrDesc) {
val.Add(&val, (*big.Int)(t.Vout[0].ValueSat))
// add maximum possible fee (the used value is not yet known)
if t.EthereumSpecific != nil && t.EthereumSpecific.GasLimit != nil && t.EthereumSpecific.GasPrice != nil {
var fees big.Int
fees.Mul((*big.Int)(t.EthereumSpecific.GasPrice), t.EthereumSpecific.GasLimit)
val.Add(&val, &fees)
}
}
return &val
}
func (t *Tx) getAddrVinValue(addrDesc bchain.AddressDescriptor) *big.Int {
var val big.Int
@ -496,6 +612,44 @@ func computePaging(count, page, itemsOnPage int) (Paging, int, int, int) {
}, from, to, page
}
func (w *Worker) getEthereumToken(index int, addrDesc, contract bchain.AddressDescriptor, details AccountDetails, txs int) (*Token, error) {
var b *big.Int
validContract := true
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(contract)
if err != nil {
return nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", contract)
}
if ci == nil {
ci = &bchain.Erc20Contract{}
addresses, _, _ := w.chainParser.GetAddressesFromAddrDesc(contract)
if len(addresses) > 0 {
ci.Contract = addresses[0]
ci.Name = addresses[0]
}
validContract = false
}
// do not read contract balances etc in case of Basic option
if details >= AccountDetailsTokenBalances && validContract {
b, err = w.chain.EthereumTypeGetErc20ContractBalance(addrDesc, contract)
if err != nil {
// return nil, nil, nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractBalance %v %v", addrDesc, c.Contract)
glog.Warningf("EthereumTypeGetErc20ContractBalance addr %v, contract %v, %v", addrDesc, contract, err)
}
} else {
b = nil
}
return &Token{
Type: ERC20TokenType,
BalanceSat: (*Amount)(b),
Contract: ci.Contract,
Name: ci.Name,
Symbol: ci.Symbol,
Transfers: txs,
Decimals: ci.Decimals,
ContractIndex: strconv.Itoa(index),
}, nil
}
func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescriptor, details AccountDetails, filter *AddressFilter) (*db.AddrBalance, []Token, *bchain.Erc20Contract, uint64, int, int, error) {
var (
ba *db.AddrBalance
@ -514,6 +668,13 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
if err != nil {
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetBalance %v", addrDesc)
}
var filterDesc bchain.AddressDescriptor
if filter.Contract != "" {
filterDesc, err = w.chainParser.GetAddrDescFromAddress(filter.Contract)
if err != nil {
return nil, nil, nil, 0, 0, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true)
}
}
if ca != nil {
ba = &db.AddrBalance{
Txs: uint32(ca.TotalTxs),
@ -525,13 +686,6 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
if err != nil {
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetNonce %v", addrDesc)
}
var filterDesc bchain.AddressDescriptor
if filter.Contract != "" {
filterDesc, err = w.chainParser.GetAddrDescFromAddress(filter.Contract)
if err != nil {
return nil, nil, nil, 0, 0, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true)
}
}
if details > AccountDetailsBasic {
tokens = make([]Token, len(ca.Contracts))
var j int
@ -543,43 +697,26 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
// filter only transactions of this contract
filter.Vout = i + 1
}
validContract := true
ci, err := w.chain.EthereumTypeGetErc20ContractInfo(c.Contract)
t, err := w.getEthereumToken(i+1, addrDesc, c.Contract, details, int(c.Txs))
if err != nil {
return nil, nil, nil, 0, 0, 0, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", c.Contract)
}
if ci == nil {
ci = &bchain.Erc20Contract{}
addresses, _, _ := w.chainParser.GetAddressesFromAddrDesc(c.Contract)
if len(addresses) > 0 {
ci.Contract = addresses[0]
ci.Name = addresses[0]
}
validContract = false
}
// do not read contract balances etc in case of Basic option
if details >= AccountDetailsTokenBalances && validContract {
b, err = w.chain.EthereumTypeGetErc20ContractBalance(addrDesc, c.Contract)
if err != nil {
// return nil, nil, nil, errors.Annotatef(err, "EthereumTypeGetErc20ContractBalance %v %v", addrDesc, c.Contract)
glog.Warningf("EthereumTypeGetErc20ContractBalance addr %v, contract %v, %v", addrDesc, c.Contract, err)
}
} else {
b = nil
}
tokens[j] = Token{
Type: ERC20TokenType,
BalanceSat: (*Amount)(b),
Contract: ci.Contract,
Name: ci.Name,
Symbol: ci.Symbol,
Transfers: int(c.Txs),
Decimals: ci.Decimals,
ContractIndex: strconv.Itoa(i + 1),
return nil, nil, nil, 0, 0, 0, err
}
tokens[j] = *t
j++
}
tokens = tokens[:j]
// special handling if filter has contract
// if the address has no transactions with given contract, check the balance, the address may have some balance even without transactions
if len(filterDesc) > 0 && j == 0 && details >= AccountDetailsTokens {
t, err := w.getEthereumToken(0, addrDesc, filterDesc, details, 0)
if err != nil {
return nil, nil, nil, 0, 0, 0, err
}
tokens = []Token{*t}
// switch off query for transactions, there are no transactions
filter.Vout = AddressFilterVoutQueryNotNecessary
} else {
tokens = tokens[:j]
}
}
ci, err = w.chain.EthereumTypeGetErc20ContractInfo(addrDesc)
if err != nil {
@ -593,6 +730,8 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
totalResults = int(ca.NonContractTxs)
} else if filter.Vout > 0 && filter.Vout-1 < len(ca.Contracts) {
totalResults = int(ca.Contracts[filter.Vout-1].Txs)
} else if filter.Vout == AddressFilterVoutQueryNotNecessary {
totalResults = 0
}
}
nonContractTxs = int(ca.NonContractTxs)
@ -603,6 +742,16 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
BalanceSat: *b,
}
}
// special handling if filtering for a contract, check the ballance of it
if len(filterDesc) > 0 && details >= AccountDetailsTokens {
t, err := w.getEthereumToken(0, addrDesc, filterDesc, details, 0)
if err != nil {
return nil, nil, nil, 0, 0, 0, err
}
tokens = []Token{*t}
// switch off query for transactions, there are no transactions
filter.Vout = AddressFilterVoutQueryNotNecessary
}
}
return ba, tokens, ci, n, nonContractTxs, totalResults, nil
}
@ -619,7 +768,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail
if ta == nil {
glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses")
// as fallback, get tx from backend
tx, err = w.GetTransaction(txid, false, true)
tx, err = w.GetTransaction(txid, false, false)
if err != nil {
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
}
@ -638,7 +787,7 @@ func (w *Worker) txFromTxid(txid string, bestheight uint32, option AccountDetail
tx = w.txFromTxAddress(txid, ta, blockInfo, bestheight)
}
} else {
tx, err = w.GetTransaction(txid, false, true)
tx, err = w.GetTransaction(txid, false, false)
if err != nil {
return nil, errors.Annotatef(err, "GetTransaction %v", txid)
}
@ -727,7 +876,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc)
}
for _, txid := range txm {
tx, err := w.GetTransaction(txid, false, false)
tx, err := w.GetTransaction(txid, false, true)
// mempool transaction may fail
if err != nil || tx == nil {
glog.Warning("GetTransaction in mempool: ", err)
@ -736,7 +885,12 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
if tx.Confirmations == 0 {
unconfirmedTxs++
uBalSat.Add(&uBalSat, tx.getAddrVoutValue(addrDesc))
uBalSat.Sub(&uBalSat, tx.getAddrVinValue(addrDesc))
// ethereum has a different logic - value not in input and add maximum possible fees
if w.chainType == bchain.ChainEthereumType {
uBalSat.Sub(&uBalSat, tx.getAddrEthereumTypeMempoolInputValue(addrDesc))
} else {
uBalSat.Sub(&uBalSat, tx.getAddrVinValue(addrDesc))
}
if page == 0 {
if option == AccountDetailsTxidHistory {
txids = append(txids, tx.Txid)
@ -749,7 +903,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
}
}
// get tx history if requested by option or check mempool if there are some transactions for a new address
if option >= AccountDetailsTxidHistory {
if option >= AccountDetailsTxidHistory && filter.Vout != AddressFilterVoutQueryNotNecessary {
txc, err := w.getAddressTxids(addrDesc, false, filter, (page+1)*txsOnPage)
if err != nil {
return nil, errors.Annotatef(err, "getAddressTxids %v false", addrDesc)
@ -820,7 +974,7 @@ func (w *Worker) balanceHistoryHeightsFromTo(fromTimestamp, toTimestamp int64) (
return fromUnix, fromHeight, toUnix, toHeight
}
func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32) (*BalanceHistory, error) {
func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32, selfAddrDesc map[string]struct{}) (*BalanceHistory, error) {
var time uint32
var err error
var ta *db.TxAddresses
@ -853,17 +1007,30 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
return nil, nil
}
bh := BalanceHistory{
Time: time,
Txs: 1,
SentSat: &Amount{},
ReceivedSat: &Amount{},
Txid: txid,
Time: time,
Txs: 1,
ReceivedSat: &Amount{},
SentSat: &Amount{},
SentToSelfSat: &Amount{},
Txid: txid,
}
countSentToSelf := false
if w.chainType == bchain.ChainBitcoinType {
// detect if this input is the first of selfAddrDesc
// to not to count sentToSelf multiple times if counting multiple xpub addresses
ownInputIndex := -1
for i := range ta.Inputs {
tai := &ta.Inputs[i]
if _, found := selfAddrDesc[string(tai.AddrDesc)]; found {
if ownInputIndex < 0 {
ownInputIndex = i
}
}
if bytes.Equal(addrDesc, tai.AddrDesc) {
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat)
if ownInputIndex == i {
countSentToSelf = true
}
}
}
for i := range ta.Outputs {
@ -871,12 +1038,17 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
if bytes.Equal(addrDesc, tao.AddrDesc) {
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat)
}
if countSentToSelf {
if _, found := selfAddrDesc[string(tao.AddrDesc)]; found {
(*big.Int)(bh.SentToSelfSat).Add((*big.Int)(bh.SentToSelfSat), &tao.ValueSat)
}
}
}
} else if w.chainType == bchain.ChainEthereumType {
var value big.Int
ethTxData := eth.GetEthereumTxData(bchainTx)
// add received amount only for OK transactions
if ethTxData.Status == 1 {
// add received amount only for OK or unknown status (old) transactions
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
if len(bchainTx.Vout) > 0 {
bchainVout := &bchainTx.Vout[0]
value = bchainVout.ValueSat
@ -888,6 +1060,9 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
if bytes.Equal(addrDesc, txAddrDesc) {
(*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &value)
}
if _, found := selfAddrDesc[string(txAddrDesc)]; found {
countSentToSelf = true
}
}
}
}
@ -899,9 +1074,14 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s
return nil, err
}
if bytes.Equal(addrDesc, txAddrDesc) {
// add sent amount only for OK transactions, however fees always
if ethTxData.Status == 1 {
// add received amount only for OK or unknown status (old) transactions, fees always
if ethTxData.Status == eth.TxStatusOK || ethTxData.Status == eth.TxStatusUnknown {
(*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &value)
if countSentToSelf {
if _, found := selfAddrDesc[string(txAddrDesc)]; found {
(*big.Int)(bh.SentToSelfSat).Add((*big.Int)(bh.SentToSelfSat), &value)
}
}
}
var feesSat big.Int
// mempool txs do not have fees yet
@ -962,8 +1142,9 @@ func (w *Worker) GetBalanceHistory(address string, fromTimestamp, toTimestamp in
if err != nil {
return nil, err
}
selfAddrDesc := map[string]struct{}{string(addrDesc): {}}
for txi := len(txs) - 1; txi >= 0; txi-- {
bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix)
bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix, selfAddrDesc)
if err != nil {
return nil, err
}
@ -1593,7 +1774,7 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
DbColumns: columnStats,
About: Text.BlockbookAbout,
}
backendInfo := &BackendInfo{
backendInfo := &common.BackendInfo{
BackendError: backendError,
BestBlockHash: ci.Bestblockhash,
Blocks: ci.Blocks,
@ -1606,7 +1787,9 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
Timeoffset: ci.Timeoffset,
Version: ci.Version,
Warnings: ci.Warnings,
Consensus: ci.Consensus,
}
w.is.SetBackendInfo(backendInfo)
glog.Info("GetSystemInfo finished in ", time.Since(start))
return &SystemInfo{blockbookInfo, backendInfo}, nil
}

View File

@ -1,8 +1,6 @@
package api
import (
"blockbook/bchain"
"blockbook/db"
"fmt"
"math/big"
"sort"
@ -11,6 +9,8 @@ import (
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/db"
)
const defaultAddressesGap = 20
@ -416,7 +416,7 @@ func (w *Worker) GetXpubAddress(xpub string, page int, txsOnPage int, option Acc
// the same tx can have multiple addresses from the same xpub, get it from backend it only once
tx, foundTx := txmMap[txid.txid]
if !foundTx {
tx, err = w.GetTransaction(txid.txid, false, false)
tx, err = w.GetTransaction(txid.txid, false, true)
// mempool transaction may fail
if err != nil || tx == nil {
glog.Warning("GetTransaction in mempool: ", err)
@ -606,12 +606,18 @@ func (w *Worker) GetXpubBalanceHistory(xpub string, fromTimestamp, toTimestamp i
if err != nil {
return nil, err
}
selfAddrDesc := make(map[string]struct{})
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
for i := range da {
selfAddrDesc[string(da[i].addrDesc)] = struct{}{}
}
}
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
for i := range da {
ad := &da[i]
txids := ad.txids
for txi := len(txids) - 1; txi >= 0; txi-- {
bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix)
bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix, selfAddrDesc)
if err != nil {
return nil, err
}

View File

@ -3,6 +3,7 @@ package bchain
import (
"sort"
"sync"
"time"
)
type addrIndex struct {
@ -27,6 +28,7 @@ type BaseMempool struct {
txEntries map[string]txEntry
addrDescToTx map[string][]Outpoint
OnNewTxAddr OnNewTxAddrFunc
OnNewTx OnNewTxFunc
}
// GetTransactions returns slice of mempool transactions for given address
@ -113,3 +115,22 @@ func (m *BaseMempool) GetTransactionTime(txid string) uint32 {
}
return e.time
}
func (m *BaseMempool) txToMempoolTx(tx *Tx) *MempoolTx {
mtx := MempoolTx{
Hex: tx.Hex,
Blocktime: time.Now().Unix(),
LockTime: tx.LockTime,
Txid: tx.Txid,
Version: tx.Version,
Vout: tx.Vout,
CoinSpecificData: tx.CoinSpecificData,
}
mtx.Vin = make([]MempoolVin, len(tx.Vin))
for i, vin := range tx.Vin {
mtx.Vin[i] = MempoolVin{
Vin: vin,
}
}
return &mtx
}

View File

@ -9,6 +9,7 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/common"
)
// BaseParser implements data parsing/handling functionality base for all other parsers
@ -39,9 +40,9 @@ func (p *BaseParser) GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescri
const zeros = "0000000000000000000000000000000000000000"
// AmountToBigInt converts amount in json.Number (string) to big.Int
// AmountToBigInt converts amount in common.JSONNumber (string) to big.Int
// it uses string operations to avoid problems with rounding
func (p *BaseParser) AmountToBigInt(n json.Number) (big.Int, error) {
func (p *BaseParser) AmountToBigInt(n common.JSONNumber) (big.Int, error) {
var r big.Int
s := string(n)
i := strings.IndexByte(s, '.')

View File

@ -1,9 +1,12 @@
// +build unittest
package bchain
import (
"encoding/json"
"math/big"
"testing"
"spacecruft.org/spacecruft/blockbook/common"
)
func NewBaseParser(adp int) *BaseParser {
@ -44,7 +47,7 @@ func TestBaseParser_AmountToDecimalString(t *testing.T) {
func TestBaseParser_AmountToBigInt(t *testing.T) {
for _, tt := range amounts {
t.Run(tt.s, func(t *testing.T) {
got, err := NewBaseParser(tt.adp).AmountToBigInt(json.Number(tt.s))
got, err := NewBaseParser(tt.adp).AmountToBigInt(common.JSONNumber(tt.s))
if err != nil {
t.Errorf("BaseParser.AmountToBigInt() error = %v", err)
return

View File

@ -1,8 +1,6 @@
package bch
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"fmt"
"github.com/martinboehm/bchutil"
@ -10,6 +8,8 @@ import (
"github.com/martinboehm/btcutil/chaincfg"
"github.com/martinboehm/btcutil/txscript"
"github.com/schancel/cashaddr-converter/address"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// AddressFormat type is used to specify different formats of address

View File

@ -3,8 +3,6 @@
package bch
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,8 +1,6 @@
package bch
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"encoding/json"
"math/big"
@ -10,6 +8,8 @@ import (
"github.com/golang/glog"
"github.com/juju/errors"
"github.com/martinboehm/bchutil"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// BCashRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package bellcoin
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package bellcoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package bellcoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// BellcoinRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,10 @@
package bitcore
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (

View File

@ -3,14 +3,15 @@
package bitcore
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"github.com/martinboehm/btcutil/chaincfg"
"math/big"
"os"
"reflect"
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,12 @@
package bitcore
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// BitcoreRPC is an interface to JSON-RPC bitcoind service.

View File

@ -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
}
}

View File

@ -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)
}
})
}
}

View File

@ -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
}

View File

@ -1,45 +1,6 @@
package coins
import (
"blockbook/bchain"
"blockbook/bchain/coins/bch"
"blockbook/bchain/coins/bellcoin"
"blockbook/bchain/coins/bitcore"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/btg"
"blockbook/bchain/coins/cpuchain"
"blockbook/bchain/coins/dash"
"blockbook/bchain/coins/dcr"
"blockbook/bchain/coins/deeponion"
"blockbook/bchain/coins/digibyte"
"blockbook/bchain/coins/divi"
"blockbook/bchain/coins/dogecoin"
"blockbook/bchain/coins/eth"
"blockbook/bchain/coins/flo"
"blockbook/bchain/coins/fujicoin"
"blockbook/bchain/coins/gamecredits"
"blockbook/bchain/coins/grs"
"blockbook/bchain/coins/koto"
"blockbook/bchain/coins/liquid"
"blockbook/bchain/coins/litecoin"
"blockbook/bchain/coins/monacoin"
"blockbook/bchain/coins/monetaryunit"
"blockbook/bchain/coins/myriad"
"blockbook/bchain/coins/namecoin"
"blockbook/bchain/coins/nuls"
"blockbook/bchain/coins/omotenashicoin"
"blockbook/bchain/coins/pivx"
"blockbook/bchain/coins/polis"
"blockbook/bchain/coins/qtum"
"blockbook/bchain/coins/ravencoin"
"blockbook/bchain/coins/ritocoin"
"blockbook/bchain/coins/unobtanium"
"blockbook/bchain/coins/vertcoin"
"blockbook/bchain/coins/viacoin"
"blockbook/bchain/coins/vipstarcoin"
"blockbook/bchain/coins/xzc"
"blockbook/bchain/coins/zec"
"blockbook/common"
"context"
"encoding/json"
"fmt"
@ -49,6 +10,48 @@ import (
"time"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/bch"
"spacecruft.org/spacecruft/blockbook/bchain/coins/bellcoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/bitcore"
"spacecruft.org/spacecruft/blockbook/bchain/coins/bitzeny"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/cpuchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/dash"
"spacecruft.org/spacecruft/blockbook/bchain/coins/dcr"
"spacecruft.org/spacecruft/blockbook/bchain/coins/deeponion"
"spacecruft.org/spacecruft/blockbook/bchain/coins/digibyte"
"spacecruft.org/spacecruft/blockbook/bchain/coins/divi"
"spacecruft.org/spacecruft/blockbook/bchain/coins/dogecoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/eth"
"spacecruft.org/spacecruft/blockbook/bchain/coins/firo"
"spacecruft.org/spacecruft/blockbook/bchain/coins/flo"
"spacecruft.org/spacecruft/blockbook/bchain/coins/fujicoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/gamecredits"
"spacecruft.org/spacecruft/blockbook/bchain/coins/grs"
"spacecruft.org/spacecruft/blockbook/bchain/coins/koto"
"spacecruft.org/spacecruft/blockbook/bchain/coins/liquid"
"spacecruft.org/spacecruft/blockbook/bchain/coins/litecoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/monacoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/monetaryunit"
"spacecruft.org/spacecruft/blockbook/bchain/coins/myriad"
"spacecruft.org/spacecruft/blockbook/bchain/coins/namecoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/nuls"
"spacecruft.org/spacecruft/blockbook/bchain/coins/omotenashicoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/pivx"
"spacecruft.org/spacecruft/blockbook/bchain/coins/polis"
"spacecruft.org/spacecruft/blockbook/bchain/coins/qtum"
"spacecruft.org/spacecruft/blockbook/bchain/coins/ravencoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/ritocoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/snowgem"
"spacecruft.org/spacecruft/blockbook/bchain/coins/trezarcoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/unobtanium"
"spacecruft.org/spacecruft/blockbook/bchain/coins/vertcoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/viacoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/vipstarcoin"
"spacecruft.org/spacecruft/blockbook/bchain/coins/zec"
"spacecruft.org/spacecruft/blockbook/common"
)
type blockChainFactory func(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error)
@ -59,14 +62,17 @@ var BlockChainFactories = make(map[string]blockChainFactory)
func init() {
BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC
BlockChainFactories["Testnet"] = btc.NewBitcoinRPC
BlockChainFactories["Signet"] = btc.NewBitcoinRPC
BlockChainFactories["Zcash"] = zec.NewZCashRPC
BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
BlockChainFactories["Ethereum Testnet Goerli"] = eth.NewEthereumRPC
BlockChainFactories["Bcash"] = bch.NewBCashRPC
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
BlockChainFactories["Bgold"] = btg.NewBGoldRPC
BlockChainFactories["Bgold Testnet"] = btg.NewBGoldRPC
BlockChainFactories["Dash"] = dash.NewDashRPC
BlockChainFactories["Dash Testnet"] = dash.NewDashRPC
BlockChainFactories["Decred"] = dcr.NewDecredRPC
@ -84,6 +90,7 @@ func init() {
BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC
BlockChainFactories["MonetaryUnit"] = monetaryunit.NewMonetaryUnitRPC
BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC
BlockChainFactories["DigiByte Testnet"] = digibyte.NewDigiByteRPC
BlockChainFactories["Myriad"] = myriad.NewMyriadRPC
BlockChainFactories["Liquid"] = liquid.NewLiquidRPC
BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC
@ -91,7 +98,7 @@ func init() {
BlockChainFactories["PIVX"] = pivx.NewPivXRPC
BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC
BlockChainFactories["Polis"] = polis.NewPolisRPC
BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC
BlockChainFactories["Firo"] = firo.NewFiroRPC
BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC
BlockChainFactories["Flo"] = flo.NewFloRPC
BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC
@ -107,9 +114,12 @@ func init() {
BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC
BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC
BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC
BlockChainFactories["SnowGem"] = snowgem.NewSnowGemRPC
BlockChainFactories["Bitcore"] = bitcore.NewBitcoreRPC
BlockChainFactories["Omotenashicoin"] = omotenashicoin.NewOmotenashiCoinRPC
BlockChainFactories["Omotenashicoin Testnet"] = omotenashicoin.NewOmotenashiCoinRPC
BlockChainFactories["BitZeny"] = bitzeny.NewBitZenyRPC
BlockChainFactories["Trezarcoin"] = trezarcoin.NewTrezarcoinRPC
}
// GetCoinNameFromConfig gets coin name and coin shortcut from config file
@ -181,8 +191,8 @@ func (c *blockChainWithMetrics) CreateMempool(chain bchain.BlockChain) (bchain.M
return c.b.CreateMempool(chain)
}
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr)
func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr, onNewTx)
}
func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error {

View File

@ -1,7 +1,6 @@
package btc
import (
"blockbook/bchain"
"bytes"
"encoding/binary"
"encoding/hex"
@ -16,8 +15,25 @@ import (
"github.com/martinboehm/btcutil/chaincfg"
"github.com/martinboehm/btcutil/hdkeychain"
"github.com/martinboehm/btcutil/txscript"
"spacecruft.org/spacecruft/blockbook/bchain"
)
// temp params for signet(wait btcd commit)
// magic numbers
const (
SignetMagic wire.BitcoinNet = 0x6a70c7f0
)
// chain parameters
var (
SigNetParams chaincfg.Params
)
func init() {
SigNetParams = chaincfg.TestNet3Params
SigNetParams.Net = SignetMagic
}
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
@ -63,6 +79,8 @@ func GetChainParams(chain string) *chaincfg.Params {
return &chaincfg.TestNet3Params
case "regtest":
return &chaincfg.RegressionNetParams
case "signet":
return &SigNetParams
}
return &chaincfg.MainNetParams
}

View File

@ -3,7 +3,6 @@
package btc
import (
"blockbook/bchain"
"encoding/hex"
"math/big"
"os"
@ -11,6 +10,7 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
)
func TestMain(m *testing.M) {
@ -259,10 +259,11 @@ func TestGetAddressesFromAddrDesc(t *testing.T) {
}
var (
testTx1, testTx2 bchain.Tx
testTx1, testTx2, testTx3 bchain.Tx
testTxPacked1 = "0001e2408ba8d7af5401000000017f9a22c9cbf54bd902400df746f138f37bcf5b4d93eb755820e974ba43ed5f42040000006a4730440220037f4ed5427cde81d55b9b6a2fd08c8a25090c2c2fff3a75c1a57625ca8a7118022076c702fe55969fa08137f71afd4851c48e31082dd3c40c919c92cdbc826758d30121029f6da5623c9f9b68a9baf9c1bc7511df88fa34c6c2f71f7c62f2f03ff48dca80feffffff019c9700000000000017a9146144d57c8aff48492c9dfb914e120b20bad72d6f8773d00700"
testTxPacked2 = "0007c91a899ab7da6a010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000"
testTxPacked3 = "00003d818bfda9aa3e02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000"
)
func init() {
@ -335,6 +336,54 @@ func init() {
},
},
}
testTx3 = bchain.Tx{
Hex: "02000000000102deb1999a857ab0a13d6b12fbd95ea75b409edde5f2ff747507ce42d9986a8b9d0000000000fdffffff9fd2d3361e203b2375eba6438efbef5b3075531e7e583c7cc76b7294fe7f22980000000000fdffffff02a0860100000000001600148091746745464e7555c31e9a5afceac14a02978ae7fc1c0000000000160014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e0247304402207d67d320a8e813f986b35e9791935fcb736754812b7038686f5de6cfdcda99cd02201c3bb2c178e0056016437ecfe365a7eef84aa9d293ebdc566177af82e22fcdd3012103abb30c1bbe878b07b58dc169b1d061d48c60be8107f632a59778b38bf7ceea5a02473044022044f54a478cfe086e870cb026c9dcd4e14e63778bef569a4d55a6332725cd9a9802202f0e94c04e6f328fc64ad9efe552888c299750d1b8d033324825a3ff29920e030121036fcd433428aa7dc65c4f5408fa31f208c54fe4b4c6c1ae9c39a825ed4f1ac039813d0000",
Blocktime: 1607805599,
Txid: "24551a58a1d1fb89d7052e2bbac7cb69a7825ee1e39439befbec8c32148cf735",
LockTime: 15745,
Version: 2,
Vin: []bchain.Vin{
{
ScriptSig: bchain.ScriptSig{
Hex: "",
},
Txid: "9d8b6a98d942ce077574fff2e5dd9e405ba75ed9fb126b3da1b07a859a99b1de",
Vout: 0,
Sequence: 4294967293,
},
{
ScriptSig: bchain.ScriptSig{
Hex: "",
},
Txid: "98227ffe94726bc77c3c587e1e5375305beffb8e43a6eb75233b201e36d3d29f",
Vout: 0,
Sequence: 4294967293,
},
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(100000),
N: 0,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "00148091746745464e7555c31e9a5afceac14a02978a",
Addresses: []string{
"tb1qszghge69ge8824wrr6d94l82c99q99u2ccgv5w",
},
},
},
{
ValueSat: *big.NewInt(1899751),
N: 1,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "0014565ea9ff4589d3e05ba149ae6e257752bfdc2a1e",
Addresses: []string{
"tb1q2e02nl6938f7qkapfxhxufth22lac2s792vsxp",
},
},
},
},
}
}
func TestPackTx(t *testing.T) {
@ -372,6 +421,17 @@ func TestPackTx(t *testing.T) {
want: testTxPacked2,
wantErr: false,
},
{
name: "signet-1",
args: args{
tx: testTx3,
height: 15745,
blockTime: 1607805599,
parser: NewBitcoinParser(GetChainParams("signet"), &Configuration{}),
},
want: testTxPacked3,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -420,6 +480,16 @@ func TestUnpackTx(t *testing.T) {
want1: 510234,
wantErr: false,
},
{
name: "signet-1",
args: args{
packedTx: testTxPacked3,
parser: NewBitcoinParser(GetChainParams("signet"), &Configuration{}),
},
want: &testTx3,
want1: 15745,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -1,7 +1,6 @@
package btc
import (
"blockbook/bchain"
"bytes"
"context"
"encoding/hex"
@ -17,6 +16,8 @@ import (
"github.com/golang/glog"
"github.com/juju/errors"
"github.com/martinboehm/btcd/wire"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/common"
)
// BitcoinRPC is an interface to JSON-RPC bitcoind service.
@ -154,12 +155,13 @@ func (b *BitcoinRPC) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, err
}
// InitializeMempool creates ZeroMQ subscription and sets AddrDescForOutpointFunc to the Mempool
func (b *BitcoinRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
func (b *BitcoinRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
if b.Mempool == nil {
return errors.New("Mempool not created")
}
b.Mempool.AddrDescForOutpoint = addrDescForOutpoint
b.Mempool.OnNewTxAddr = onNewTxAddr
b.Mempool.OnNewTx = onNewTx
if b.mq == nil {
mq, err := bchain.NewMQ(b.ChainConfig.MessageQueueBinding, b.pushHandler)
if err != nil {
@ -237,13 +239,13 @@ type CmdGetBlockChainInfo struct {
type ResGetBlockChainInfo struct {
Error *bchain.RPCError `json:"error"`
Result struct {
Chain string `json:"chain"`
Blocks int `json:"blocks"`
Headers int `json:"headers"`
Bestblockhash string `json:"bestblockhash"`
Difficulty json.Number `json:"difficulty"`
SizeOnDisk int64 `json:"size_on_disk"`
Warnings string `json:"warnings"`
Chain string `json:"chain"`
Blocks int `json:"blocks"`
Headers int `json:"headers"`
Bestblockhash string `json:"bestblockhash"`
Difficulty common.JSONNumber `json:"difficulty"`
SizeOnDisk int64 `json:"size_on_disk"`
Warnings string `json:"warnings"`
} `json:"result"`
}
@ -256,11 +258,11 @@ type CmdGetNetworkInfo struct {
type ResGetNetworkInfo struct {
Error *bchain.RPCError `json:"error"`
Result struct {
Version json.Number `json:"version"`
Subversion json.Number `json:"subversion"`
ProtocolVersion json.Number `json:"protocolversion"`
Timeoffset float64 `json:"timeoffset"`
Warnings string `json:"warnings"`
Version common.JSONNumber `json:"version"`
Subversion common.JSONNumber `json:"subversion"`
ProtocolVersion common.JSONNumber `json:"protocolversion"`
Timeoffset float64 `json:"timeoffset"`
Warnings string `json:"warnings"`
} `json:"result"`
}
@ -358,8 +360,8 @@ type CmdEstimateSmartFee struct {
type ResEstimateSmartFee struct {
Error *bchain.RPCError `json:"error"`
Result struct {
Feerate json.Number `json:"feerate"`
Blocks int `json:"blocks"`
Feerate common.JSONNumber `json:"feerate"`
Blocks int `json:"blocks"`
} `json:"result"`
}
@ -373,8 +375,8 @@ type CmdEstimateFee struct {
}
type ResEstimateFee struct {
Error *bchain.RPCError `json:"error"`
Result json.Number `json:"result"`
Error *bchain.RPCError `json:"error"`
Result common.JSONNumber `json:"result"`
}
// sendrawtransaction

View File

@ -1,7 +1,6 @@
package btc
import (
"blockbook/bchain"
"bytes"
"encoding/json"
"fmt"
@ -12,8 +11,8 @@ import (
"time"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
)
// https://whatthefee.io returns

View File

@ -1,9 +1,6 @@
package btg
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
"bytes"
"encoding/binary"
"io"
@ -11,6 +8,9 @@ import (
"github.com/martinboehm/btcd/chaincfg/chainhash"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
const (

View File

@ -3,7 +3,6 @@
package btg
import (
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"fmt"
@ -13,6 +12,7 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package btg
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// BGoldRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package cpuchain
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -1,11 +1,11 @@
package cpuchain
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// CPUchainRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,11 +1,10 @@
package dash
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (

View File

@ -1,10 +1,8 @@
// build unittest
// +build unittest
package dash
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"fmt"
@ -13,6 +11,9 @@ import (
"path/filepath"
"reflect"
"testing"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
type testBlock struct {

View File

@ -1,12 +1,12 @@
package dash
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const firstBlockWithSpecialTransactions = 1028160

View File

@ -9,18 +9,19 @@ import (
"math/big"
"strconv"
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
cfg "github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/hdkeychain"
"github.com/decred/dcrd/txscript"
cfg "github.com/decred/dcrd/chaincfg/v3"
"github.com/decred/dcrd/dcrec"
"github.com/decred/dcrd/dcrutil/v3"
"github.com/decred/dcrd/hdkeychain/v3"
"github.com/decred/dcrd/txscript/v3"
"github.com/juju/errors"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/base58"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
const (
@ -65,9 +66,9 @@ func NewDecredParser(params *chaincfg.Params, c *btc.Configuration) *DecredParse
switch d.BitcoinParser.Params.Name {
case "testnet3":
d.netConfig = &cfg.TestNet3Params
d.netConfig = cfg.TestNet3Params()
default:
d.netConfig = &cfg.MainNetParams
d.netConfig = cfg.MainNetParams()
}
return d
}
@ -203,7 +204,10 @@ func (p *DecredParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressD
return nil, err
}
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(txscript.DefaultScriptVersion, script, p.netConfig)
const scriptVersion = 0
const treasuryEnabled = true
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(scriptVersion, script,
p.netConfig, treasuryEnabled)
if err != nil {
return nil, err
}
@ -241,7 +245,9 @@ func (p *DecredParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
}
func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
var addr, err = extKey.Address(p.netConfig)
pk := extKey.SerializedPubKey()
hash := dcrutil.Hash160(pk)
addr, err := dcrutil.NewAddressPubKeyHash(hash, p.netConfig, dcrec.STEcdsaSecp256k1)
if err != nil {
return nil, err
}
@ -252,7 +258,7 @@ func (p *DecredParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchai
// listed indexes
func (p *DecredParser) DeriveAddressDescriptors(xpub string, change uint32,
indexes []uint32) ([]bchain.AddressDescriptor, error) {
extKey, err := hdkeychain.NewKeyFromString(xpub)
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
if err != nil {
return nil, err
}
@ -283,7 +289,7 @@ func (p *DecredParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32
if toIndex <= fromIndex {
return nil, errors.New("toIndex<=fromIndex")
}
extKey, err := hdkeychain.NewKeyFromString(xpub)
extKey, err := hdkeychain.NewKeyFromString(xpub, p.netConfig)
if err != nil {
return nil, err
}

View File

@ -3,13 +3,14 @@
package dcr
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
"reflect"
"testing"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
var (

View File

@ -1,7 +1,6 @@
package dcr
import (
"blockbook/bchain"
"bytes"
"encoding/json"
"fmt"
@ -16,11 +15,12 @@ import (
"sync"
"time"
"blockbook/bchain/coins/btc"
"github.com/decred/dcrd/dcrjson"
"github.com/decred/dcrd/dcrjson/v3"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/common"
)
// voteBitYes defines the vote bit set when a given block validates the previous
@ -168,61 +168,61 @@ type GetBlockHashResult struct {
type GetBlockResult struct {
Error Error `json:"error"`
Result struct {
Hash string `json:"hash"`
Confirmations int64 `json:"confirmations"`
Size int32 `json:"size"`
Height uint32 `json:"height"`
Version json.Number `json:"version"`
MerkleRoot string `json:"merkleroot"`
StakeRoot string `json:"stakeroot"`
RawTx []RawTx `json:"rawtx"`
Tx []string `json:"tx,omitempty"`
STx []string `json:"stx,omitempty"`
Time int64 `json:"time"`
Nonce json.Number `json:"nonce"`
VoteBits uint16 `json:"votebits"`
FinalState string `json:"finalstate"`
Voters uint16 `json:"voters"`
FreshStake uint8 `json:"freshstake"`
Revocations uint8 `json:"revocations"`
PoolSize uint32 `json:"poolsize"`
Bits string `json:"bits"`
SBits float64 `json:"sbits"`
ExtraData string `json:"extradata"`
StakeVersion uint32 `json:"stakeversion"`
Difficulty float64 `json:"difficulty"`
ChainWork string `json:"chainwork"`
PreviousHash string `json:"previousblockhash"`
NextHash string `json:"nextblockhash,omitempty"`
Hash string `json:"hash"`
Confirmations int64 `json:"confirmations"`
Size int32 `json:"size"`
Height uint32 `json:"height"`
Version common.JSONNumber `json:"version"`
MerkleRoot string `json:"merkleroot"`
StakeRoot string `json:"stakeroot"`
RawTx []RawTx `json:"rawtx"`
Tx []string `json:"tx,omitempty"`
STx []string `json:"stx,omitempty"`
Time int64 `json:"time"`
Nonce common.JSONNumber `json:"nonce"`
VoteBits uint16 `json:"votebits"`
FinalState string `json:"finalstate"`
Voters uint16 `json:"voters"`
FreshStake uint8 `json:"freshstake"`
Revocations uint8 `json:"revocations"`
PoolSize uint32 `json:"poolsize"`
Bits string `json:"bits"`
SBits float64 `json:"sbits"`
ExtraData string `json:"extradata"`
StakeVersion uint32 `json:"stakeversion"`
Difficulty float64 `json:"difficulty"`
ChainWork string `json:"chainwork"`
PreviousHash string `json:"previousblockhash"`
NextHash string `json:"nextblockhash,omitempty"`
} `json:"result"`
}
type GetBlockHeaderResult struct {
Error Error `json:"error"`
Result struct {
Hash string `json:"hash"`
Confirmations int64 `json:"confirmations"`
Version json.Number `json:"version"`
MerkleRoot string `json:"merkleroot"`
StakeRoot string `json:"stakeroot"`
VoteBits uint16 `json:"votebits"`
FinalState string `json:"finalstate"`
Voters uint16 `json:"voters"`
FreshStake uint8 `json:"freshstake"`
Revocations uint8 `json:"revocations"`
PoolSize uint32 `json:"poolsize"`
Bits string `json:"bits"`
SBits float64 `json:"sbits"`
Height uint32 `json:"height"`
Size uint32 `json:"size"`
Time int64 `json:"time"`
Nonce uint32 `json:"nonce"`
ExtraData string `json:"extradata"`
StakeVersion uint32 `json:"stakeversion"`
Difficulty float64 `json:"difficulty"`
ChainWork string `json:"chainwork"`
PreviousHash string `json:"previousblockhash,omitempty"`
NextHash string `json:"nextblockhash,omitempty"`
Hash string `json:"hash"`
Confirmations int64 `json:"confirmations"`
Version common.JSONNumber `json:"version"`
MerkleRoot string `json:"merkleroot"`
StakeRoot string `json:"stakeroot"`
VoteBits uint16 `json:"votebits"`
FinalState string `json:"finalstate"`
Voters uint16 `json:"voters"`
FreshStake uint8 `json:"freshstake"`
Revocations uint8 `json:"revocations"`
PoolSize uint32 `json:"poolsize"`
Bits string `json:"bits"`
SBits float64 `json:"sbits"`
Height uint32 `json:"height"`
Size uint32 `json:"size"`
Time int64 `json:"time"`
Nonce uint32 `json:"nonce"`
ExtraData string `json:"extradata"`
StakeVersion uint32 `json:"stakeversion"`
Difficulty float64 `json:"difficulty"`
ChainWork string `json:"chainwork"`
PreviousHash string `json:"previousblockhash,omitempty"`
NextHash string `json:"nextblockhash,omitempty"`
} `json:"result"`
}
@ -297,8 +297,8 @@ type EstimateSmartFeeResult struct {
}
type EstimateFeeResult struct {
Error Error `json:"error"`
Result json.Number `json:"result"`
Error Error `json:"error"`
Result common.JSONNumber `json:"result"`
}
type SendRawTransactionResult struct {
@ -637,7 +637,7 @@ func (d *DecredRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
Version: block.Result.Version,
Nonce: block.Result.Nonce,
Bits: block.Result.Bits,
Difficulty: json.Number(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
Difficulty: common.JSONNumber(strconv.FormatFloat(block.Result.Difficulty, 'e', -1, 64)),
Txids: block.Result.Tx,
}

View File

@ -1,11 +1,10 @@
package deeponion
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package deeponion
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,12 +1,12 @@
package deeponion
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// DeepOnionRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,20 +1,21 @@
package digibyte
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (
// MainnetMagic is mainnet network constant
MainnetMagic wire.BitcoinNet = 0xdab6c3fa
TestnetMagic wire.BitcoinNet = 0xddbdc8fd
)
var (
// MainNetParams are parser parameters for mainnet
MainNetParams chaincfg.Params
TestNetParams chaincfg.Params
)
func init() {
@ -23,6 +24,12 @@ func init() {
MainNetParams.PubKeyHashAddrID = []byte{30}
MainNetParams.ScriptHashAddrID = []byte{63}
MainNetParams.Bech32HRPSegwit = "dgb"
TestNetParams = chaincfg.TestNet3Params
TestNetParams.Net = TestnetMagic
TestNetParams.PubKeyHashAddrID = []byte{126}
TestNetParams.ScriptHashAddrID = []byte{140}
TestNetParams.Bech32HRPSegwit = "dgbt"
}
// DigiByteParser handle
@ -30,18 +37,27 @@ type DigiByteParser struct {
*btc.BitcoinParser
}
// NewDigiByteParser returns new VertcoinParser instance
// NewDigiByteParser returns new DigiByteParser instance
func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser {
return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
}
// GetChainParams contains network parameters for the main DigiByte network
// and the DigiByte Testnet network
func GetChainParams(chain string) *chaincfg.Params {
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
if err == nil {
err = chaincfg.Register(&TestNetParams)
}
if err != nil {
panic(err)
}
}
return &MainNetParams
switch chain {
case "test":
return &TestNetParams
default:
return &MainNetParams
}
}

View File

@ -3,8 +3,6 @@
package digibyte
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package digibyte
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// DigiByteRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,20 +1,18 @@
package divi
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
"bytes"
"io"
"encoding/hex"
"encoding/json"
"io"
"math/big"
"github.com/juju/errors"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
const (

View File

@ -3,8 +3,6 @@
package divi
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"fmt"
@ -16,6 +14,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package divi
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// DivicoinRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,13 +1,13 @@
package dogecoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
"bytes"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package dogecoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"fmt"
@ -16,6 +14,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package dogecoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// DogecoinRPC is an interface to JSON-RPC dogecoind service.

View File

@ -1,7 +1,6 @@
package eth
import (
"blockbook/bchain"
"bytes"
"context"
"encoding/hex"
@ -13,6 +12,7 @@ import (
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
)
var erc20abi = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x06fdde03"},
@ -145,24 +145,26 @@ func parseErc20StringProperty(contractDesc bchain.AddressDescriptor, data string
n := parseErc20NumericProperty(contractDesc, data[64:128])
if n != nil {
l := n.Uint64()
if 2*int(l) <= len(data)-128 {
if l > 0 && 2*int(l) <= len(data)-128 {
b, err := hex.DecodeString(data[128 : 128+2*l])
if err == nil {
return string(b)
}
}
}
} else if len(data) == 64 {
// allow string properties as 32 bytes of UTF-8 data
b, err := hex.DecodeString(data)
if err == nil {
i := bytes.Index(b, []byte{0})
if i > 0 {
b = b[:i]
}
if utf8.Valid(b) {
return string(b)
}
}
// allow string properties as UTF-8 data
b, err := hex.DecodeString(data)
if err == nil {
i := bytes.Index(b, []byte{0})
if i > 32 {
i = 32
}
if i > 0 {
b = b[:i]
}
if utf8.Valid(b) {
return string(b)
}
}
if glog.V(1) {
@ -181,18 +183,26 @@ func (b *EthereumRPC) EthereumTypeGetErc20ContractInfo(contractDesc bchain.Addre
address := EIP55Address(contractDesc)
data, err := b.ethCall(erc20NameSignature, address)
if err != nil {
return nil, err
// ignore the error from the eth_call - since geth v1.9.15 they changed the behavior
// and returning error "execution reverted" for some non contract addresses
// https://github.com/ethereum/go-ethereum/issues/21249#issuecomment-648647672
glog.Warning(errors.Annotatef(err, "erc20NameSignature %v", address))
return nil, nil
// return nil, errors.Annotatef(err, "erc20NameSignature %v", address)
}
name := parseErc20StringProperty(contractDesc, data)
if name != "" {
data, err = b.ethCall(erc20SymbolSignature, address)
if err != nil {
return nil, err
glog.Warning(errors.Annotatef(err, "erc20SymbolSignature %v", address))
return nil, nil
// return nil, errors.Annotatef(err, "erc20SymbolSignature %v", address)
}
symbol := parseErc20StringProperty(contractDesc, data)
data, err = b.ethCall(erc20DecimalsSignature, address)
if err != nil {
return nil, err
glog.Warning(errors.Annotatef(err, "erc20DecimalsSignature %v", address))
// return nil, errors.Annotatef(err, "erc20DecimalsSignature %v", address)
}
contract = &bchain.Erc20Contract{
Contract: address,

View File

@ -3,12 +3,13 @@
package eth
import (
"blockbook/bchain"
"blockbook/tests/dbtestdata"
fmt "fmt"
"fmt"
"math/big"
"strings"
"testing"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
)
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
@ -138,6 +139,16 @@ func TestErc20_parseErc20StringProperty(t *testing.T) {
args: "0x44616920537461626c65636f696e2076312e3020444444444444444444444444",
want: "Dai Stablecoin v1.0 DDDDDDDDDDDD",
},
{
name: "long",
args: "0x556e6973776170205631000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
want: "Uniswap V1",
},
{
name: "garbage",
args: "0x2234880850896048596206002535425366538144616734015984380565810000",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -1,7 +1,6 @@
package eth
import (
"blockbook/bchain"
"encoding/hex"
"math/big"
"strconv"
@ -9,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/golang/protobuf/proto"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"golang.org/x/crypto/sha3"
)
@ -311,8 +311,14 @@ func (p *EthereumParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) (
if pt.Receipt.GasUsed, err = hexDecodeBig(r.Receipt.GasUsed); err != nil {
return nil, errors.Annotatef(err, "GasUsed %v", r.Receipt.GasUsed)
}
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status)
if r.Receipt.Status != "" {
if pt.Receipt.Status, err = hexDecodeBig(r.Receipt.Status); err != nil {
return nil, errors.Annotatef(err, "Status %v", r.Receipt.Status)
}
} else {
// unknown status, use 'U' as status bytes
// there is a potential for conflict with value 0x55 but this is not used by any chain at this moment
pt.Receipt.Status = []byte{'U'}
}
ptLogs := make([]*ProtoCompleteTransaction_ReceiptType_LogType, len(r.Receipt.Logs))
for i, l := range r.Receipt.Logs {
@ -379,9 +385,14 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
Topics: topics,
}
}
status := ""
// handle a special value []byte{'U'} as unknown state
if len(pt.Receipt.Status) != 1 || pt.Receipt.Status[0] != 'U' {
status = hexEncodeBig(pt.Receipt.Status)
}
rr = &rpcReceipt{
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
Status: hexEncodeBig(pt.Receipt.Status),
Status: status,
Logs: logs,
}
}
@ -461,40 +472,51 @@ func (p *EthereumParser) EthereumTypeGetErc20FromTx(tx *bchain.Tx) ([]bchain.Erc
return r, nil
}
// TxStatus is status of transaction
type TxStatus int
// statuses of transaction
const (
txStatusUnknown = iota - 2
txStatusPending
txStatusFailure
txStatusOK
TxStatusUnknown = TxStatus(iota - 2)
TxStatusPending
TxStatusFailure
TxStatusOK
)
// EthereumTxData contains ethereum specific transaction data
type EthereumTxData struct {
Status int `json:"status"` // 1 OK, 0 Fail, -1 pending, -2 unknown
Status TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending, -2 unknown
Nonce uint64 `json:"nonce"`
GasLimit *big.Int `json:"gaslimit"`
GasUsed *big.Int `json:"gasused"`
GasPrice *big.Int `json:"gasprice"`
Data string `json:"data"`
}
// GetEthereumTxData returns EthereumTxData from bchain.Tx
func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData {
etd := EthereumTxData{Status: txStatusPending}
csd, ok := tx.CoinSpecificData.(completeTransaction)
return GetEthereumTxDataFromSpecificData(tx.CoinSpecificData)
}
// GetEthereumTxDataFromSpecificData returns EthereumTxData from coinSpecificData
func GetEthereumTxDataFromSpecificData(coinSpecificData interface{}) *EthereumTxData {
etd := EthereumTxData{Status: TxStatusPending}
csd, ok := coinSpecificData.(completeTransaction)
if ok {
if csd.Tx != nil {
etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce)
etd.GasLimit, _ = hexutil.DecodeBig(csd.Tx.GasLimit)
etd.GasPrice, _ = hexutil.DecodeBig(csd.Tx.GasPrice)
etd.Data = csd.Tx.Payload
}
if csd.Receipt != nil {
switch csd.Receipt.Status {
case "0x1":
etd.Status = txStatusOK
etd.Status = TxStatusOK
case "": // old transactions did not set status
etd.Status = txStatusUnknown
etd.Status = TxStatusUnknown
default:
etd.Status = txStatusFailure
etd.Status = TxStatusFailure
}
etd.GasUsed, _ = hexutil.DecodeBig(csd.Receipt.GasUsed)
}

View File

@ -3,13 +3,14 @@
package eth
import (
"blockbook/bchain"
"blockbook/tests/dbtestdata"
"encoding/hex"
"fmt"
"math/big"
"reflect"
"testing"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/tests/dbtestdata"
)
func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
@ -67,7 +68,7 @@ func TestEthParser_GetAddrDescFromAddress(t *testing.T) {
}
}
var testTx1, testTx2 bchain.Tx
var testTx1, testTx2, testTx1Failed, testTx1NoStatus bchain.Tx
func init() {
@ -155,6 +156,83 @@ func init() {
},
},
}
testTx1Failed = bchain.Tx{
Blocktime: 1534858022,
Time: 1534858022,
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
Vin: []bchain.Vin{
{
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
},
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(1999622000000000000),
ScriptPubKey: bchain.ScriptPubKey{
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
AccountNonce: "0xb26c",
GasPrice: "0x430e23400",
GasLimit: "0x5208",
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
Value: "0x1bc0159d530e6000",
Payload: "0x",
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
BlockNumber: "0x41eee8",
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
TransactionIndex: "0xa",
},
Receipt: &rpcReceipt{
GasUsed: "0x5208",
Status: "0x0",
Logs: []*rpcLog{},
},
},
}
testTx1NoStatus = bchain.Tx{
Blocktime: 1534858022,
Time: 1534858022,
Txid: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
Vin: []bchain.Vin{
{
Addresses: []string{"0x3E3a3D69dc66bA10737F531ed088954a9EC89d97"},
},
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(1999622000000000000),
ScriptPubKey: bchain.ScriptPubKey{
Addresses: []string{"0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f"},
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
AccountNonce: "0xb26c",
GasPrice: "0x430e23400",
GasLimit: "0x5208",
To: "0x555Ee11FBDDc0E49A9bAB358A8941AD95fFDB48f",
Value: "0x1bc0159d530e6000",
Payload: "0x",
Hash: "0xcd647151552b5132b2aef7c9be00dc6f73afc5901dde157aab131335baaa853b",
BlockNumber: "0x41eee8",
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
TransactionIndex: "0xa",
},
Receipt: &rpcReceipt{
GasUsed: "0x5208",
Status: "",
Logs: []*rpcLog{},
},
},
}
}
func TestEthereumParser_PackTx(t *testing.T) {
@ -188,6 +266,24 @@ func TestEthereumParser_PackTx(t *testing.T) {
},
want: dbtestdata.EthTx2Packed,
},
{
name: "3",
args: args{
tx: &testTx1Failed,
height: 4321000,
blockTime: 1534858022,
},
want: dbtestdata.EthTx1FailedPacked,
},
{
name: "4",
args: args{
tx: &testTx1NoStatus,
height: 4321000,
blockTime: 1534858022,
},
want: dbtestdata.EthTx1NoStatusPacked,
},
}
p := NewEthereumParser(1)
for _, tt := range tests {
@ -229,6 +325,18 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
want: &testTx2,
want1: 4321000,
},
{
name: "3",
args: args{hex: dbtestdata.EthTx1FailedPacked},
want: &testTx1Failed,
want1: 4321000,
},
{
name: "4",
args: args{hex: dbtestdata.EthTx1NoStatusPacked},
want: &testTx1NoStatus,
want1: 4321000,
},
}
p := NewEthereumParser(1)
for _, tt := range tests {
@ -265,3 +373,30 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
})
}
}
func TestEthereumParser_GetEthereumTxData(t *testing.T) {
tests := []struct {
name string
tx *bchain.Tx
want string
}{
{
name: "Test empty data",
tx: &testTx1,
want: "0x",
},
{
name: "Test non empty data",
tx: &testTx2,
want: "0xa9059cbb000000000000000000000000555ee11fbddc0e49a9bab358a8941ad95ffdb48f00000000000000000000000000000000000000000000021e19e0c9bab2400000",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetEthereumTxData(tt.tx)
if got.Data != tt.want {
t.Errorf("EthereumParser.GetEthereumTxData() = %v, want %v", got.Data, tt.want)
}
})
}
}

View File

@ -1,7 +1,6 @@
package eth
import (
"blockbook/bchain"
"context"
"encoding/json"
"fmt"
@ -12,11 +11,14 @@ import (
ethereum "github.com/ethereum/go-ethereum"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/common"
)
// EthereumNet type specifies the type of ethereum network
@ -27,6 +29,8 @@ const (
MainNet EthereumNet = 1
// TestNet is Ropsten test network
TestNet EthereumNet = 3
// TestNetGoerli is Goerli test network
TestNetGoerli EthereumNet = 5
)
// Configuration represents json config file
@ -158,6 +162,9 @@ func (b *EthereumRPC) Initialize() error {
b.Testnet = true
b.Network = "testnet"
break
case TestNetGoerli:
b.Testnet = true
b.Network = "goerli"
default:
return errors.Errorf("Unknown network id %v", id)
}
@ -176,7 +183,7 @@ func (b *EthereumRPC) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, er
}
// InitializeMempool creates subscriptions to newHeads and newPendingTransactions
func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error {
func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc, onNewTx bchain.OnNewTxFunc) error {
if b.Mempool == nil {
return errors.New("Mempool not created")
}
@ -191,6 +198,7 @@ func (b *EthereumRPC) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOu
}
b.Mempool.OnNewTxAddr = onNewTxAddr
b.Mempool.OnNewTx = onNewTx
if err = b.subscribeEvents(); err != nil {
return err
@ -332,19 +340,15 @@ func (b *EthereumRPC) GetChainInfo() (*bchain.ChainInfo, error) {
if err != nil {
return nil, err
}
var ver, protocol string
var ver string
if err := b.rpc.CallContext(ctx, &ver, "web3_clientVersion"); err != nil {
return nil, err
}
if err := b.rpc.CallContext(ctx, &protocol, "eth_protocolVersion"); err != nil {
return nil, err
}
rv := &bchain.ChainInfo{
Blocks: int(h.Number.Int64()),
Bestblockhash: h.Hash().Hex(),
Difficulty: h.Difficulty.String(),
Version: ver,
ProtocolVersion: protocol,
Blocks: int(h.Number.Int64()),
Bestblockhash: h.Hash().Hex(),
Difficulty: h.Difficulty.String(),
Version: ver,
}
idi := int(id.Uint64())
if idi == 1 {
@ -569,8 +573,8 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
}
return &bchain.BlockInfo{
BlockHeader: *bch,
Difficulty: json.Number(head.Difficulty),
Nonce: json.Number(head.Nonce),
Difficulty: common.JSONNumber(head.Difficulty),
Nonce: common.JSONNumber(head.Nonce),
Txids: txs.Transactions,
}, nil
}
@ -720,6 +724,18 @@ func (b *EthereumRPC) EthereumTypeEstimateGas(params map[string]interface{}) (ui
if ok && len(s) > 0 {
msg.Data = ethcommon.FromHex(s)
}
s, ok = getStringFromMap("value", params)
if ok && len(s) > 0 {
msg.Value, _ = hexutil.DecodeBig(s)
}
s, ok = getStringFromMap("gas", params)
if ok && len(s) > 0 {
msg.Gas, _ = hexutil.DecodeUint64(s)
}
s, ok = getStringFromMap("gasPrice", params)
if ok && len(s) > 0 {
msg.GasPrice, _ = hexutil.DecodeBig(s)
}
return b.client.EstimateGas(ctx, msg)
}

View File

@ -1,11 +1,11 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: tx.proto
// source: bchain/coins/eth/ethtx.proto
/*
Package eth is a generated protocol buffer package.
It is generated from these files:
tx.proto
bchain/coins/eth/ethtx.proto
It has these top-level messages:
ProtoCompleteTransaction
@ -228,33 +228,34 @@ func init() {
proto.RegisterType((*ProtoCompleteTransaction_ReceiptType_LogType)(nil), "eth.ProtoCompleteTransaction.ReceiptType.LogType")
}
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
func init() { proto.RegisterFile("bchain/coins/eth/ethtx.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 393 bytes of a gzipped FileDescriptorProto
// 409 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x8a, 0xd4, 0x30,
0x14, 0xc6, 0xe9, 0x9f, 0xf9, 0xb3, 0xa7, 0x55, 0x24, 0x88, 0x84, 0xe2, 0x45, 0x59, 0xbc, 0xa8,
0x5e, 0x14, 0x5c, 0x7d, 0x81, 0x75, 0xc4, 0x55, 0x18, 0xd6, 0x21, 0x46, 0xef, 0xb3, 0x69, 0xd8,
0x29, 0xb6, 0x4d, 0x69, 0x52, 0xe8, 0xbe, 0x91, 0x2f, 0xe4, 0xbb, 0x78, 0x29, 0x39, 0x4d, 0xd7,
0x11, 0x51, 0xbc, 0x3b, 0xbf, 0x6f, 0xce, 0x37, 0xf9, 0xbe, 0xa4, 0xb0, 0xb5, 0x53, 0xd9, 0x0f,
0xda, 0x6a, 0x12, 0x29, 0x7b, 0x3c, 0xff, 0xb6, 0x02, 0x7a, 0x70, 0xb8, 0xd3, 0x6d, 0xdf, 0x28,
0xab, 0xf8, 0x20, 0x3a, 0x23, 0xa4, 0xad, 0x75, 0x47, 0x72, 0x48, 0xde, 0x34, 0x5a, 0x7e, 0xbd,
0x1e, 0xdb, 0x1b, 0x35, 0xd0, 0x20, 0x0f, 0x8a, 0x07, 0xec, 0x54, 0x22, 0x4f, 0xe1, 0x0c, 0x91,
0xd7, 0xad, 0xa2, 0x61, 0x1e, 0x14, 0x31, 0xfb, 0x25, 0x90, 0xd7, 0x10, 0xf2, 0x89, 0x46, 0x79,
0x50, 0x24, 0x17, 0xcf, 0x4a, 0x65, 0x8f, 0xe5, 0xdf, 0x8e, 0x2a, 0xf9, 0xc4, 0xef, 0x7a, 0xc5,
0x42, 0x3e, 0x91, 0x1d, 0x6c, 0x98, 0x92, 0xaa, 0xee, 0x2d, 0x8d, 0xd1, 0xfa, 0xfc, 0xdf, 0x56,
0xbf, 0x8c, 0xfe, 0xc5, 0x99, 0xfd, 0x08, 0x60, 0x3d, 0xff, 0x27, 0x39, 0x87, 0xf4, 0x52, 0x4a,
0x3d, 0x76, 0xf6, 0x5a, 0x77, 0x52, 0x61, 0x8d, 0x98, 0xfd, 0xa6, 0x91, 0x0c, 0xb6, 0x57, 0xc2,
0x1c, 0x86, 0x5a, 0xce, 0x35, 0x52, 0x76, 0xcf, 0xfe, 0xb7, 0x7d, 0xdd, 0xd6, 0x16, 0xbb, 0xc4,
0xec, 0x9e, 0xc9, 0x63, 0x58, 0x7d, 0x11, 0xcd, 0xa8, 0x30, 0x69, 0xca, 0x66, 0x20, 0x14, 0x36,
0x07, 0x71, 0xd7, 0x68, 0x51, 0xd1, 0x15, 0xea, 0x0b, 0x12, 0x02, 0xf1, 0x7b, 0x61, 0x8e, 0x74,
0x8d, 0x32, 0xce, 0xe4, 0x21, 0x84, 0x5c, 0xd3, 0x0d, 0x2a, 0x21, 0xd7, 0x6e, 0xe7, 0xdd, 0xa0,
0x5b, 0xba, 0x9d, 0x77, 0xdc, 0x4c, 0x5e, 0xc0, 0xa3, 0x93, 0xca, 0x1f, 0xba, 0x4a, 0x4d, 0xf4,
0x0c, 0x9f, 0xe3, 0x0f, 0x3d, 0xfb, 0x1e, 0x40, 0x72, 0x72, 0x27, 0x2e, 0xcd, 0x95, 0x30, 0x9f,
0x8d, 0xaa, 0xb0, 0x7a, 0xca, 0x16, 0x24, 0x4f, 0x60, 0xfd, 0xc9, 0x0a, 0x3b, 0x1a, 0xdf, 0xd9,
0x13, 0xd9, 0x41, 0xb4, 0xd7, 0xb7, 0x34, 0xca, 0xa3, 0x22, 0xb9, 0x78, 0xf9, 0xdf, 0xb7, 0x5f,
0xee, 0xf5, 0x2d, 0xbe, 0x82, 0x73, 0x67, 0x1f, 0x61, 0xe3, 0xd9, 0x25, 0xb8, 0xac, 0xaa, 0x41,
0x19, 0xb3, 0x24, 0xf0, 0xe8, 0xba, 0xbe, 0x15, 0x56, 0xf8, 0xf3, 0x71, 0x76, 0xa9, 0xb8, 0xee,
0x6b, 0x69, 0x30, 0x40, 0xca, 0x3c, 0xdd, 0xac, 0xf1, 0xb3, 0x7d, 0xf5, 0x33, 0x00, 0x00, 0xff,
0xff, 0xde, 0xd5, 0x28, 0xa3, 0xc2, 0x02, 0x00, 0x00,
0x18, 0xc5, 0xe9, 0x9f, 0x99, 0xd9, 0xfd, 0xa6, 0x8a, 0x04, 0x91, 0x30, 0xec, 0x45, 0x59, 0xbc,
0x18, 0xbd, 0xe8, 0xe2, 0xea, 0x0b, 0xac, 0x23, 0xae, 0xc2, 0xb0, 0x0e, 0x31, 0x7a, 0x9f, 0x49,
0xc3, 0x36, 0x38, 0x6d, 0x4a, 0x93, 0x42, 0xf7, 0x8d, 0x7c, 0x21, 0xdf, 0xc5, 0x4b, 0xc9, 0xd7,
0x74, 0x1d, 0x11, 0x65, 0x2f, 0x0a, 0xf9, 0x9d, 0x7e, 0xa7, 0x39, 0x27, 0x29, 0x9c, 0xed, 0x65,
0x25, 0x74, 0x73, 0x21, 0x8d, 0x6e, 0xec, 0x85, 0x72, 0x95, 0x7f, 0xdc, 0x50, 0xb4, 0x9d, 0x71,
0x86, 0x24, 0xca, 0x55, 0xe7, 0xdf, 0x67, 0x40, 0x77, 0x1e, 0x37, 0xa6, 0x6e, 0x0f, 0xca, 0x29,
0xde, 0x89, 0xc6, 0x0a, 0xe9, 0xb4, 0x69, 0x48, 0x0e, 0xcb, 0xb7, 0x07, 0x23, 0xbf, 0xdd, 0xf4,
0xf5, 0x5e, 0x75, 0x34, 0xca, 0xa3, 0xf5, 0x23, 0x76, 0x2c, 0x91, 0x33, 0x38, 0x45, 0xe4, 0xba,
0x56, 0x34, 0xce, 0xa3, 0x75, 0xca, 0x7e, 0x0b, 0xe4, 0x0d, 0xc4, 0x7c, 0xa0, 0x49, 0x1e, 0xad,
0x97, 0x97, 0xcf, 0x0b, 0xe5, 0xaa, 0xe2, 0x5f, 0x5b, 0x15, 0x7c, 0xe0, 0x77, 0xad, 0x62, 0x31,
0x1f, 0xc8, 0x06, 0x16, 0x4c, 0x49, 0xa5, 0x5b, 0x47, 0x53, 0xb4, 0xbe, 0xf8, 0xbf, 0x35, 0x0c,
0xa3, 0x7f, 0x72, 0xae, 0x7e, 0x46, 0x30, 0x1f, 0xbf, 0x49, 0xce, 0x21, 0xbb, 0x92, 0xd2, 0xf4,
0x8d, 0xbb, 0x31, 0x8d, 0x54, 0x58, 0x23, 0x65, 0x7f, 0x68, 0x64, 0x05, 0x27, 0xd7, 0xc2, 0xee,
0x3a, 0x2d, 0xc7, 0x1a, 0x19, 0xbb, 0xe7, 0xf0, 0x6e, 0xab, 0x6b, 0xed, 0xb0, 0x4b, 0xca, 0xee,
0x99, 0x3c, 0x85, 0xd9, 0x57, 0x71, 0xe8, 0x15, 0x26, 0xcd, 0xd8, 0x08, 0x84, 0xc2, 0x62, 0x27,
0xee, 0x0e, 0x46, 0x94, 0x74, 0x86, 0xfa, 0x84, 0x84, 0x40, 0xfa, 0x41, 0xd8, 0x8a, 0xce, 0x51,
0xc6, 0x35, 0x79, 0x0c, 0x31, 0x37, 0x74, 0x81, 0x4a, 0xcc, 0x8d, 0x9f, 0x79, 0xdf, 0x99, 0x9a,
0x9e, 0x8c, 0x33, 0x7e, 0x4d, 0x5e, 0xc2, 0x93, 0xa3, 0xca, 0x1f, 0x9b, 0x52, 0x0d, 0xf4, 0x14,
0xaf, 0xe3, 0x2f, 0x7d, 0xf5, 0x23, 0x82, 0xe5, 0xd1, 0x99, 0xf8, 0x34, 0xd7, 0xc2, 0x7e, 0xb1,
0xaa, 0xc4, 0xea, 0x19, 0x9b, 0x90, 0x3c, 0x83, 0xf9, 0x67, 0x27, 0x5c, 0x6f, 0x43, 0xe7, 0x40,
0x64, 0x03, 0xc9, 0xd6, 0xdc, 0xd2, 0x24, 0x4f, 0xd6, 0xcb, 0xcb, 0x57, 0x0f, 0x3e, 0xfd, 0x62,
0x6b, 0x6e, 0xf1, 0x16, 0xbc, 0x7b, 0xf5, 0x09, 0x16, 0x81, 0x7d, 0x82, 0xab, 0xb2, 0xec, 0x94,
0xb5, 0x53, 0x82, 0x80, 0xbe, 0xeb, 0x3b, 0xe1, 0x44, 0xd8, 0x1f, 0xd7, 0x3e, 0x15, 0x37, 0xad,
0x96, 0x16, 0x03, 0x64, 0x2c, 0xd0, 0x7e, 0x8e, 0xbf, 0xed, 0xeb, 0x5f, 0x01, 0x00, 0x00, 0xff,
0xff, 0xc2, 0x69, 0x8d, 0xdf, 0xd6, 0x02, 0x00, 0x00,
}

View File

@ -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
}

View File

@ -1,8 +1,6 @@
package xzc
package firo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/binary"
"encoding/json"
@ -11,13 +9,18 @@ import (
"github.com/martinboehm/btcd/chaincfg/chainhash"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (
OpZeroCoinMint = 0xc1
OpZeroCoinSpend = 0xc2
OpSigmaMint = 0xc3
OpSigmaSpend = 0xc4
OpZeroCoinMint = 0xc1
OpZeroCoinSpend = 0xc2
OpSigmaMint = 0xc3
OpSigmaSpend = 0xc4
OpLelantusMint = 0xc5
OpLelantusJMint = 0xc6
OpLelantusJoinSplit = 0xc7
MainnetMagic wire.BitcoinNet = 0xe3d9fef1
TestnetMagic wire.BitcoinNet = 0xcffcbeea
@ -28,6 +31,8 @@ const (
MTPL = 64
SpendTxID = "0000000000000000000000000000000000000000000000000000000000000000"
TransactionQuorumCommitmentType = 6
)
var (
@ -58,21 +63,21 @@ func init() {
RegtestParams.Net = RegtestMagic
}
// ZcoinParser handle
type ZcoinParser struct {
// FiroParser handle
type FiroParser struct {
*btc.BitcoinParser
}
// NewZcoinParser returns new ZcoinParser instance
func NewZcoinParser(params *chaincfg.Params, c *btc.Configuration) *ZcoinParser {
return &ZcoinParser{
// NewFiroParser returns new FiroParser instance
func NewFiroParser(params *chaincfg.Params, c *btc.Configuration) *FiroParser {
return &FiroParser{
BitcoinParser: btc.NewBitcoinParser(params, c),
}
}
// GetChainParams contains network parameters for the main Zcoin network,
// the regression test Zcoin network, the test Zcoin network and
// the simulation test Zcoin network, in this order
// GetChainParams contains network parameters for the main Firo network,
// the regression test Firo network, the test Firo network and
// the simulation test Firo network, in this order
func GetChainParams(chain string) *chaincfg.Params {
if !chaincfg.IsRegistered(&MainNetParams) {
err := chaincfg.Register(&MainNetParams)
@ -97,7 +102,7 @@ func GetChainParams(chain string) *chaincfg.Params {
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
func (p *FiroParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
if len(addrDesc) > 0 {
switch addrDesc[0] {
@ -109,6 +114,12 @@ func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor
return []string{"Sigmamint"}, false, nil
case OpSigmaSpend:
return []string{"Sigmaspend"}, false, nil
case OpLelantusMint:
return []string{"LelantusMint"}, false, nil
case OpLelantusJMint:
return []string{"LelantusJMint"}, false, nil
case OpLelantusJoinSplit:
return []string{"LelantusJoinSplit"}, false, nil
}
}
@ -116,17 +127,27 @@ func (p *ZcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor
}
// PackTx packs transaction to byte array using protobuf
func (p *ZcoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
func (p *FiroParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
return p.BaseParser.PackTx(tx, height, blockTime)
}
// UnpackTx unpacks transaction from protobuf byte array
func (p *ZcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
func (p *FiroParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
return p.BaseParser.UnpackTx(buf)
}
// TxFromFiroMsgTx converts bitcoin wire Tx to bchain.Tx
func (p *FiroParser) TxFromFiroMsgTx(t *FiroMsgTx, parseAddresses bool) bchain.Tx {
btx := p.TxFromMsgTx(&t.MsgTx, parseAddresses)
// NOTE: wire.MsgTx.TxHash() doesn't include extra
btx.Txid = t.TxHash().String()
return btx
}
// ParseBlock parses raw block to our Block struct
func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
func (p *FiroParser) ParseBlock(b []byte) (*bchain.Block, error) {
reader := bytes.NewReader(b)
// parse standard block header first
@ -181,16 +202,37 @@ func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
txs := make([]bchain.Tx, ntx)
for i := uint64(0); i < ntx; i++ {
tx := wire.MsgTx{}
tx := FiroMsgTx{}
err := tx.BtcDecode(reader, 0, wire.WitnessEncoding)
if err != nil {
// read version and seek back
var version uint32 = 0
if err = binary.Read(reader, binary.LittleEndian, &version); err != nil {
return nil, err
}
btx := p.TxFromMsgTx(&tx, false)
if _, err = reader.Seek(-4, io.SeekCurrent); err != nil {
return nil, err
}
p.parseZcoinTx(&btx)
txVersion := version & 0xffff
txType := (version >> 16) & 0xffff
enc := wire.WitnessEncoding
// transaction quorum commitment could not be parsed with witness flag
if txVersion == 3 && txType == TransactionQuorumCommitmentType {
enc = wire.BaseEncoding
}
if err = tx.FiroDecode(reader, 0, enc); err != nil {
return nil, err
}
btx := p.TxFromFiroMsgTx(&tx, false)
if err = p.parseFiroTx(&btx); err != nil {
return nil, err
}
txs[i] = btx
}
@ -205,7 +247,7 @@ func (p *ZcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
}
// ParseTxFromJson parses JSON message containing transaction and returns Tx struct
func (p *ZcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
func (p *FiroParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
var tx bchain.Tx
err := json.Unmarshal(msg, &tx)
if err != nil {
@ -222,12 +264,12 @@ func (p *ZcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
vout.JsonValue = ""
}
p.parseZcoinTx(&tx)
p.parseFiroTx(&tx)
return &tx, nil
}
func (p *ZcoinParser) parseZcoinTx(tx *bchain.Tx) error {
func (p *FiroParser) parseFiroTx(tx *bchain.Tx) error {
for i := range tx.Vin {
vin := &tx.Vin[i]

View File

@ -1,6 +1,6 @@
// +build unittest
package xzc
package firo
import (
"bytes"
@ -13,17 +13,18 @@ import (
"strings"
"testing"
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
var (
testTx1, testTx2, testTx3, testTx4 bchain.Tx
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4 string
rawBlock1, rawBlock2 string
jsonTx json.RawMessage
testTx1, testTx2, testTx3, testTx4, testTx5, testTx6 bchain.Tx
rawTestTx1, rawTestTx2, rawTestTx3, rawTestTx4, rawTestTx5, rawTestTx6 string
testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4, testTxPacked5, testTxPacked6 string
rawBlock1, rawBlock2, rawBlock3 string
jsonTx json.RawMessage
)
func readHexs(path string) []string {
@ -40,12 +41,15 @@ func init() {
rawBlocks := readHexs("./testdata/rawblock.hex")
rawBlock1 = rawBlocks[0]
rawBlock2 = rawBlocks[1]
rawBlock3 = rawBlocks[2]
hextxs := readHexs("./testdata/txs.hex")
rawTestTx1 := hextxs[0]
rawTestTx2 := hextxs[1]
rawTestTx3 := hextxs[2]
rawTestTx4 := hextxs[3]
rawTestTx1 = hextxs[0]
rawTestTx2 = hextxs[1]
rawTestTx3 = hextxs[2]
rawTestTx4 = hextxs[3]
rawTestTx5 = hextxs[4]
rawTestTx6 = hextxs[5]
rawSpendHex := readHexs("./testdata/rawspend.hex")[0]
@ -60,13 +64,15 @@ func init() {
testTxPacked2 = testTxPackeds[1]
testTxPacked3 = testTxPackeds[2]
testTxPacked4 = testTxPackeds[3]
testTxPacked5 = testTxPackeds[4]
testTxPacked6 = testTxPackeds[5]
testTx1 = bchain.Tx{
Hex: rawTestTx1,
Blocktime: 1533980594,
Time: 1533980594,
Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23",
LockTime: 0,
LockTime: 99688,
Vin: []bchain.Vin{
{
ScriptSig: bchain.ScriptSig{
@ -79,14 +85,14 @@ func init() {
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(18188266638),
ValueSat: *big.NewInt(100000000),
N: 0,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28",
},
},
{
ValueSat: *big.NewInt(18188266638),
ValueSat: *big.NewInt(871824000),
N: 1,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac",
@ -106,9 +112,7 @@ func init() {
LockTime: 0,
Vin: []bchain.Vin{
{
ScriptSig: bchain.ScriptSig{
Hex: rawSpendHex,
},
Coinbase: rawSpendHex,
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
Vout: 4294967295,
Sequence: 2,
@ -227,7 +231,7 @@ func init() {
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac",
Addresses: []string{
"a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3",
"aQ18FBVFtnueucZKeVg4srhmzbpAeb1KoN",
},
},
},
@ -251,6 +255,103 @@ func init() {
},
},
},
// TODO: test segwit
},
}
testTx5 = bchain.Tx{
Hex: rawTestTx5,
Blocktime: 1591752749,
Time: 1591752749,
Txid: "8d1f32f35c32d2c127a7400dc1ec52049fbf0b8bcdf284cfaa3da59b6169a22d",
LockTime: 0,
Vin: []bchain.Vin{},
Vout: []bchain.Vout{},
}
testTx6 = bchain.Tx{
Hex: rawTestTx6,
Blocktime: 1591762049,
Time: 1591762049,
Txid: "e5767d3606230a65f150837a6f28b4f0e4c2702a683045df3883d57702739c61",
LockTime: 0,
Vin: []bchain.Vin{
{
Coinbase: "02b4140101",
Sequence: 4294967295,
},
},
Vout: []bchain.Vout{
{
ValueSat: *big.NewInt(1400000000),
N: 0,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "2103fb09a216761d5e7f248294970c2370f7f84ce1ad564b8e7096b1e19116af1d52ac",
Addresses: []string{
"TAn9Ghkp31myXRgejCj11wWVHT14Lsj349",
},
},
},
{
ValueSat: *big.NewInt(50000000),
N: 1,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a914296134d2415bf1f2b518b3f673816d7e603b160088ac",
Addresses: []string{
"TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo",
},
},
},
{
ValueSat: *big.NewInt(50000000),
N: 2,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a914e1e1dc06a889c1b6d3eb00eef7a96f6a7cfb884888ac",
Addresses: []string{
"TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5",
},
},
},
{
ValueSat: *big.NewInt(50000000),
N: 3,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a914ab03ecfddee6330497be894d16c29ae341c123aa88ac",
Addresses: []string{
"TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT",
},
},
},
{
ValueSat: *big.NewInt(150000000),
N: 4,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a9144281a58a1d5b2d3285e00cb45a8492debbdad4c588ac",
Addresses: []string{
"TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve",
},
},
},
{
ValueSat: *big.NewInt(50000000),
N: 5,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a9141fd264c0bb53bd9fef18e2248ddf1383d6e811ae88ac",
Addresses: []string{
"TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS",
},
},
},
{
ValueSat: *big.NewInt(750000000),
N: 6,
ScriptPubKey: bchain.ScriptPubKey{
Hex: "76a91471a3892d164ffa3829078bf9ad5f114a3908ce5588ac",
Addresses: []string{
"TLL5GQULX4uBfz7yXL6VcZyvzdKVv1RGxm",
},
},
},
},
}
}
@ -264,32 +365,32 @@ func TestMain(m *testing.M) {
func TestGetAddrDesc(t *testing.T) {
type args struct {
tx bchain.Tx
parser *ZcoinParser
parser *FiroParser
}
tests := []struct {
name string
args args
}{
{
name: "xzc-1",
name: "firo-1",
args: args{
tx: testTx1,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
},
// FIXME: work around handle zerocoin spend as coinbase
// {
// name: "xzc-2",
// name: "firo-2",
// args: args{
// tx: testTx2,
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
// },
// },
{
name: "xzc-3",
name: "firo-3",
args: args{
tx: testTx3,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
},
}
@ -347,7 +448,7 @@ func TestGetAddrDescFromVoutForMint(t *testing.T) {
wantErr: false,
},
}
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -397,7 +498,7 @@ func TestGetAddressesFromAddrDescForMint(t *testing.T) {
wantErr: false,
},
}
parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{})
parser := NewFiroParser(GetChainParams("main"), &btc.Configuration{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -422,7 +523,7 @@ func TestPackTx(t *testing.T) {
tx bchain.Tx
height uint32
blockTime int64
parser *ZcoinParser
parser *FiroParser
}
tests := []struct {
name string
@ -431,50 +532,72 @@ func TestPackTx(t *testing.T) {
wantErr bool
}{
{
name: "xzc-1",
name: "firo-1",
args: args{
tx: testTx1,
height: 100002,
blockTime: 1533980594,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTxPacked1,
wantErr: false,
},
// FIXME: work around handle zerocoin spend as coinbase
// {
// name: "xzc-2",
// name: "firo-2",
// args: args{
// tx: testTx2,
// height: 11002,
// blockTime: 1481277009,
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
// },
// want: testTxPacked2,
// wantErr: true,
// },
{
name: "xzc-3",
name: "firo-3",
args: args{
tx: testTx3,
height: 126202,
blockTime: 1547091829,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTxPacked3,
wantErr: false,
},
{
name: "xzc-coinbase",
name: "firo-coinbase",
args: args{
tx: testTx4,
height: 100001,
blockTime: 1533977563,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTxPacked4,
wantErr: false,
},
{
name: "firo-quorum-commitment-tx",
args: args{
tx: testTx5,
height: 5268,
blockTime: 1591752749,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: testTxPacked5,
wantErr: false,
},
{
name: "firo-special-coinbase-tx",
args: args{
tx: testTx6,
height: 5300,
blockTime: 1591762049,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: testTxPacked6,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -496,7 +619,7 @@ func TestPackTx(t *testing.T) {
func TestUnpackTx(t *testing.T) {
type args struct {
packedTx string
parser *ZcoinParser
parser *FiroParser
}
tests := []struct {
name string
@ -506,10 +629,10 @@ func TestUnpackTx(t *testing.T) {
wantErr bool
}{
{
name: "xzc-1",
name: "firo-1",
args: args{
packedTx: testTxPacked1,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &testTx1,
want1: 100002,
@ -517,35 +640,55 @@ func TestUnpackTx(t *testing.T) {
},
// FIXME: work around handle zerocoin spend as coinbase
// {
// name: "xzc-2",
// name: "firo-2",
// args: args{
// packedTx: testTxPacked2,
// parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
// parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
// },
// want: &testTx2,
// want1: 11002,
// wantErr: true,
// },
{
name: "xzc-3",
name: "firo-3",
args: args{
packedTx: testTxPacked3,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &testTx3,
want1: 126202,
wantErr: false,
},
{
name: "xzc-coinbase",
name: "firo-coinbase",
args: args{
packedTx: testTxPacked4,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &testTx4,
want1: 100001,
wantErr: false,
},
{
name: "firo-special-tx",
args: args{
packedTx: testTxPacked5,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: &testTx5,
want1: 5268,
wantErr: false,
},
{
name: "firo-special-coinbase-tx",
args: args{
packedTx: testTxPacked6,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: &testTx6,
want1: 5300,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -571,7 +714,7 @@ func TestUnpackTx(t *testing.T) {
func TestParseBlock(t *testing.T) {
type args struct {
rawBlock string
parser *ZcoinParser
parser *FiroParser
}
tests := []struct {
name string
@ -584,7 +727,7 @@ func TestParseBlock(t *testing.T) {
name: "normal-block",
args: args{
rawBlock: rawBlock1,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &bchain.Block{
BlockHeader: bchain.BlockHeader{
@ -599,7 +742,7 @@ func TestParseBlock(t *testing.T) {
name: "spend-block",
args: args{
rawBlock: rawBlock2,
parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}),
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: &bchain.Block{
BlockHeader: bchain.BlockHeader{
@ -610,6 +753,21 @@ func TestParseBlock(t *testing.T) {
wantTxs: 4,
wantErr: false,
},
{
name: "special-tx-block",
args: args{
rawBlock: rawBlock3,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: &bchain.Block{
BlockHeader: bchain.BlockHeader{
Size: 200062,
Time: 1591752749,
},
},
wantTxs: 3,
wantErr: false,
},
}
for _, tt := range tests {
@ -633,3 +791,191 @@ func TestParseBlock(t *testing.T) {
})
}
}
func TestDecodeTransaction(t *testing.T) {
type args struct {
enc wire.MessageEncoding
rawTransaction string
parser *FiroParser
privacyType byte // 0 as non privacy
}
tests := []struct {
name string
args args
want bchain.Tx
wantErr bool
}{
{
name: "normal-transaction",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx1,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTx1,
},
{
name: "coinbase-firospend",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx2,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
privacyType: OpSigmaSpend,
},
want: testTx2,
},
{
name: "normal-transaction-2",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx3,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTx3,
},
{
name: "coinbase-transaction",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx4,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTx4,
},
{
name: "quorum-commitment-transaction",
args: args{
enc: wire.BaseEncoding,
rawTransaction: rawTestTx5,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
want: testTx5,
},
{
name: "quorum-commitment-transaction-witness",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx5,
parser: NewFiroParser(GetChainParams("main"), &btc.Configuration{}),
},
wantErr: true,
},
{
name: "special-coinbase",
args: args{
enc: wire.WitnessEncoding,
rawTransaction: rawTestTx6,
parser: NewFiroParser(GetChainParams("test"), &btc.Configuration{}),
},
want: testTx6,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b, _ := hex.DecodeString(tt.args.rawTransaction)
r := bytes.NewReader(b)
msg := FiroMsgTx{}
err := msg.FiroDecode(r, 0, tt.args.enc)
if tt.wantErr {
if err == nil {
t.Errorf("Want error")
}
return
}
if err != nil {
t.Fatal(err)
}
got := tt.args.parser.TxFromFiroMsgTx(&msg, true)
if pErr := tt.args.parser.parseFiroTx(&got); pErr != nil {
t.Fatal(pErr)
}
if r.Len() != 0 {
t.Errorf("Expected EOF but there are remaining %d bytes to read", r.Len())
}
if len(got.Vin) != len(tt.want.Vin) {
t.Errorf("Check vin size, got %v, want %v", len(got.Vin), len(tt.want.Vin))
}
for i := 0; i != len(got.Vin); i++ {
if !reflect.DeepEqual(got.Vin[i].Addresses, tt.want.Vin[i].Addresses) {
t.Errorf("Check Addresses at input %d, got %v, want %v",
i, got.Vin[i].Addresses, tt.want.Vin[i].Addresses)
}
if !reflect.DeepEqual(got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase) {
t.Errorf("Check Coinbase at input %d, got %v, want %v",
i, got.Vin[i].Coinbase, tt.want.Vin[i].Coinbase)
}
if !reflect.DeepEqual(got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig) {
t.Errorf("Check ScriptSig at input %d, got %v, want %v",
i, got.Vin[i].ScriptSig, tt.want.Vin[i].ScriptSig)
}
if !reflect.DeepEqual(got.Vin[i].Sequence, tt.want.Vin[i].Sequence) {
t.Errorf("Check Sequence at input %d, got %v, want %v",
i, got.Vin[i].Sequence, tt.want.Vin[i].Sequence)
}
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Txid, tt.want.Vin[i].Txid) {
t.Errorf("Check Txid at input %d, got %v, want %v",
i, got.Vin[i].Txid, tt.want.Vin[i].Txid)
}
if tt.args.privacyType == 0 && !reflect.DeepEqual(got.Vin[i].Vout, tt.want.Vin[i].Vout) {
t.Errorf("Check Vout at input %d, got %v, want %v",
i, got.Vin[i].Vout, tt.want.Vin[i].Vout)
}
}
if len(got.Vout) != len(tt.want.Vout) {
t.Errorf("Check vout size, got %v, want %v", len(got.Vout), len(tt.want.Vout))
}
for i := 0; i != len(got.Vout); i++ {
if !reflect.DeepEqual(got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue) {
t.Errorf("Check JsonValue at output %d, got %v, want %v",
i, got.Vout[i].JsonValue, tt.want.Vout[i].JsonValue)
}
if !reflect.DeepEqual(got.Vout[i].N, tt.want.Vout[i].N) {
t.Errorf("Check N at output %d, got %v, want %v",
i, got.Vout[i].N, tt.want.Vout[i].N)
}
// empty addresses and null should be the same
if !((len(got.Vout[i].ScriptPubKey.Addresses) == 0 && len(got.Vout[i].ScriptPubKey.Addresses) == len(tt.want.Vout[i].ScriptPubKey.Addresses)) ||
reflect.DeepEqual(got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)) {
t.Errorf("Check ScriptPubKey.Addresses at output %d, got %v, want %v",
i, got.Vout[i].ScriptPubKey.Addresses, tt.want.Vout[i].ScriptPubKey.Addresses)
}
if !reflect.DeepEqual(got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex) {
t.Errorf("Check ScriptPubKey.Hex at output %d, got %v, want %v",
i, got.Vout[i].ScriptPubKey.Hex, tt.want.Vout[i].ScriptPubKey.Hex)
}
if !reflect.DeepEqual(got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat) {
t.Errorf("Check ValueSat at output %d, got %v, want %v",
i, got.Vout[i].ValueSat, tt.want.Vout[i].ValueSat)
}
}
if got.LockTime != tt.want.LockTime {
t.Errorf("Check LockTime, got %v, want %v", got.LockTime, tt.want.LockTime)
}
if got.Txid != tt.want.Txid {
t.Errorf("Check TxId, got %v, want %v", got.Txid, tt.want.Txid)
}
})
}
}

View File

@ -1,28 +1,28 @@
package xzc
package firo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
type ZcoinRPC struct {
type FiroRPC struct {
*btc.BitcoinRPC
}
func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
func NewFiroRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
// init base implementation
bc, err := btc.NewBitcoinRPC(config, pushHandler)
if err != nil {
return nil, err
}
// init zcoin implementation
zc := &ZcoinRPC{
// init firo implementation
zc := &FiroRPC{
BitcoinRPC: bc.(*btc.BitcoinRPC),
}
@ -35,7 +35,7 @@ func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationTyp
return zc, nil
}
func (zc *ZcoinRPC) Initialize() error {
func (zc *FiroRPC) Initialize() error {
ci, err := zc.GetChainInfo()
if err != nil {
return err
@ -45,7 +45,7 @@ func (zc *ZcoinRPC) Initialize() error {
params := GetChainParams(chainName)
// always create parser
zc.Parser = NewZcoinParser(params, zc.ChainConfig)
zc.Parser = NewFiroParser(params, zc.ChainConfig)
// parameters for getInfo request
if params.Net == MainnetMagic {
@ -61,7 +61,7 @@ func (zc *ZcoinRPC) Initialize() error {
return nil
}
func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
func (zc *FiroRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
var err error
if hash == "" {
@ -96,7 +96,7 @@ func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error)
return block, nil
}
func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
func (zc *FiroRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
glog.V(1).Info("rpc: getblock (verbosity=true) ", hash)
res := btc.ResGetBlockInfo{}
@ -117,7 +117,7 @@ func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
return &res.Result, nil
}
func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.Block, error) {
func (zc *FiroRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.Block, error) {
data, err := zc.GetBlockRaw(hash)
if err != nil {
return nil, err
@ -134,7 +134,7 @@ func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.B
return block, nil
}
func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
func (zc *FiroRPC) GetBlockRaw(hash string) ([]byte, error) {
glog.V(1).Info("rpc: getblock (verbosity=false) ", hash)
res := btc.ResGetBlockRaw{}
@ -155,7 +155,7 @@ func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
return hex.DecodeString(res.Result)
}
func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
func (zc *FiroRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
glog.V(1).Info("rpc: getrawtransaction nonverbose ", txid)
res := btc.ResGetRawTransactionNonverbose{}
@ -183,7 +183,7 @@ func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
return tx, nil
}
func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) {
func (zc *FiroRPC) GetTransaction(txid string) (*bchain.Tx, error) {
r, err := zc.getRawTransaction(txid)
if err != nil {
return nil, err
@ -198,14 +198,14 @@ func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) {
return tx, nil
}
func (zc *ZcoinRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) {
func (zc *FiroRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) {
if csd, ok := tx.CoinSpecificData.(json.RawMessage); ok {
return csd, nil
}
return zc.getRawTransaction(tx.Txid)
}
func (zc *ZcoinRPC) getRawTransaction(txid string) (json.RawMessage, error) {
func (zc *FiroRPC) getRawTransaction(txid string) (json.RawMessage, error) {
glog.V(1).Info("rpc: getrawtransaction ", txid)
res := btc.ResGetRawTransaction{}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,10 @@
package flo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,13 +3,13 @@
package flo
import (
"blockbook/bchain/coins/btc"
"encoding/hex"
"os"
"reflect"
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,13 +1,12 @@
package flo
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/juju/errors"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// FloRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package fujicoin
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (

View File

@ -3,8 +3,6 @@
package fujicoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package fujicoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// FujicoinRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package gamecredits
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package gamecredits
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package gamecredits
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// GameCreditsRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,12 +1,11 @@
package grs
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/base58"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package grs
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"math/big"
@ -13,6 +11,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
var (

View File

@ -1,12 +1,12 @@
package grs
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// GroestlcoinRPC is an interface to JSON-RPC service

View File

@ -1,11 +1,10 @@
package koto
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package koto
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"bytes"
"encoding/hex"
"math/big"
@ -13,6 +11,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
var (

View File

@ -1,12 +1,12 @@
package koto
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// KotoRPC is an interface to JSON-RPC bitcoind service

View File

@ -1,16 +1,15 @@
package liquid
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"strconv"
vlq "github.com/bsm/go-vlq"
"github.com/golang/glog"
"github.com/martinboehm/btcd/txscript"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
const (

View File

@ -3,8 +3,6 @@
package liquid
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,12 +1,12 @@
package liquid
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"github.com/juju/errors"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// LiquidRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package litecoin
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package litecoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package litecoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// LitecoinRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,10 +1,9 @@
package monacoin
import (
"blockbook/bchain/coins/btc"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package monacoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package monacoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// MonacoinRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,18 +1,17 @@
package monetaryunit
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
"bytes"
"io"
"encoding/hex"
"encoding/json"
"io"
"github.com/juju/errors"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
const (

View File

@ -3,8 +3,6 @@
package monetaryunit
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package monetaryunit
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// MonetaryUnitRPC is an interface to JSON-RPC bitcoind service.

View File

@ -1,13 +1,13 @@
package myriad
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"blockbook/bchain/coins/utils"
"bytes"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
"spacecruft.org/spacecruft/blockbook/bchain/coins/utils"
)
// magic numbers

View File

@ -3,8 +3,6 @@
package myriad
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/hex"
"math/big"
"os"
@ -12,6 +10,8 @@ import (
"testing"
"github.com/martinboehm/btcutil/chaincfg"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
func TestMain(m *testing.M) {

View File

@ -1,11 +1,11 @@
package myriad
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"encoding/json"
"github.com/golang/glog"
"spacecruft.org/spacecruft/blockbook/bchain"
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
)
// MyriadRPC is an interface to JSON-RPC bitcoind service.

Some files were not shown because too many files have changed in this diff Show More