mirror of
https://github.com/romanz/electrs.git
synced 2025-02-24 15:02:21 +01:00
Merge branch 'fix-hashtypes'
This commit is contained in:
commit
2133120234
12 changed files with 164 additions and 220 deletions
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -83,7 +83,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bech32"
|
name = "bech32"
|
||||||
version = "0.7.1"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -119,23 +119,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitcoin"
|
name = "bitcoin"
|
||||||
version = "0.21.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bech32 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitcoin_hashes"
|
name = "bitcoin_hashes"
|
||||||
version = "0.7.1"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -337,8 +335,8 @@ version = "0.8.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitcoin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitcoin 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"configure_me 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"configure_me 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"configure_me_codegen 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"configure_me_codegen 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -717,33 +715,6 @@ dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.6.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -757,32 +728,6 @@ name = "rand_core"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_hc"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_isaac"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_jitter"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_os"
|
name = "rand_os"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -796,23 +741,6 @@ dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_pcg"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_xorshift"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -946,11 +874,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "secp256k1"
|
name = "secp256k1"
|
||||||
version = "0.15.5"
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secp256k1-sys"
|
||||||
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1273,11 +1209,11 @@ dependencies = [
|
||||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||||
"checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2"
|
"checksum bech32 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cdcf67bb7ba7797a081cd19009948ab533af7c355d5caf1d08c777582d351e9c"
|
||||||
"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92"
|
"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92"
|
||||||
"checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260"
|
"checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260"
|
||||||
"checksum bitcoin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34f963060a2091b4e285d8082e1946be35caf467e73b3155262c8357fb4595"
|
"checksum bitcoin 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a32c9d2fa897cfbb0db45d71e3d2838666194abc4828c0f994e4b5c3bf85ba4"
|
||||||
"checksum bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db6b697833d852acea530c9e815e6adc724267856b6506bc500362a068a39c7b"
|
"checksum bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6"
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
|
"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
|
||||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||||
|
@ -1347,16 +1283,9 @@ dependencies = [
|
||||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||||
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
||||||
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
|
||||||
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
|
||||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
|
||||||
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
|
||||||
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
|
||||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
|
||||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
|
||||||
"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
||||||
"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
||||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
@ -1374,7 +1303,8 @@ dependencies = [
|
||||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||||
"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a"
|
"checksum secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
|
||||||
|
"checksum secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220"
|
||||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
|
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
|
||||||
|
|
|
@ -24,8 +24,8 @@ latest_rust = [] # use latest Rust features (otherwise, support Rust 1.34)
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.10"
|
base64 = "0.10"
|
||||||
bincode = "1.0"
|
bincode = "1.0"
|
||||||
bitcoin = { version = "0.21", features = ["use-serde"] }
|
bitcoin = { version = "0.23", features = ["use-serde"] }
|
||||||
bitcoin_hashes = "0.7.1"
|
bitcoin_hashes = "0.7.6"
|
||||||
configure_me = "0.3.3"
|
configure_me = "0.3.3"
|
||||||
crossbeam-channel = "0.3"
|
crossbeam-channel = "0.3"
|
||||||
dirs = "1.0"
|
dirs = "1.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
use bitcoin::hash_types::BlockHash;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::{config::Config, daemon, errors::*, index, signal::Waiter, store};
|
use crate::{config::Config, daemon, errors::*, index, signal::Waiter, store};
|
||||||
|
@ -8,7 +8,7 @@ pub struct App {
|
||||||
index: index::Index,
|
index: index::Index,
|
||||||
daemon: daemon::Daemon,
|
daemon: daemon::Daemon,
|
||||||
banner: String,
|
banner: String,
|
||||||
tip: Mutex<Sha256dHash>,
|
tip: Mutex<BlockHash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
@ -23,7 +23,7 @@ impl App {
|
||||||
index,
|
index,
|
||||||
daemon: daemon.reconnect()?,
|
daemon: daemon.reconnect()?,
|
||||||
banner: config.server_banner.clone(),
|
banner: config.server_banner.clone(),
|
||||||
tip: Mutex::new(Sha256dHash::default()),
|
tip: Mutex::new(BlockHash::default()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
use bitcoin::hash_types::BlockHash;
|
||||||
use bitcoin::blockdata::block::Block;
|
use bitcoin::blockdata::block::Block;
|
||||||
use bitcoin::consensus::encode::{deserialize, Decodable};
|
use bitcoin::consensus::encode::{deserialize, Decodable};
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use libc;
|
use libc;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -20,11 +19,12 @@ use crate::metrics::{CounterVec, Histogram, HistogramOpts, HistogramVec, MetricO
|
||||||
use crate::signal::Waiter;
|
use crate::signal::Waiter;
|
||||||
use crate::store::{DBStore, Row, WriteStore};
|
use crate::store::{DBStore, Row, WriteStore};
|
||||||
use crate::util::{spawn_thread, HeaderList, SyncChannel};
|
use crate::util::{spawn_thread, HeaderList, SyncChannel};
|
||||||
|
use bitcoin::BitcoinHash;
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
magic: u32,
|
magic: u32,
|
||||||
current_headers: HeaderList,
|
current_headers: HeaderList,
|
||||||
indexed_blockhashes: Mutex<HashSet<Sha256dHash>>,
|
indexed_blockhashes: Mutex<HashSet<BlockHash>>,
|
||||||
// metrics
|
// metrics
|
||||||
duration: HistogramVec,
|
duration: HistogramVec,
|
||||||
block_count: CounterVec,
|
block_count: CounterVec,
|
||||||
|
@ -35,7 +35,7 @@ impl Parser {
|
||||||
fn new(
|
fn new(
|
||||||
daemon: &Daemon,
|
daemon: &Daemon,
|
||||||
metrics: &Metrics,
|
metrics: &Metrics,
|
||||||
indexed_blockhashes: HashSet<Sha256dHash>,
|
indexed_blockhashes: HashSet<BlockHash>,
|
||||||
) -> Result<Arc<Parser>> {
|
) -> Result<Arc<Parser>> {
|
||||||
Ok(Arc::new(Parser {
|
Ok(Arc::new(Parser {
|
||||||
magic: daemon.magic(),
|
magic: daemon.magic(),
|
||||||
|
|
29
src/cache.rs
29
src/cache.rs
|
@ -1,9 +1,9 @@
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::metrics::{CounterVec, MetricOpts, Metrics};
|
use crate::metrics::{CounterVec, MetricOpts, Metrics};
|
||||||
|
|
||||||
|
use bitcoin::hash_types::{BlockHash, Txid};
|
||||||
use bitcoin::blockdata::transaction::Transaction;
|
use bitcoin::blockdata::transaction::Transaction;
|
||||||
use bitcoin::consensus::encode::deserialize;
|
use bitcoin::consensus::encode::deserialize;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
use prometheus::IntGauge;
|
use prometheus::IntGauge;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -62,7 +62,7 @@ impl<K: Hash + Eq, V> SizedLruCache<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockTxIDsCache {
|
pub struct BlockTxIDsCache {
|
||||||
map: Mutex<SizedLruCache<Sha256dHash /* blockhash */, Vec<Sha256dHash /* txid */>>>,
|
map: Mutex<SizedLruCache<BlockHash, Vec<Txid>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockTxIDsCache {
|
impl BlockTxIDsCache {
|
||||||
|
@ -85,11 +85,11 @@ impl BlockTxIDsCache {
|
||||||
|
|
||||||
pub fn get_or_else<F>(
|
pub fn get_or_else<F>(
|
||||||
&self,
|
&self,
|
||||||
blockhash: &Sha256dHash,
|
blockhash: &BlockHash,
|
||||||
load_txids_func: F,
|
load_txids_func: F,
|
||||||
) -> Result<Vec<Sha256dHash>>
|
) -> Result<Vec<Txid>>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<Vec<Sha256dHash>>,
|
F: FnOnce() -> Result<Vec<Txid>>,
|
||||||
{
|
{
|
||||||
if let Some(txids) = self.map.lock().unwrap().get(blockhash) {
|
if let Some(txids) = self.map.lock().unwrap().get(blockhash) {
|
||||||
return Ok(txids.clone());
|
return Ok(txids.clone());
|
||||||
|
@ -107,7 +107,7 @@ impl BlockTxIDsCache {
|
||||||
|
|
||||||
pub struct TransactionCache {
|
pub struct TransactionCache {
|
||||||
// Store serialized transaction (should use less RAM).
|
// Store serialized transaction (should use less RAM).
|
||||||
map: Mutex<SizedLruCache<Sha256dHash, Vec<u8>>>,
|
map: Mutex<SizedLruCache<Txid, Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransactionCache {
|
impl TransactionCache {
|
||||||
|
@ -128,7 +128,7 @@ impl TransactionCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_or_else<F>(&self, txid: &Sha256dHash, load_txn_func: F) -> Result<Transaction>
|
pub fn get_or_else<F>(&self, txid: &Txid, load_txn_func: F) -> Result<Transaction>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<Vec<u8>>,
|
F: FnOnce() -> Result<Vec<u8>>,
|
||||||
{
|
{
|
||||||
|
@ -201,17 +201,17 @@ mod tests {
|
||||||
assert_eq!(usage.get(), 100);
|
assert_eq!(usage.get(), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_hash(seed: u8) -> Sha256dHash {
|
fn gen_hash<T: Hash>(seed: u8) -> T {
|
||||||
let bytes: Vec<u8> = (seed..seed + 32).collect();
|
let bytes: Vec<u8> = (seed..seed + 32).collect();
|
||||||
Sha256dHash::hash(&bytes[..])
|
<T as Hash>::hash(&bytes[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocktxids_cache_hit_and_miss() {
|
fn test_blocktxids_cache_hit_and_miss() {
|
||||||
let block1 = gen_hash(1);
|
let block1: BlockHash = gen_hash(1);
|
||||||
let block2 = gen_hash(2);
|
let block2: BlockHash = gen_hash(2);
|
||||||
let block3 = gen_hash(3);
|
let block3: BlockHash = gen_hash(3);
|
||||||
let txids = vec![gen_hash(4), gen_hash(5)];
|
let txids: Vec<Txid> = vec![gen_hash(4), gen_hash(5)];
|
||||||
|
|
||||||
let misses: Mutex<usize> = Mutex::new(0);
|
let misses: Mutex<usize> = Mutex::new(0);
|
||||||
let miss_func = || {
|
let miss_func = || {
|
||||||
|
@ -249,7 +249,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_txn_cache() {
|
fn test_txn_cache() {
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
|
||||||
use hex;
|
use hex;
|
||||||
|
|
||||||
let dummy_metrics = Metrics::new("127.0.0.1:60000".parse().unwrap());
|
let dummy_metrics = Metrics::new("127.0.0.1:60000".parse().unwrap());
|
||||||
|
@ -257,7 +256,7 @@ mod tests {
|
||||||
let tx_bytes = hex::decode("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
|
let tx_bytes = hex::decode("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
|
||||||
|
|
||||||
let tx: Transaction = deserialize(&tx_bytes).unwrap();
|
let tx: Transaction = deserialize(&tx_bytes).unwrap();
|
||||||
let txid = tx.bitcoin_hash();
|
let txid = tx.txid();
|
||||||
|
|
||||||
let mut misses = 0;
|
let mut misses = 0;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use base64;
|
use base64;
|
||||||
|
use bitcoin_hashes::Hash;
|
||||||
|
use bitcoin::hash_types::{BlockHash, Txid};
|
||||||
use bitcoin::blockdata::block::{Block, BlockHeader};
|
use bitcoin::blockdata::block::{Block, BlockHeader};
|
||||||
use bitcoin::blockdata::transaction::Transaction;
|
use bitcoin::blockdata::transaction::Transaction;
|
||||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||||
use bitcoin::network::constants::Network;
|
use bitcoin::network::constants::Network;
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
|
||||||
use bitcoin_hashes::hex::{FromHex, ToHex};
|
use bitcoin_hashes::hex::{FromHex, ToHex};
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use glob;
|
use glob;
|
||||||
use hex;
|
use hex;
|
||||||
use serde_json::{from_str, from_value, Map, Value};
|
use serde_json::{from_str, from_value, Map, Value};
|
||||||
|
@ -22,9 +22,10 @@ use crate::errors::*;
|
||||||
use crate::metrics::{HistogramOpts, HistogramVec, Metrics};
|
use crate::metrics::{HistogramOpts, HistogramVec, Metrics};
|
||||||
use crate::signal::Waiter;
|
use crate::signal::Waiter;
|
||||||
use crate::util::HeaderList;
|
use crate::util::HeaderList;
|
||||||
|
use bitcoin::BitcoinHash;
|
||||||
|
|
||||||
fn parse_hash(value: &Value) -> Result<Sha256dHash> {
|
fn parse_hash<T: Hash>(value: &Value) -> Result<T> {
|
||||||
Ok(Sha256dHash::from_hex(
|
Ok(T::from_hex(
|
||||||
value
|
value
|
||||||
.as_str()
|
.as_str()
|
||||||
.chain_err(|| format!("non-string value: {}", value))?,
|
.chain_err(|| format!("non-string value: {}", value))?,
|
||||||
|
@ -460,11 +461,11 @@ impl Daemon {
|
||||||
Ok(self.getnetworkinfo()?.relayfee)
|
Ok(self.getnetworkinfo()?.relayfee)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getbestblockhash(&self) -> Result<Sha256dHash> {
|
pub fn getbestblockhash(&self) -> Result<BlockHash> {
|
||||||
parse_hash(&self.request("getbestblockhash", json!([]))?).chain_err(|| "invalid blockhash")
|
parse_hash(&self.request("getbestblockhash", json!([]))?).chain_err(|| "invalid blockhash")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getblockheader(&self, blockhash: &Sha256dHash) -> Result<BlockHeader> {
|
pub fn getblockheader(&self, blockhash: &BlockHash) -> Result<BlockHeader> {
|
||||||
header_from_value(self.request(
|
header_from_value(self.request(
|
||||||
"getblockheader",
|
"getblockheader",
|
||||||
json!([blockhash.to_hex(), /*verbose=*/ false]),
|
json!([blockhash.to_hex(), /*verbose=*/ false]),
|
||||||
|
@ -485,7 +486,7 @@ impl Daemon {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getblock(&self, blockhash: &Sha256dHash) -> Result<Block> {
|
pub fn getblock(&self, blockhash: &BlockHash) -> Result<Block> {
|
||||||
let block = block_from_value(
|
let block = block_from_value(
|
||||||
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ false]))?,
|
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ false]))?,
|
||||||
)?;
|
)?;
|
||||||
|
@ -493,7 +494,7 @@ impl Daemon {
|
||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_blocktxids(&self, blockhash: &Sha256dHash) -> Result<Vec<Sha256dHash>> {
|
fn load_blocktxids(&self, blockhash: &BlockHash) -> Result<Vec<Txid>> {
|
||||||
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ 1]))?
|
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ 1]))?
|
||||||
.get("tx")
|
.get("tx")
|
||||||
.chain_err(|| "block missing txids")?
|
.chain_err(|| "block missing txids")?
|
||||||
|
@ -501,15 +502,15 @@ impl Daemon {
|
||||||
.chain_err(|| "invalid block txids")?
|
.chain_err(|| "invalid block txids")?
|
||||||
.iter()
|
.iter()
|
||||||
.map(parse_hash)
|
.map(parse_hash)
|
||||||
.collect::<Result<Vec<Sha256dHash>>>()
|
.collect::<Result<Vec<Txid>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getblocktxids(&self, blockhash: &Sha256dHash) -> Result<Vec<Sha256dHash>> {
|
pub fn getblocktxids(&self, blockhash: &BlockHash) -> Result<Vec<Txid>> {
|
||||||
self.blocktxids_cache
|
self.blocktxids_cache
|
||||||
.get_or_else(&blockhash, || self.load_blocktxids(blockhash))
|
.get_or_else(&blockhash, || self.load_blocktxids(blockhash))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getblocks(&self, blockhashes: &[Sha256dHash]) -> Result<Vec<Block>> {
|
pub fn getblocks(&self, blockhashes: &[BlockHash]) -> Result<Vec<Block>> {
|
||||||
let params_list: Vec<Value> = blockhashes
|
let params_list: Vec<Value> = blockhashes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hash| json!([hash.to_hex(), /*verbose=*/ false]))
|
.map(|hash| json!([hash.to_hex(), /*verbose=*/ false]))
|
||||||
|
@ -524,8 +525,8 @@ impl Daemon {
|
||||||
|
|
||||||
pub fn gettransaction(
|
pub fn gettransaction(
|
||||||
&self,
|
&self,
|
||||||
txhash: &Sha256dHash,
|
txhash: &Txid,
|
||||||
blockhash: Option<Sha256dHash>,
|
blockhash: Option<BlockHash>,
|
||||||
) -> Result<Transaction> {
|
) -> Result<Transaction> {
|
||||||
let mut args = json!([txhash.to_hex(), /*verbose=*/ false]);
|
let mut args = json!([txhash.to_hex(), /*verbose=*/ false]);
|
||||||
if let Some(blockhash) = blockhash {
|
if let Some(blockhash) = blockhash {
|
||||||
|
@ -536,8 +537,8 @@ impl Daemon {
|
||||||
|
|
||||||
pub fn gettransaction_raw(
|
pub fn gettransaction_raw(
|
||||||
&self,
|
&self,
|
||||||
txhash: &Sha256dHash,
|
txhash: &Txid,
|
||||||
blockhash: Option<Sha256dHash>,
|
blockhash: Option<BlockHash>,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
let mut args = json!([txhash.to_hex(), verbose]);
|
let mut args = json!([txhash.to_hex(), verbose]);
|
||||||
|
@ -547,7 +548,7 @@ impl Daemon {
|
||||||
Ok(self.request("getrawtransaction", args)?)
|
Ok(self.request("getrawtransaction", args)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gettransactions(&self, txhashes: &[&Sha256dHash]) -> Result<Vec<Transaction>> {
|
pub fn gettransactions(&self, txhashes: &[&Txid]) -> Result<Vec<Transaction>> {
|
||||||
let params_list: Vec<Value> = txhashes
|
let params_list: Vec<Value> = txhashes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|txhash| json!([txhash.to_hex(), /*verbose=*/ false]))
|
.map(|txhash| json!([txhash.to_hex(), /*verbose=*/ false]))
|
||||||
|
@ -562,7 +563,7 @@ impl Daemon {
|
||||||
Ok(txs)
|
Ok(txs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getmempooltxids(&self) -> Result<HashSet<Sha256dHash>> {
|
pub fn getmempooltxids(&self) -> Result<HashSet<Txid>> {
|
||||||
let txids: Value = self.request("getrawmempool", json!([/*verbose=*/ false]))?;
|
let txids: Value = self.request("getrawmempool", json!([/*verbose=*/ false]))?;
|
||||||
let mut result = HashSet::new();
|
let mut result = HashSet::new();
|
||||||
for value in txids.as_array().chain_err(|| "non-array result")? {
|
for value in txids.as_array().chain_err(|| "non-array result")? {
|
||||||
|
@ -571,7 +572,7 @@ impl Daemon {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getmempoolentry(&self, txid: &Sha256dHash) -> Result<MempoolEntry> {
|
pub fn getmempoolentry(&self, txid: &Txid) -> Result<MempoolEntry> {
|
||||||
let entry = self.request("getmempoolentry", json!([txid.to_hex()]))?;
|
let entry = self.request("getmempoolentry", json!([txid.to_hex()]))?;
|
||||||
let fee = (entry
|
let fee = (entry
|
||||||
.get("fee")
|
.get("fee")
|
||||||
|
@ -588,16 +589,16 @@ impl Daemon {
|
||||||
Ok(MempoolEntry::new(fee, vsize))
|
Ok(MempoolEntry::new(fee, vsize))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn broadcast(&self, tx: &Transaction) -> Result<Sha256dHash> {
|
pub fn broadcast(&self, tx: &Transaction) -> Result<Txid> {
|
||||||
let tx = hex::encode(serialize(tx));
|
let tx = hex::encode(serialize(tx));
|
||||||
let txid = self.request("sendrawtransaction", json!([tx]))?;
|
let txid = self.request("sendrawtransaction", json!([tx]))?;
|
||||||
Ok(
|
Ok(
|
||||||
Sha256dHash::from_hex(txid.as_str().chain_err(|| "non-string txid")?)
|
Txid::from_hex(txid.as_str().chain_err(|| "non-string txid")?)
|
||||||
.chain_err(|| "failed to parse txid")?,
|
.chain_err(|| "failed to parse txid")?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_headers(&self, tip: &Sha256dHash) -> Result<Vec<BlockHeader>> {
|
fn get_all_headers(&self, tip: &BlockHash) -> Result<Vec<BlockHeader>> {
|
||||||
let info: Value = self.request("getblockheader", json!([tip.to_hex()]))?;
|
let info: Value = self.request("getblockheader", json!([tip.to_hex()]))?;
|
||||||
let tip_height = info
|
let tip_height = info
|
||||||
.get("height")
|
.get("height")
|
||||||
|
@ -607,7 +608,7 @@ impl Daemon {
|
||||||
let all_heights: Vec<usize> = (0..=tip_height).collect();
|
let all_heights: Vec<usize> = (0..=tip_height).collect();
|
||||||
let chunk_size = 100_000;
|
let chunk_size = 100_000;
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = BlockHash::default();
|
||||||
for heights in all_heights.chunks(chunk_size) {
|
for heights in all_heights.chunks(chunk_size) {
|
||||||
trace!("downloading {} block headers", heights.len());
|
trace!("downloading {} block headers", heights.len());
|
||||||
let mut headers = self.getblockheaders(&heights)?;
|
let mut headers = self.getblockheaders(&heights)?;
|
||||||
|
@ -628,7 +629,7 @@ impl Daemon {
|
||||||
pub fn get_new_headers(
|
pub fn get_new_headers(
|
||||||
&self,
|
&self,
|
||||||
indexed_headers: &HeaderList,
|
indexed_headers: &HeaderList,
|
||||||
bestblockhash: &Sha256dHash,
|
bestblockhash: &BlockHash,
|
||||||
) -> Result<Vec<BlockHeader>> {
|
) -> Result<Vec<BlockHeader>> {
|
||||||
// Iterate back over headers until known blockash is found:
|
// Iterate back over headers until known blockash is found:
|
||||||
if indexed_headers.is_empty() {
|
if indexed_headers.is_empty() {
|
||||||
|
@ -640,7 +641,7 @@ impl Daemon {
|
||||||
bestblockhash,
|
bestblockhash,
|
||||||
);
|
);
|
||||||
let mut new_headers = vec![];
|
let mut new_headers = vec![];
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = BlockHash::default();
|
||||||
let mut blockhash = *bestblockhash;
|
let mut blockhash = *bestblockhash;
|
||||||
while blockhash != null_hash {
|
while blockhash != null_hash {
|
||||||
if indexed_headers.header_by_blockhash(&blockhash).is_some() {
|
if indexed_headers.header_by_blockhash(&blockhash).is_some() {
|
||||||
|
|
36
src/index.rs
36
src/index.rs
|
@ -1,9 +1,8 @@
|
||||||
use bincode;
|
use bincode;
|
||||||
|
use bitcoin::hash_types::{BlockHash, Txid};
|
||||||
use bitcoin::blockdata::block::{Block, BlockHeader};
|
use bitcoin::blockdata::block::{Block, BlockHeader};
|
||||||
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
|
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
|
||||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
@ -21,6 +20,7 @@ use crate::util::{
|
||||||
full_hash, hash_prefix, spawn_thread, Bytes, FullHash, HashPrefix, HeaderEntry, HeaderList,
|
full_hash, hash_prefix, spawn_thread, Bytes, FullHash, HashPrefix, HeaderEntry, HeaderList,
|
||||||
HeaderMap, SyncChannel, HASH_PREFIX_LEN,
|
HeaderMap, SyncChannel, HASH_PREFIX_LEN,
|
||||||
};
|
};
|
||||||
|
use bitcoin::BitcoinHash;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TxInKey {
|
pub struct TxInKey {
|
||||||
|
@ -36,7 +36,7 @@ pub struct TxInRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxInRow {
|
impl TxInRow {
|
||||||
pub fn new(txid: &Sha256dHash, input: &TxIn) -> TxInRow {
|
pub fn new(txid: &Txid, input: &TxIn) -> TxInRow {
|
||||||
TxInRow {
|
TxInRow {
|
||||||
key: TxInKey {
|
key: TxInKey {
|
||||||
code: b'I',
|
code: b'I',
|
||||||
|
@ -47,7 +47,7 @@ impl TxInRow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter(txid: &Sha256dHash, output_index: usize) -> Bytes {
|
pub fn filter(txid: &Txid, output_index: usize) -> Bytes {
|
||||||
bincode::serialize(&TxInKey {
|
bincode::serialize(&TxInKey {
|
||||||
code: b'I',
|
code: b'I',
|
||||||
prev_hash_prefix: hash_prefix(&txid[..]),
|
prev_hash_prefix: hash_prefix(&txid[..]),
|
||||||
|
@ -81,7 +81,7 @@ pub struct TxOutRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxOutRow {
|
impl TxOutRow {
|
||||||
pub fn new(txid: &Sha256dHash, output: &TxOut) -> TxOutRow {
|
pub fn new(txid: &Txid, output: &TxOut) -> TxOutRow {
|
||||||
TxOutRow {
|
TxOutRow {
|
||||||
key: TxOutKey {
|
key: TxOutKey {
|
||||||
code: b'O',
|
code: b'O',
|
||||||
|
@ -123,7 +123,7 @@ pub struct TxRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxRow {
|
impl TxRow {
|
||||||
pub fn new(txid: &Sha256dHash, height: u32) -> TxRow {
|
pub fn new(txid: &Txid, height: u32) -> TxRow {
|
||||||
TxRow {
|
TxRow {
|
||||||
key: TxKey {
|
key: TxKey {
|
||||||
code: b'T',
|
code: b'T',
|
||||||
|
@ -137,7 +137,7 @@ impl TxRow {
|
||||||
[b"T", &txid_prefix[..]].concat()
|
[b"T", &txid_prefix[..]].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_full(txid: &Sha256dHash) -> Bytes {
|
pub fn filter_full(txid: &Txid) -> Bytes {
|
||||||
[b"T", &txid[..]].concat()
|
[b"T", &txid[..]].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +174,8 @@ pub fn index_transaction<'a>(
|
||||||
txn: &'a Transaction,
|
txn: &'a Transaction,
|
||||||
height: usize,
|
height: usize,
|
||||||
) -> impl 'a + Iterator<Item = Row> {
|
) -> impl 'a + Iterator<Item = Row> {
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = Txid::default();
|
||||||
let txid: Sha256dHash = txn.txid();
|
let txid = txn.txid();
|
||||||
|
|
||||||
let inputs = txn.input.iter().filter_map(move |input| {
|
let inputs = txn.input.iter().filter_map(move |input| {
|
||||||
if input.previous_output.txid == null_hash {
|
if input.previous_output.txid == null_hash {
|
||||||
|
@ -213,7 +213,7 @@ pub fn index_block<'a>(block: &'a Block, height: usize) -> impl 'a + Iterator<It
|
||||||
.chain(std::iter::once(row))
|
.chain(std::iter::once(row))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_indexed_block(blockhash: &Sha256dHash) -> Row {
|
pub fn last_indexed_block(blockhash: &BlockHash) -> Row {
|
||||||
// Store last indexed block (i.e. all previous blocks were indexed)
|
// Store last indexed block (i.e. all previous blocks were indexed)
|
||||||
Row {
|
Row {
|
||||||
key: b"L".to_vec(),
|
key: b"L".to_vec(),
|
||||||
|
@ -221,7 +221,7 @@ pub fn last_indexed_block(blockhash: &Sha256dHash) -> Row {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<Sha256dHash> {
|
pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<BlockHash> {
|
||||||
let mut result = HashSet::new();
|
let mut result = HashSet::new();
|
||||||
for row in store.scan(b"B") {
|
for row in store.scan(b"B") {
|
||||||
let key: BlockKey = bincode::deserialize(&row.key).unwrap();
|
let key: BlockKey = bincode::deserialize(&row.key).unwrap();
|
||||||
|
@ -231,10 +231,10 @@ pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<Sha256dHash> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
||||||
let latest_blockhash: Sha256dHash = match store.get(b"L") {
|
let latest_blockhash: BlockHash = match store.get(b"L") {
|
||||||
// latest blockheader persisted in the DB.
|
// latest blockheader persisted in the DB.
|
||||||
Some(row) => deserialize(&row).unwrap(),
|
Some(row) => deserialize(&row).unwrap(),
|
||||||
None => Sha256dHash::default(),
|
None => BlockHash::default(),
|
||||||
};
|
};
|
||||||
trace!("latest indexed blockhash: {}", latest_blockhash);
|
trace!("latest indexed blockhash: {}", latest_blockhash);
|
||||||
let mut map = HeaderMap::new();
|
let mut map = HeaderMap::new();
|
||||||
|
@ -244,7 +244,7 @@ fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
||||||
map.insert(deserialize(&key.hash).unwrap(), header);
|
map.insert(deserialize(&key.hash).unwrap(), header);
|
||||||
}
|
}
|
||||||
let mut headers = vec![];
|
let mut headers = vec![];
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = BlockHash::default();
|
||||||
let mut blockhash = latest_blockhash;
|
let mut blockhash = latest_blockhash;
|
||||||
while blockhash != null_hash {
|
while blockhash != null_hash {
|
||||||
let header = map
|
let header = map
|
||||||
|
@ -264,7 +264,7 @@ fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
headers
|
headers
|
||||||
.last()
|
.last()
|
||||||
.map(BitcoinHash::bitcoin_hash)
|
.map(BlockHeader::bitcoin_hash)
|
||||||
.unwrap_or(null_hash),
|
.unwrap_or(null_hash),
|
||||||
latest_blockhash
|
latest_blockhash
|
||||||
);
|
);
|
||||||
|
@ -370,7 +370,7 @@ impl Index {
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, store: &impl WriteStore, waiter: &Waiter) -> Result<Sha256dHash> {
|
pub fn update(&self, store: &impl WriteStore, waiter: &Waiter) -> Result<BlockHash> {
|
||||||
let daemon = self.daemon.reconnect()?;
|
let daemon = self.daemon.reconnect()?;
|
||||||
let tip = daemon.getbestblockhash()?;
|
let tip = daemon.getbestblockhash()?;
|
||||||
let new_headers: Vec<HeaderEntry> = {
|
let new_headers: Vec<HeaderEntry> = {
|
||||||
|
@ -380,13 +380,13 @@ impl Index {
|
||||||
if let Some(latest_header) = new_headers.last() {
|
if let Some(latest_header) = new_headers.last() {
|
||||||
info!("{:?} ({} left to index)", latest_header, new_headers.len());
|
info!("{:?} ({} left to index)", latest_header, new_headers.len());
|
||||||
};
|
};
|
||||||
let height_map = HashMap::<Sha256dHash, usize>::from_iter(
|
let height_map = HashMap::<BlockHash, usize>::from_iter(
|
||||||
new_headers.iter().map(|h| (*h.hash(), h.height())),
|
new_headers.iter().map(|h| (*h.hash(), h.height())),
|
||||||
);
|
);
|
||||||
|
|
||||||
let chan = SyncChannel::new(1);
|
let chan = SyncChannel::new(1);
|
||||||
let sender = chan.sender();
|
let sender = chan.sender();
|
||||||
let blockhashes: Vec<Sha256dHash> = new_headers.iter().map(|h| *h.hash()).collect();
|
let blockhashes: Vec<BlockHash> = new_headers.iter().map(|h| *h.hash()).collect();
|
||||||
let batch_size = self.batch_size;
|
let batch_size = self.batch_size;
|
||||||
let fetcher = spawn_thread("fetcher", move || {
|
let fetcher = spawn_thread("fetcher", move || {
|
||||||
for chunk in blockhashes.chunks(batch_size) {
|
for chunk in blockhashes.chunks(batch_size) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use bitcoin::hash_types::Txid;
|
||||||
use bitcoin::blockdata::transaction::Transaction;
|
use bitcoin::blockdata::transaction::Transaction;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use hex;
|
use hex;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
@ -139,7 +139,7 @@ impl Stats {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tracker {
|
pub struct Tracker {
|
||||||
items: HashMap<Sha256dHash, Item>,
|
items: HashMap<Txid, Item>,
|
||||||
index: MempoolStore,
|
index: MempoolStore,
|
||||||
histogram: Vec<(f32, u32)>,
|
histogram: Vec<(f32, u32)>,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
|
@ -175,7 +175,7 @@ impl Tracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_txn(&self, txid: &Sha256dHash) -> Option<Transaction> {
|
pub fn get_txn(&self, txid: &Txid) -> Option<Transaction> {
|
||||||
self.items.get(txid).map(|stats| stats.tx.clone())
|
self.items.get(txid).map(|stats| stats.tx.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ impl Tracker {
|
||||||
|
|
||||||
let timer = self.stats.start_timer("add");
|
let timer = self.stats.start_timer("add");
|
||||||
let txids_iter = new_txids.difference(&old_txids);
|
let txids_iter = new_txids.difference(&old_txids);
|
||||||
let entries: Vec<(&Sha256dHash, MempoolEntry)> = txids_iter
|
let entries: Vec<(&Txid, MempoolEntry)> = txids_iter
|
||||||
.filter_map(|txid| {
|
.filter_map(|txid| {
|
||||||
match daemon.getmempoolentry(txid) {
|
match daemon.getmempoolentry(txid) {
|
||||||
Ok(entry) => Some((txid, entry)),
|
Ok(entry) => Some((txid, entry)),
|
||||||
|
@ -212,7 +212,7 @@ impl Tracker {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if !entries.is_empty() {
|
if !entries.is_empty() {
|
||||||
let txids: Vec<&Sha256dHash> = entries.iter().map(|(txid, _)| *txid).collect();
|
let txids: Vec<&Txid> = entries.iter().map(|(txid, _)| *txid).collect();
|
||||||
let txs = match daemon.gettransactions(&txids) {
|
let txs = match daemon.gettransactions(&txids) {
|
||||||
Ok(txs) => txs,
|
Ok(txs) => txs,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -241,12 +241,12 @@ impl Tracker {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&mut self, txid: &Sha256dHash, tx: Transaction, entry: MempoolEntry) {
|
fn add(&mut self, txid: &Txid, tx: Transaction, entry: MempoolEntry) {
|
||||||
self.index.add(&tx);
|
self.index.add(&tx);
|
||||||
self.items.insert(*txid, Item { tx, entry });
|
self.items.insert(*txid, Item { tx, entry });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(&mut self, txid: &Sha256dHash) {
|
fn remove(&mut self, txid: &Txid) {
|
||||||
let stats = self
|
let stats = self
|
||||||
.items
|
.items
|
||||||
.remove(txid)
|
.remove(txid)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use bitcoin::network::constants::Network;
|
||||||
use bitcoin::network::message::NetworkMessage;
|
use bitcoin::network::message::NetworkMessage;
|
||||||
use bitcoin::network::message_blockdata::InvType;
|
use bitcoin::network::message_blockdata::InvType;
|
||||||
use bitcoin::network::socket::Socket;
|
use bitcoin::network::socket::Socket;
|
||||||
use bitcoin::util::hash::Sha256dHash;
|
use bitcoin::hash_types::Txid;
|
||||||
use bitcoin::util::Error;
|
use bitcoin::util::Error;
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
@ -19,7 +19,7 @@ fn connect() -> Result<Socket, Error> {
|
||||||
Ok(sock)
|
Ok(sock)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(mut sock: Socket, tx: Sender<Sha256dHash>) {
|
fn handle(mut sock: Socket, tx: Sender<Txid>) {
|
||||||
let mut outgoing = vec![sock.version_message(0).unwrap()];
|
let mut outgoing = vec![sock.version_message(0).unwrap()];
|
||||||
loop {
|
loop {
|
||||||
for msg in outgoing.split_off(0) {
|
for msg in outgoing.split_off(0) {
|
||||||
|
@ -53,7 +53,7 @@ fn handle(mut sock: Socket, tx: Sender<Sha256dHash>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run() -> util::Channel<Sha256dHash> {
|
pub fn run() -> util::Channel<Txid> {
|
||||||
let chan = util::Channel::new();
|
let chan = util::Channel::new();
|
||||||
let tx = chan.sender();
|
let tx = chan.sender();
|
||||||
|
|
||||||
|
|
68
src/query.rs
68
src/query.rs
|
@ -1,7 +1,8 @@
|
||||||
use bitcoin::blockdata::transaction::Transaction;
|
use bitcoin::blockdata::transaction::Transaction;
|
||||||
use bitcoin::consensus::encode::deserialize;
|
use bitcoin::consensus::encode::deserialize;
|
||||||
|
use bitcoin::hash_types::{Txid, BlockHash, TxMerkleNode};
|
||||||
|
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
|
||||||
use bitcoin_hashes::hex::ToHex;
|
use bitcoin_hashes::hex::ToHex;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use bitcoin_hashes::Hash;
|
use bitcoin_hashes::Hash;
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
|
@ -19,16 +20,16 @@ use crate::store::{ReadStore, Row};
|
||||||
use crate::util::{FullHash, HashPrefix, HeaderEntry};
|
use crate::util::{FullHash, HashPrefix, HeaderEntry};
|
||||||
|
|
||||||
pub struct FundingOutput {
|
pub struct FundingOutput {
|
||||||
pub txn_id: Sha256dHash,
|
pub txn_id: Txid,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
pub output_index: usize,
|
pub output_index: usize,
|
||||||
pub value: u64,
|
pub value: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutPoint = (Sha256dHash, usize); // (txid, output_index)
|
type OutPoint = (Txid, usize); // (txid, output_index)
|
||||||
|
|
||||||
struct SpendingInput {
|
struct SpendingInput {
|
||||||
txn_id: Sha256dHash,
|
txn_id: Txid,
|
||||||
height: u32,
|
height: u32,
|
||||||
funding_output: OutPoint,
|
funding_output: OutPoint,
|
||||||
value: u64,
|
value: u64,
|
||||||
|
@ -62,15 +63,15 @@ impl Status {
|
||||||
calc_balance(&self.mempool)
|
calc_balance(&self.mempool)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn history(&self) -> Vec<(i32, Sha256dHash)> {
|
pub fn history(&self) -> Vec<(i32, Txid)> {
|
||||||
let mut txns_map = HashMap::<Sha256dHash, i32>::new();
|
let mut txns_map = HashMap::<Txid, i32>::new();
|
||||||
for f in self.funding() {
|
for f in self.funding() {
|
||||||
txns_map.insert(f.txn_id, f.height as i32);
|
txns_map.insert(f.txn_id, f.height as i32);
|
||||||
}
|
}
|
||||||
for s in self.spending() {
|
for s in self.spending() {
|
||||||
txns_map.insert(s.txn_id, s.height as i32);
|
txns_map.insert(s.txn_id, s.height as i32);
|
||||||
}
|
}
|
||||||
let mut txns: Vec<(i32, Sha256dHash)> =
|
let mut txns: Vec<(i32, Txid)> =
|
||||||
txns_map.into_iter().map(|item| (item.1, item.0)).collect();
|
txns_map.into_iter().map(|item| (item.1, item.0)).collect();
|
||||||
txns.sort_unstable();
|
txns.sort_unstable();
|
||||||
txns
|
txns
|
||||||
|
@ -116,15 +117,15 @@ struct TxnHeight {
|
||||||
height: u32,
|
height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merklize(left: Sha256dHash, right: Sha256dHash) -> Sha256dHash {
|
fn merklize<T: Hash>(left: T, right: T) -> T {
|
||||||
let data = [&left[..], &right[..]].concat();
|
let data = [&left[..], &right[..]].concat();
|
||||||
Sha256dHash::hash(&data)
|
<T as Hash>::hash(&data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_merkle_branch_and_root(
|
fn create_merkle_branch_and_root<T: Hash>(
|
||||||
mut hashes: Vec<Sha256dHash>,
|
mut hashes: Vec<T>,
|
||||||
mut index: usize,
|
mut index: usize,
|
||||||
) -> (Vec<Sha256dHash>, Sha256dHash) {
|
) -> (Vec<T>, T) {
|
||||||
let mut merkle = vec![];
|
let mut merkle = vec![];
|
||||||
while hashes.len() > 1 {
|
while hashes.len() > 1 {
|
||||||
if hashes.len() % 2 != 0 {
|
if hashes.len() % 2 != 0 {
|
||||||
|
@ -143,7 +144,7 @@ fn create_merkle_branch_and_root(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the functions below can be part of ReadStore.
|
// TODO: the functions below can be part of ReadStore.
|
||||||
fn txrow_by_txid(store: &dyn ReadStore, txid: &Sha256dHash) -> Option<TxRow> {
|
fn txrow_by_txid(store: &dyn ReadStore, txid: &Txid) -> Option<TxRow> {
|
||||||
let key = TxRow::filter_full(&txid);
|
let key = TxRow::filter_full(&txid);
|
||||||
let value = store.get(&key)?;
|
let value = store.get(&key)?;
|
||||||
Some(TxRow::from_row(&Row { key, value }))
|
Some(TxRow::from_row(&Row { key, value }))
|
||||||
|
@ -167,7 +168,7 @@ fn txids_by_script_hash(store: &dyn ReadStore, script_hash: &[u8]) -> Vec<HashPr
|
||||||
|
|
||||||
fn txids_by_funding_output(
|
fn txids_by_funding_output(
|
||||||
store: &dyn ReadStore,
|
store: &dyn ReadStore,
|
||||||
txn_id: &Sha256dHash,
|
txn_id: &Txid,
|
||||||
output_index: usize,
|
output_index: usize,
|
||||||
) -> Vec<HashPrefix> {
|
) -> Vec<HashPrefix> {
|
||||||
store
|
store
|
||||||
|
@ -215,7 +216,7 @@ impl Query {
|
||||||
let mut txns = vec![];
|
let mut txns = vec![];
|
||||||
for txid_prefix in prefixes {
|
for txid_prefix in prefixes {
|
||||||
for tx_row in txrows_by_prefix(store, txid_prefix) {
|
for tx_row in txrows_by_prefix(store, txid_prefix) {
|
||||||
let txid: Sha256dHash = deserialize(&tx_row.key.txid).unwrap();
|
let txid: Txid = deserialize(&tx_row.key.txid).unwrap();
|
||||||
let txn = self.load_txn(&txid, Some(tx_row.height))?;
|
let txn = self.load_txn(&txid, Some(tx_row.height))?;
|
||||||
txns.push(TxnHeight {
|
txns.push(TxnHeight {
|
||||||
txn,
|
txn,
|
||||||
|
@ -345,9 +346,9 @@ impl Query {
|
||||||
|
|
||||||
fn lookup_confirmed_blockhash(
|
fn lookup_confirmed_blockhash(
|
||||||
&self,
|
&self,
|
||||||
tx_hash: &Sha256dHash,
|
tx_hash: &Txid,
|
||||||
block_height: Option<u32>,
|
block_height: Option<u32>,
|
||||||
) -> Result<Option<Sha256dHash>> {
|
) -> Result<Option<BlockHash>> {
|
||||||
let blockhash = if self.tracker.read().unwrap().get_txn(&tx_hash).is_some() {
|
let blockhash = if self.tracker.read().unwrap().get_txn(&tx_hash).is_some() {
|
||||||
None // found in mempool (as unconfirmed transaction)
|
None // found in mempool (as unconfirmed transaction)
|
||||||
} else {
|
} else {
|
||||||
|
@ -371,7 +372,7 @@ impl Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal API for transaction retrieval
|
// Internal API for transaction retrieval
|
||||||
fn load_txn(&self, txid: &Sha256dHash, block_height: Option<u32>) -> Result<Transaction> {
|
fn load_txn(&self, txid: &Txid, block_height: Option<u32>) -> Result<Transaction> {
|
||||||
let _timer = self.duration.with_label_values(&["load_txn"]).start_timer();
|
let _timer = self.duration.with_label_values(&["load_txn"]).start_timer();
|
||||||
self.tx_cache.get_or_else(&txid, || {
|
self.tx_cache.get_or_else(&txid, || {
|
||||||
let blockhash = self.lookup_confirmed_blockhash(txid, block_height)?;
|
let blockhash = self.lookup_confirmed_blockhash(txid, block_height)?;
|
||||||
|
@ -385,7 +386,7 @@ impl Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API for transaction retrieval (for Electrum RPC)
|
// Public API for transaction retrieval (for Electrum RPC)
|
||||||
pub fn get_transaction(&self, tx_hash: &Sha256dHash, verbose: bool) -> Result<Value> {
|
pub fn get_transaction(&self, tx_hash: &Txid, verbose: bool) -> Result<Value> {
|
||||||
let _timer = self
|
let _timer = self
|
||||||
.duration
|
.duration
|
||||||
.with_label_values(&["get_transaction"])
|
.with_label_values(&["get_transaction"])
|
||||||
|
@ -415,9 +416,9 @@ impl Query {
|
||||||
|
|
||||||
pub fn get_merkle_proof(
|
pub fn get_merkle_proof(
|
||||||
&self,
|
&self,
|
||||||
tx_hash: &Sha256dHash,
|
tx_hash: &Txid,
|
||||||
height: usize,
|
height: usize,
|
||||||
) -> Result<(Vec<Sha256dHash>, usize)> {
|
) -> Result<(Vec<TxMerkleNode>, usize)> {
|
||||||
let header_entry = self
|
let header_entry = self
|
||||||
.app
|
.app
|
||||||
.index()
|
.index()
|
||||||
|
@ -428,7 +429,11 @@ impl Query {
|
||||||
.iter()
|
.iter()
|
||||||
.position(|txid| txid == tx_hash)
|
.position(|txid| txid == tx_hash)
|
||||||
.chain_err(|| format!("missing txid {}", tx_hash))?;
|
.chain_err(|| format!("missing txid {}", tx_hash))?;
|
||||||
let (branch, _root) = create_merkle_branch_and_root(txids, pos);
|
let tx_nodes: Vec<TxMerkleNode> = txids
|
||||||
|
.into_iter()
|
||||||
|
.map(|txid| TxMerkleNode::from_inner(txid.into_inner()))
|
||||||
|
.collect();
|
||||||
|
let (branch, _root) = create_merkle_branch_and_root(tx_nodes, pos);
|
||||||
Ok((branch, pos))
|
Ok((branch, pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,13 +456,17 @@ impl Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
let heights: Vec<usize> = (0..=cp_height).collect();
|
let heights: Vec<usize> = (0..=cp_height).collect();
|
||||||
let header_hashes: Vec<Sha256dHash> = self
|
let header_hashes: Vec<BlockHash> = self
|
||||||
.get_headers(&heights)
|
.get_headers(&heights)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|h| *h.hash())
|
.map(|h| *h.hash())
|
||||||
.collect();
|
.collect();
|
||||||
|
let merkle_nodes: Vec<Sha256dHash> = header_hashes
|
||||||
|
.iter()
|
||||||
|
.map(|block_hash| Sha256dHash::from_inner(block_hash.into_inner()))
|
||||||
|
.collect();
|
||||||
assert_eq!(header_hashes.len(), heights.len());
|
assert_eq!(header_hashes.len(), heights.len());
|
||||||
Ok(create_merkle_branch_and_root(header_hashes, height))
|
Ok(create_merkle_branch_and_root(merkle_nodes, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_id_from_pos(
|
pub fn get_id_from_pos(
|
||||||
|
@ -465,7 +474,7 @@ impl Query {
|
||||||
height: usize,
|
height: usize,
|
||||||
tx_pos: usize,
|
tx_pos: usize,
|
||||||
want_merkle: bool,
|
want_merkle: bool,
|
||||||
) -> Result<(Sha256dHash, Vec<Sha256dHash>)> {
|
) -> Result<(Txid, Vec<TxMerkleNode>)> {
|
||||||
let header_entry = self
|
let header_entry = self
|
||||||
.app
|
.app
|
||||||
.index()
|
.index()
|
||||||
|
@ -477,15 +486,20 @@ impl Query {
|
||||||
.get(tx_pos)
|
.get(tx_pos)
|
||||||
.chain_err(|| format!("No tx in position #{} in block #{}", tx_pos, height))?;
|
.chain_err(|| format!("No tx in position #{} in block #{}", tx_pos, height))?;
|
||||||
|
|
||||||
|
let tx_nodes = txids
|
||||||
|
.into_iter()
|
||||||
|
.map(|txid| TxMerkleNode::from_inner(txid.into_inner()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let branch = if want_merkle {
|
let branch = if want_merkle {
|
||||||
create_merkle_branch_and_root(txids, tx_pos).0
|
create_merkle_branch_and_root(tx_nodes, tx_pos).0
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
Ok((txid, branch))
|
Ok((txid, branch))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn broadcast(&self, txn: &Transaction) -> Result<Sha256dHash> {
|
pub fn broadcast(&self, txn: &Transaction) -> Result<Txid> {
|
||||||
self.app.daemon().broadcast(txn)
|
self.app.daemon().broadcast(txn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/rpc.rs
14
src/rpc.rs
|
@ -1,7 +1,7 @@
|
||||||
use bitcoin::blockdata::transaction::Transaction;
|
use bitcoin::blockdata::transaction::Transaction;
|
||||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||||
use bitcoin_hashes::hex::{FromHex, ToHex};
|
use bitcoin_hashes::hex::{FromHex, ToHex};
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
use bitcoin_hashes::{Hash, sha256d::Hash as Sha256dHash};
|
||||||
use error_chain::ChainedError;
|
use error_chain::ChainedError;
|
||||||
use hex;
|
use hex;
|
||||||
use serde_json::{from_str, Value};
|
use serde_json::{from_str, Value};
|
||||||
|
@ -21,10 +21,10 @@ const ELECTRS_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
const PROTOCOL_VERSION: &str = "1.4";
|
const PROTOCOL_VERSION: &str = "1.4";
|
||||||
|
|
||||||
// TODO: Sha256dHash should be a generic hash-container (since script hash is single SHA256)
|
// TODO: Sha256dHash should be a generic hash-container (since script hash is single SHA256)
|
||||||
fn hash_from_value(val: Option<&Value>) -> Result<Sha256dHash> {
|
fn hash_from_value<T: Hash>(val: Option<&Value>) -> Result<T> {
|
||||||
let script_hash = val.chain_err(|| "missing hash")?;
|
let script_hash = val.chain_err(|| "missing hash")?;
|
||||||
let script_hash = script_hash.as_str().chain_err(|| "non-string hash")?;
|
let script_hash = script_hash.as_str().chain_err(|| "non-string hash")?;
|
||||||
let script_hash = Sha256dHash::from_hex(script_hash).chain_err(|| "non-hex hash")?;
|
let script_hash = T::from_hex(script_hash).chain_err(|| "non-hex hash")?;
|
||||||
Ok(script_hash)
|
Ok(script_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blockchain_scripthash_subscribe(&mut self, params: &[Value]) -> Result<Value> {
|
fn blockchain_scripthash_subscribe(&mut self, params: &[Value]) -> Result<Value> {
|
||||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||||
let status = self.query.status(&script_hash[..])?;
|
let status = self.query.status(&script_hash[..])?;
|
||||||
let result = status.hash().map_or(Value::Null, |h| json!(hex::encode(h)));
|
let result = status.hash().map_or(Value::Null, |h| json!(hex::encode(h)));
|
||||||
self.status_hashes.insert(script_hash, result.clone());
|
self.status_hashes.insert(script_hash, result.clone());
|
||||||
|
@ -210,7 +210,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blockchain_scripthash_get_balance(&self, params: &[Value]) -> Result<Value> {
|
fn blockchain_scripthash_get_balance(&self, params: &[Value]) -> Result<Value> {
|
||||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||||
let status = self.query.status(&script_hash[..])?;
|
let status = self.query.status(&script_hash[..])?;
|
||||||
Ok(
|
Ok(
|
||||||
json!({ "confirmed": status.confirmed_balance(), "unconfirmed": status.mempool_balance() }),
|
json!({ "confirmed": status.confirmed_balance(), "unconfirmed": status.mempool_balance() }),
|
||||||
|
@ -218,7 +218,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blockchain_scripthash_get_history(&self, params: &[Value]) -> Result<Value> {
|
fn blockchain_scripthash_get_history(&self, params: &[Value]) -> Result<Value> {
|
||||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||||
let status = self.query.status(&script_hash[..])?;
|
let status = self.query.status(&script_hash[..])?;
|
||||||
Ok(json!(Value::Array(
|
Ok(json!(Value::Array(
|
||||||
status
|
status
|
||||||
|
@ -230,7 +230,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> {
|
fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> {
|
||||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||||
Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
|
Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
src/util.rs
34
src/util.rs
|
@ -1,6 +1,6 @@
|
||||||
use bitcoin::blockdata::block::BlockHeader;
|
use bitcoin::hash_types::BlockHash;
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
use bitcoin::util::hash::BitcoinHash;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
use bitcoin::blockdata::block::BlockHeader;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -11,7 +11,7 @@ use std::thread;
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
pub type Bytes = Vec<u8>;
|
pub type Bytes = Vec<u8>;
|
||||||
pub type HeaderMap = HashMap<Sha256dHash, BlockHeader>;
|
pub type HeaderMap = HashMap<BlockHash, BlockHeader>;
|
||||||
|
|
||||||
// TODO: consolidate serialization/deserialize code for bincode/bitcoin.
|
// TODO: consolidate serialization/deserialize code for bincode/bitcoin.
|
||||||
const HASH_LEN: usize = 32;
|
const HASH_LEN: usize = 32;
|
||||||
|
@ -33,12 +33,12 @@ pub fn full_hash(hash: &[u8]) -> FullHash {
|
||||||
#[derive(Eq, PartialEq, Clone)]
|
#[derive(Eq, PartialEq, Clone)]
|
||||||
pub struct HeaderEntry {
|
pub struct HeaderEntry {
|
||||||
height: usize,
|
height: usize,
|
||||||
hash: Sha256dHash,
|
hash: BlockHash,
|
||||||
header: BlockHeader,
|
header: BlockHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeaderEntry {
|
impl HeaderEntry {
|
||||||
pub fn hash(&self) -> &Sha256dHash {
|
pub fn hash(&self) -> &BlockHash {
|
||||||
&self.hash
|
&self.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl fmt::Debug for HeaderEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HashedHeader {
|
struct HashedHeader {
|
||||||
blockhash: Sha256dHash,
|
blockhash: BlockHash,
|
||||||
header: BlockHeader,
|
header: BlockHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ fn hash_headers(headers: Vec<BlockHeader>) -> Vec<HashedHeader> {
|
||||||
|
|
||||||
pub struct HeaderList {
|
pub struct HeaderList {
|
||||||
headers: Vec<HeaderEntry>,
|
headers: Vec<HeaderEntry>,
|
||||||
heights: HashMap<Sha256dHash, usize>,
|
heights: HashMap<BlockHash, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeaderList {
|
impl HeaderList {
|
||||||
|
@ -106,7 +106,7 @@ impl HeaderList {
|
||||||
Some(h) => h.header.prev_blockhash,
|
Some(h) => h.header.prev_blockhash,
|
||||||
None => return vec![], // hashed_headers is empty
|
None => return vec![], // hashed_headers is empty
|
||||||
};
|
};
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = BlockHash::default();
|
||||||
let new_height: usize = if prev_blockhash == null_hash {
|
let new_height: usize = if prev_blockhash == null_hash {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,8 +125,8 @@ impl HeaderList {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(&mut self, new_headers: Vec<HeaderEntry>, tip: Sha256dHash) {
|
pub fn apply(&mut self, new_headers: Vec<HeaderEntry>, tip: BlockHash) {
|
||||||
if tip == Sha256dHash::default() {
|
if tip == BlockHash::default() {
|
||||||
assert!(new_headers.is_empty());
|
assert!(new_headers.is_empty());
|
||||||
self.heights.clear();
|
self.heights.clear();
|
||||||
self.headers.clear();
|
self.headers.clear();
|
||||||
|
@ -150,7 +150,7 @@ impl HeaderList {
|
||||||
let expected_prev_blockhash = if height > 0 {
|
let expected_prev_blockhash = if height > 0 {
|
||||||
*self.headers[height - 1].hash()
|
*self.headers[height - 1].hash()
|
||||||
} else {
|
} else {
|
||||||
Sha256dHash::default()
|
BlockHash::default()
|
||||||
};
|
};
|
||||||
assert_eq!(entry.header().prev_blockhash, expected_prev_blockhash);
|
assert_eq!(entry.header().prev_blockhash, expected_prev_blockhash);
|
||||||
// First new header's height (may override existing headers)
|
// First new header's height (may override existing headers)
|
||||||
|
@ -182,7 +182,7 @@ impl HeaderList {
|
||||||
assert!(self.heights.contains_key(&tip));
|
assert!(self.heights.contains_key(&tip));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn header_by_blockhash(&self, blockhash: &Sha256dHash) -> Option<&HeaderEntry> {
|
pub fn header_by_blockhash(&self, blockhash: &BlockHash) -> Option<&HeaderEntry> {
|
||||||
let height = self.heights.get(blockhash)?;
|
let height = self.heights.get(blockhash)?;
|
||||||
let header = self.headers.get(*height)?;
|
let header = self.headers.get(*height)?;
|
||||||
if *blockhash == *header.hash() {
|
if *blockhash == *header.hash() {
|
||||||
|
@ -203,7 +203,7 @@ impl HeaderList {
|
||||||
self.headers.last() == other.headers.last()
|
self.headers.last() == other.headers.last()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tip(&self) -> Sha256dHash {
|
pub fn tip(&self) -> BlockHash {
|
||||||
self.headers.last().map(|h| *h.hash()).unwrap_or_default()
|
self.headers.last().map(|h| *h.hash()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,24 +285,24 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_headers() {
|
fn test_headers() {
|
||||||
use bitcoin::blockdata::block::BlockHeader;
|
use bitcoin::blockdata::block::BlockHeader;
|
||||||
|
use bitcoin::hash_types::{BlockHash, TxMerkleNode};
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
use bitcoin::util::hash::BitcoinHash;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
|
||||||
use bitcoin_hashes::Hash;
|
use bitcoin_hashes::Hash;
|
||||||
|
|
||||||
use super::HeaderList;
|
use super::HeaderList;
|
||||||
|
|
||||||
// Test an empty header list
|
// Test an empty header list
|
||||||
let null_hash = Sha256dHash::default();
|
let null_hash = BlockHash::default();
|
||||||
let mut header_list = HeaderList::empty();
|
let mut header_list = HeaderList::empty();
|
||||||
assert_eq!(header_list.tip(), null_hash);
|
assert_eq!(header_list.tip(), null_hash);
|
||||||
let ordered = header_list.order(vec![]);
|
let ordered = header_list.order(vec![]);
|
||||||
assert_eq!(ordered.len(), 0);
|
assert_eq!(ordered.len(), 0);
|
||||||
header_list.apply(vec![], null_hash);
|
header_list.apply(vec![], null_hash);
|
||||||
|
|
||||||
let merkle_root = Sha256dHash::hash(&[255]);
|
let merkle_root = TxMerkleNode::hash(&[255]);
|
||||||
let mut headers = vec![BlockHeader {
|
let mut headers = vec![BlockHeader {
|
||||||
version: 1,
|
version: 1,
|
||||||
prev_blockhash: Sha256dHash::default(),
|
prev_blockhash: BlockHash::default(),
|
||||||
merkle_root,
|
merkle_root,
|
||||||
time: 0,
|
time: 0,
|
||||||
bits: 0,
|
bits: 0,
|
||||||
|
|
Loading…
Add table
Reference in a new issue