cleanup: bump bitcoin and elements dependencies
This commit is contained in:
parent
3000bd13e7
commit
ea6954288c
310
Cargo.lock
generated
310
Cargo.lock
generated
@ -32,6 +32,12 @@ version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "ascii"
|
||||
version = "1.0.0"
|
||||
@ -49,15 +55,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -79,6 +76,16 @@ dependencies = [
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base58ck"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
|
||||
dependencies = [
|
||||
"bitcoin-internals",
|
||||
"bitcoin_hashes 0.14.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.10.1"
|
||||
@ -100,6 +107,12 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b"
|
||||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
@ -133,7 +146,7 @@ version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a41df6ad9642c5c15ae312dd3d074de38fd3eb7cc87ad4ce10f90292a83fe4d"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"bech32 0.8.1",
|
||||
"bitcoin_hashes 0.10.0",
|
||||
"secp256k1 0.20.3",
|
||||
"serde",
|
||||
@ -141,21 +154,52 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin"
|
||||
version = "0.28.0"
|
||||
version = "0.32.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b2a9a8e3c7544f5ce2b475f2f56580a3102b37e0ee001558ad4faedcf56cf4"
|
||||
checksum = "1e499f9fc0407f50fe98af744ab44fa67d409f76b6772e1689ec8485eb0c0f66"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"bitcoin_hashes 0.10.0",
|
||||
"secp256k1 0.22.1",
|
||||
"base58ck",
|
||||
"bech32 0.11.1",
|
||||
"bitcoin-internals",
|
||||
"bitcoin-io",
|
||||
"bitcoin-units",
|
||||
"bitcoin_hashes 0.14.1",
|
||||
"hex-conservative",
|
||||
"hex_lit",
|
||||
"secp256k1 0.29.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.7.6"
|
||||
name = "bitcoin-internals"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6"
|
||||
checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-io"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-private"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin-units"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2"
|
||||
dependencies = [
|
||||
"bitcoin-internals",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
@ -166,6 +210,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b"
|
||||
dependencies = [
|
||||
"bitcoin-io",
|
||||
"hex-conservative",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@ -292,15 +347,6 @@ dependencies = [
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.9"
|
||||
@ -337,7 +383,7 @@ version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
@ -418,16 +464,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "elements"
|
||||
version = "0.19.1"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c5ef61d480567b862631efcc22f704eeed7291dbf929ae008a8d5b7f5c4527"
|
||||
checksum = "9d562b364c5d2aced40b01b3f73fc968311787e6813957593d4ffa94cd8733e3"
|
||||
dependencies = [
|
||||
"bitcoin 0.28.0",
|
||||
"bitcoin_hashes 0.10.0",
|
||||
"bech32 0.11.1",
|
||||
"bitcoin 0.32.8",
|
||||
"secp256k1-zkp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slip21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -465,12 +510,6 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.21"
|
||||
@ -565,6 +604,21 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hex-conservative"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex_lit"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.6"
|
||||
@ -742,7 +796,7 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
@ -783,7 +837,7 @@ version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -793,7 +847,7 @@ dependencies = [
|
||||
"arrayref",
|
||||
"base64 0.13.0",
|
||||
"bincode",
|
||||
"bitcoin 0.28.0",
|
||||
"bitcoin 0.32.8",
|
||||
"bounded-vec-deque",
|
||||
"clap",
|
||||
"crossbeam-channel",
|
||||
@ -891,7 +945,7 @@ version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
@ -901,7 +955,7 @@ version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1017,6 +1071,15 @@ version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
@ -1058,108 +1121,32 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core 0.4.2",
|
||||
"rand_hc",
|
||||
"rand_isaac",
|
||||
"rand_jitter",
|
||||
"rand_os",
|
||||
"rand_pcg",
|
||||
"rand_xorshift",
|
||||
"winapi",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
dependencies = [
|
||||
"cloudabi",
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1168,7 +1155,7 @@ version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
@ -1186,15 +1173,6 @@ dependencies = [
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
@ -1323,13 +1301,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.22.1"
|
||||
version = "0.29.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26947345339603ae8395f68e2f3d85a6b0a8ddfe6315818e80b8504415099db0"
|
||||
checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
|
||||
dependencies = [
|
||||
"bitcoin_hashes 0.10.0",
|
||||
"bitcoin_hashes 0.14.1",
|
||||
"rand",
|
||||
"secp256k1-sys 0.5.0",
|
||||
"secp256k1-sys 0.10.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@ -1344,33 +1322,34 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1-sys"
|
||||
version = "0.5.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07b5b9d7322572e1f3aeed208668ce87789b3645dbb73082c5ce99a004103a35"
|
||||
checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1-zkp"
|
||||
version = "0.6.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c724fda6aae465ed9a39320202bc6164e0adb3cdf9bc16d5af4be7eebaba75e5"
|
||||
checksum = "52a44aed3002b5ae975f8624c5df3a949cfbf00479e18778b6058fcd213b76e3"
|
||||
dependencies = [
|
||||
"bitcoin-private",
|
||||
"rand",
|
||||
"secp256k1 0.22.1",
|
||||
"secp256k1 0.29.1",
|
||||
"secp256k1-zkp-sys",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1-zkp-sys"
|
||||
version = "0.6.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6f880412a627e79d3ce17355150ea1e0e76570efb7f0f70df51504cbe2582e3"
|
||||
checksum = "57f08b2d0b143a22e07f798ae4f0ab20d5590d7c68e0d090f2088a48a21d1654"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"secp256k1-sys 0.5.0",
|
||||
"secp256k1-sys 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1446,15 +1425,6 @@ version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||
|
||||
[[package]]
|
||||
name = "slip21"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acff9a1a0f4d902c8184bdde5338861dd95eb1397a12c4df78fb0b6ebeed4cbe"
|
||||
dependencies = [
|
||||
"bitcoin_hashes 0.7.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
@ -1915,6 +1885,26 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdea86ddd5568519879b8187e1cf04e24fce28f7fe046ceecbce472ff19a2572"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c15e1b46eff7c6c91195752e0eeed8ef040e391cdece7c25376957d5f15df22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.8+zstd.1.5.5"
|
||||
|
||||
@ -28,12 +28,12 @@ electrum-discovery = ["electrum-client"]
|
||||
arrayref = "0.3.6"
|
||||
base64 = "0.13.0"
|
||||
bincode-do-not-use-directly = { version = "1.3.1", package = "bincode" }
|
||||
bitcoin = { version = "0.28", features = [ "use-serde" ] }
|
||||
bitcoin = { version = "0.32.8", features = [ "serde" ] }
|
||||
bounded-vec-deque = "0.1.1"
|
||||
clap = "2.33.3"
|
||||
crossbeam-channel = "0.5.0"
|
||||
dirs = "4.0.0"
|
||||
elements = { version = "0.19.1", features = [ "serde-feature" ], optional = true }
|
||||
elements = { version = "0.26.1", features = [ "serde" ], optional = true }
|
||||
error-chain = "0.12.4"
|
||||
glob = "0.3"
|
||||
hex = "0.4.2"
|
||||
|
||||
@ -9,7 +9,7 @@ fn main() {
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bitcoin::blockdata::script::Script;
|
||||
use bitcoin::blockdata::script::ScriptBuf;
|
||||
use bitcoin::consensus::encode::deserialize;
|
||||
use electrs::{
|
||||
chain::Transaction,
|
||||
@ -62,7 +62,7 @@ fn main() {
|
||||
}
|
||||
|
||||
let tx: Transaction = deserialize(value).expect("failed to parse Transaction");
|
||||
let txid = tx.txid();
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
iter.next();
|
||||
|
||||
@ -71,7 +71,7 @@ fn main() {
|
||||
continue;
|
||||
}
|
||||
// skip coinbase txs
|
||||
if tx.is_coin_base() {
|
||||
if tx.is_coinbase() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -91,12 +91,26 @@ fn main() {
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let total_out: u64 = tx.output.iter().map(|out| out.value).sum();
|
||||
let small_out = tx.output.iter().map(|out| out.value).min().unwrap();
|
||||
let large_out = tx.output.iter().map(|out| out.value).max().unwrap();
|
||||
let total_out: u64 = tx.output.iter().map(|out| out.value.to_sat()).sum();
|
||||
let small_out = tx
|
||||
.output
|
||||
.iter()
|
||||
.map(|out| out.value.to_sat())
|
||||
.min()
|
||||
.unwrap();
|
||||
let large_out = tx
|
||||
.output
|
||||
.iter()
|
||||
.map(|out| out.value.to_sat())
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
let total_in: u64 = prevouts.values().map(|out| out.value).sum();
|
||||
let smallest_in = prevouts.values().map(|out| out.value).min().unwrap();
|
||||
let total_in: u64 = prevouts.values().map(|out| out.value.to_sat()).sum();
|
||||
let smallest_in = prevouts
|
||||
.values()
|
||||
.map(|out| out.value.to_sat())
|
||||
.min()
|
||||
.unwrap();
|
||||
|
||||
let fee = total_in - total_out;
|
||||
|
||||
@ -119,7 +133,7 @@ fn main() {
|
||||
|
||||
// test for sending back to one of the spent spks
|
||||
let has_reuse = {
|
||||
let prev_spks: HashSet<Script> = prevouts
|
||||
let prev_spks: HashSet<ScriptBuf> = prevouts
|
||||
.values()
|
||||
.map(|out| out.script_pubkey.clone())
|
||||
.collect();
|
||||
|
||||
73
src/chain.rs
73
src/chain.rs
@ -2,25 +2,64 @@ use std::str::FromStr;
|
||||
|
||||
#[cfg(not(feature = "liquid"))] // use regular Bitcoin data structures
|
||||
pub use bitcoin::{
|
||||
blockdata::{opcodes, script, witness::Witness},
|
||||
address,
|
||||
block::Header as BlockHeader,
|
||||
blockdata::{opcodes, script},
|
||||
consensus::deserialize,
|
||||
hashes,
|
||||
util::address,
|
||||
Block, BlockHash, BlockHeader, OutPoint, Script, Transaction, TxIn, TxOut, Txid,
|
||||
hashes, Block, BlockHash, OutPoint, ScriptBuf as Script, Transaction, TxIn, TxOut, Txid,
|
||||
Witness,
|
||||
};
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
pub use {
|
||||
crate::elements::asset,
|
||||
elements::{
|
||||
address, confidential, encode::deserialize, hashes, opcodes, script, Address, AssetId,
|
||||
Block, BlockHash, BlockHeader, OutPoint, Script, Transaction, TxIn, TxInWitness as Witness,
|
||||
TxOut, Txid,
|
||||
address, bitcoin::bech32::Hrp, confidential, encode::deserialize, hashes, opcodes, script,
|
||||
Address, AssetId, Block, BlockHash, BlockHeader, OutPoint, Script, Transaction, TxIn,
|
||||
TxInWitness as Witness, TxOut, Txid,
|
||||
},
|
||||
};
|
||||
|
||||
use bitcoin::blockdata::constants::genesis_block;
|
||||
pub use bitcoin::network::constants::Network as BNetwork;
|
||||
pub use bitcoin::Network as BNetwork;
|
||||
|
||||
// Extension trait for getting txid in a cross-compatible way
|
||||
pub trait TxidCompat {
|
||||
fn get_txid(&self) -> Txid;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
impl TxidCompat for Transaction {
|
||||
fn get_txid(&self) -> Txid {
|
||||
self.compute_txid()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
impl TxidCompat for Transaction {
|
||||
fn get_txid(&self) -> Txid {
|
||||
self.txid()
|
||||
}
|
||||
}
|
||||
|
||||
// Extension trait for getting block size in a cross-compatible way
|
||||
pub trait BlockSizeCompat {
|
||||
fn get_block_size(&self) -> usize;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
impl BlockSizeCompat for Block {
|
||||
fn get_block_size(&self) -> usize {
|
||||
self.total_size()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
impl BlockSizeCompat for Block {
|
||||
fn get_block_size(&self) -> usize {
|
||||
self.size()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
pub type Value = u64;
|
||||
@ -53,8 +92,8 @@ pub const LIQUID_TESTNET_PARAMS: address::AddressParams = address::AddressParams
|
||||
p2pkh_prefix: 36,
|
||||
p2sh_prefix: 19,
|
||||
blinded_prefix: 23,
|
||||
bech_hrp: "tex",
|
||||
blech_hrp: "tlq",
|
||||
bech_hrp: Hrp::parse_unchecked("tex"),
|
||||
blech_hrp: Hrp::parse_unchecked("tlq"),
|
||||
};
|
||||
|
||||
/// Magic for testnet4, 0x1c163f28 (from BIP94) with flipped endianness.
|
||||
@ -66,7 +105,10 @@ impl Network {
|
||||
pub fn magic(self) -> u32 {
|
||||
match self {
|
||||
Self::Testnet4 => TESTNET4_MAGIC,
|
||||
_ => BNetwork::from(self).magic(),
|
||||
_ => {
|
||||
let magic = BNetwork::from(self).magic();
|
||||
u32::from_le_bytes(magic.to_bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +220,10 @@ pub fn liquid_genesis_hash(network: Network) -> elements::BlockHash {
|
||||
"1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c379296888a206003"
|
||||
.parse()
|
||||
.unwrap();
|
||||
static ref ZERO_HASH: BlockHash =
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
.parse()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
match network {
|
||||
@ -185,7 +231,7 @@ pub fn liquid_genesis_hash(network: Network) -> elements::BlockHash {
|
||||
// The genesis block for liquid regtest chains varies based on the chain configuration.
|
||||
// This instead uses an all zeroed-out hash, which doesn't matter in practice because its
|
||||
// only used for Electrum server discovery, which isn't active on regtest.
|
||||
_ => Default::default(),
|
||||
_ => *ZERO_HASH,
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +267,7 @@ impl From<Network> for BNetwork {
|
||||
match network {
|
||||
Network::Bitcoin => BNetwork::Bitcoin,
|
||||
Network::Testnet => BNetwork::Testnet,
|
||||
Network::Testnet4 => BNetwork::Testnet,
|
||||
Network::Testnet4 => BNetwork::Testnet4,
|
||||
Network::Regtest => BNetwork::Regtest,
|
||||
Network::Signet => BNetwork::Signet,
|
||||
}
|
||||
@ -234,6 +280,7 @@ impl From<BNetwork> for Network {
|
||||
match network {
|
||||
BNetwork::Bitcoin => Network::Bitcoin,
|
||||
BNetwork::Testnet => Network::Testnet,
|
||||
BNetwork::Testnet4 => Network::Testnet4,
|
||||
BNetwork::Regtest => Network::Regtest,
|
||||
BNetwork::Signet => Network::Signet,
|
||||
}
|
||||
|
||||
@ -2,11 +2,12 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::io::{BufRead, BufReader, Lines, Write};
|
||||
use std::net::{SocketAddr, TcpStream};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use base64;
|
||||
use bitcoin::hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin::hashes::Hash;
|
||||
use glob;
|
||||
use hex;
|
||||
use itertools::Itertools;
|
||||
@ -27,14 +28,14 @@ use crate::errors::*;
|
||||
|
||||
fn parse_hash<T>(value: &Value) -> Result<T>
|
||||
where
|
||||
T: FromHex,
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: std::fmt::Debug,
|
||||
{
|
||||
T::from_hex(
|
||||
value
|
||||
.as_str()
|
||||
.chain_err(|| format!("non-string value: {}", value))?,
|
||||
)
|
||||
.chain_err(|| format!("non-hex value: {}", value))
|
||||
value
|
||||
.as_str()
|
||||
.chain_err(|| format!("non-string value: {}", value))?
|
||||
.parse::<T>()
|
||||
.map_err(|e| format!("failed to parse hash: {:?}", e).into())
|
||||
}
|
||||
|
||||
fn header_from_value(value: Value) -> Result<BlockHeader> {
|
||||
@ -547,7 +548,7 @@ impl Daemon {
|
||||
pub fn getblockheader(&self, blockhash: &BlockHash) -> Result<BlockHeader> {
|
||||
header_from_value(self.request(
|
||||
"getblockheader",
|
||||
json!([blockhash.to_hex(), /*verbose=*/ false]),
|
||||
json!([blockhash.to_string(), /*verbose=*/ false]),
|
||||
)?)
|
||||
}
|
||||
|
||||
@ -566,21 +567,22 @@ impl Daemon {
|
||||
}
|
||||
|
||||
pub fn getblock(&self, blockhash: &BlockHash) -> Result<Block> {
|
||||
let block = block_from_value(
|
||||
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ false]))?,
|
||||
)?;
|
||||
let block = block_from_value(self.request(
|
||||
"getblock",
|
||||
json!([blockhash.to_string(), /*verbose=*/ false]),
|
||||
)?)?;
|
||||
assert_eq!(block.block_hash(), *blockhash);
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
pub fn getblock_raw(&self, blockhash: &BlockHash, verbose: u32) -> Result<Value> {
|
||||
self.request("getblock", json!([blockhash.to_hex(), verbose]))
|
||||
self.request("getblock", json!([blockhash.to_string(), verbose]))
|
||||
}
|
||||
|
||||
pub fn getblocks(&self, blockhashes: &[BlockHash]) -> Result<Vec<Block>> {
|
||||
let params_list: Vec<Value> = blockhashes
|
||||
.iter()
|
||||
.map(|hash| json!([hash.to_hex(), /*verbose=*/ false]))
|
||||
.map(|hash| json!([hash.to_string(), /*verbose=*/ false]))
|
||||
.collect();
|
||||
let values = self.requests("getblock", ¶ms_list)?;
|
||||
let mut blocks = vec![];
|
||||
@ -593,7 +595,7 @@ impl Daemon {
|
||||
pub fn gettransactions(&self, txhashes: &[&Txid]) -> Result<Vec<Transaction>> {
|
||||
let params_list: Vec<Value> = txhashes
|
||||
.iter()
|
||||
.map(|txhash| json!([txhash.to_hex(), /*verbose=*/ false]))
|
||||
.map(|txhash| json!([txhash.to_string(), /*verbose=*/ false]))
|
||||
.collect();
|
||||
let values = self.retry_request_batch("getrawtransaction", ¶ms_list, 0.25)?;
|
||||
let mut txs = vec![];
|
||||
@ -612,14 +614,14 @@ impl Daemon {
|
||||
) -> Result<Value> {
|
||||
self.request(
|
||||
"getrawtransaction",
|
||||
json!([txid.to_hex(), verbose, blockhash]),
|
||||
json!([txid.to_string(), verbose, blockhash]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn getmempooltx(&self, txhash: &Txid) -> Result<Transaction> {
|
||||
let value = self.request(
|
||||
"getrawtransaction",
|
||||
json!([txhash.to_hex(), /*verbose=*/ false]),
|
||||
json!([txhash.to_string(), /*verbose=*/ false]),
|
||||
)?;
|
||||
tx_from_value(value)
|
||||
}
|
||||
@ -635,8 +637,10 @@ impl Daemon {
|
||||
|
||||
pub fn broadcast_raw(&self, txhex: &str) -> Result<Txid> {
|
||||
let txid = self.request("sendrawtransaction", json!([txhex]))?;
|
||||
Txid::from_hex(txid.as_str().chain_err(|| "non-string txid")?)
|
||||
.chain_err(|| "failed to parse txid")
|
||||
txid.as_str()
|
||||
.chain_err(|| "non-string txid")?
|
||||
.parse::<Txid>()
|
||||
.map_err(|e| format!("failed to parse txid: {:?}", e).into())
|
||||
}
|
||||
|
||||
pub fn test_mempool_accept(
|
||||
@ -707,7 +711,7 @@ impl Daemon {
|
||||
}
|
||||
|
||||
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_string()]))?;
|
||||
let tip_height = info
|
||||
.get("height")
|
||||
.expect("missing height")
|
||||
@ -723,7 +727,7 @@ impl Daemon {
|
||||
result.append(&mut headers);
|
||||
}
|
||||
|
||||
let mut blockhash = BlockHash::default();
|
||||
let mut blockhash = BlockHash::all_zeros();
|
||||
for header in &result {
|
||||
assert_eq!(header.prev_blockhash, blockhash);
|
||||
blockhash = header.block_hash();
|
||||
@ -749,7 +753,7 @@ impl Daemon {
|
||||
bestblockhash,
|
||||
);
|
||||
let mut new_headers = vec![];
|
||||
let null_hash = BlockHash::default();
|
||||
let null_hash = BlockHash::all_zeros();
|
||||
let mut blockhash = *bestblockhash;
|
||||
while blockhash != null_hash {
|
||||
if indexed_headers.header_by_blockhash(&blockhash).is_some() {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use bitcoin::hashes::sha256d;
|
||||
use bitcoin::hashes::Hash;
|
||||
pub use electrum_client::client::Client;
|
||||
pub use electrum_client::ServerFeaturesRes;
|
||||
@ -19,7 +20,9 @@ impl TryFrom<ServerFeaturesRes> for ServerFeatures {
|
||||
Ok(ServerFeatures {
|
||||
// electrum-client doesn't retain the hosts map data, but we already have it from the add_peer request
|
||||
hosts: HashMap::new(),
|
||||
genesis_hash: BlockHash::from_inner(features.genesis_hash),
|
||||
genesis_hash: BlockHash::from_raw_hash(sha256d::Hash::from_byte_array(
|
||||
features.genesis_hash,
|
||||
)),
|
||||
server_version: features.server_version,
|
||||
protocol_min: features
|
||||
.protocol_min
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||
|
||||
use bitcoin::hashes::{hex::FromHex, sha256, Hash};
|
||||
use bitcoin::hashes::{sha256, Hash};
|
||||
use elements::confidential::{Asset, Value};
|
||||
use elements::encode::{deserialize, serialize};
|
||||
use elements::secp256k1_zkp::ZERO_TWEAK;
|
||||
@ -17,13 +17,16 @@ use crate::util::{bincode_util, full_hash, Bytes, FullHash, TransactionStatus, T
|
||||
|
||||
lazy_static! {
|
||||
pub static ref NATIVE_ASSET_ID: AssetId =
|
||||
AssetId::from_hex("6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d")
|
||||
"6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d"
|
||||
.parse()
|
||||
.unwrap();
|
||||
pub static ref NATIVE_ASSET_ID_TESTNET: AssetId =
|
||||
AssetId::from_hex("144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49")
|
||||
"144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
|
||||
.parse()
|
||||
.unwrap();
|
||||
pub static ref NATIVE_ASSET_ID_REGTEST: AssetId =
|
||||
AssetId::from_hex("5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225")
|
||||
"5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225"
|
||||
.parse()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -93,7 +96,7 @@ impl IssuedAsset {
|
||||
let reissuance_token = parse_asset_id(&asset.reissuance_token);
|
||||
|
||||
let contract_hash = if issuance.asset_entropy != [0u8; 32] {
|
||||
Some(ContractHash::from_inner(issuance.asset_entropy))
|
||||
Some(ContractHash::from_byte_array(issuance.asset_entropy))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -258,7 +261,7 @@ fn index_tx_assets(
|
||||
value: pegout.value,
|
||||
}),
|
||||
));
|
||||
} else if txo.script_pubkey.is_provably_unspendable() && !txo.is_fee() {
|
||||
} else if txo.script_pubkey.is_op_return() && !txo.is_fee() {
|
||||
if let (Asset::Explicit(asset_id), Value::Explicit(value)) = (txo.asset, txo.value) {
|
||||
if value > 0 {
|
||||
history.push((
|
||||
@ -277,7 +280,7 @@ fn index_tx_assets(
|
||||
for (txi_index, txi) in tx.input.iter().enumerate() {
|
||||
if let Some(pegin) = get_pegin_data(txi, network) {
|
||||
history.push((
|
||||
pegin.asset.explicit().unwrap(),
|
||||
pegin.asset,
|
||||
TxHistoryInfo::Pegin(PeginInfo {
|
||||
txid,
|
||||
vin: txi_index as u32,
|
||||
@ -409,7 +412,7 @@ pub fn lookup_asset(
|
||||
}
|
||||
|
||||
pub fn get_issuance_entropy(txin: &TxIn) -> Result<sha256::Midstate> {
|
||||
if !txin.has_issuance {
|
||||
if !txin.has_issuance() {
|
||||
bail!("input has no issuance");
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use bitcoin::hashes::{hex::ToHex, Hash};
|
||||
use bitcoin::hashes::Hash;
|
||||
use elements::hex::ToHex;
|
||||
use elements::secp256k1_zkp::ZERO_TWEAK;
|
||||
use elements::{confidential::Value, encode::serialize, issuance::ContractHash, AssetId, TxIn};
|
||||
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
use bitcoin::hashes::hex::ToHex;
|
||||
use elements::hex::ToHex;
|
||||
use elements::{confidential::Asset, PeginData, PegoutData, TxIn, TxOut};
|
||||
|
||||
use crate::chain::{bitcoin_genesis_hash, BNetwork, Network};
|
||||
use crate::util::{FullHash, ScriptToAsm};
|
||||
use crate::util::FullHash;
|
||||
|
||||
pub fn get_pegin_data(txout: &TxIn, network: Network) -> Option<PeginData<'_>> {
|
||||
let pegged_asset_id = network.pegged_asset()?;
|
||||
txout
|
||||
.pegin_data()
|
||||
.filter(|pegin| pegin.asset == Asset::Explicit(*pegged_asset_id))
|
||||
txout.pegin_data().and_then(|pegin| {
|
||||
if pegin.asset == *pegged_asset_id {
|
||||
Some(pegin)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_pegout_data(
|
||||
@ -17,15 +21,20 @@ pub fn get_pegout_data(
|
||||
parent_network: BNetwork,
|
||||
) -> Option<PegoutData<'_>> {
|
||||
let pegged_asset_id = network.pegged_asset()?;
|
||||
txout.pegout_data().filter(|pegout| {
|
||||
pegout.asset == Asset::Explicit(*pegged_asset_id)
|
||||
txout.pegout_data().and_then(|pegout| {
|
||||
if pegout.asset == Asset::Explicit(*pegged_asset_id)
|
||||
&& pegout.genesis_hash
|
||||
== bitcoin_genesis_hash(match parent_network {
|
||||
BNetwork::Bitcoin => Network::Liquid,
|
||||
BNetwork::Testnet => Network::LiquidTestnet,
|
||||
BNetwork::Signet => return false,
|
||||
BNetwork::Testnet | BNetwork::Testnet4 => Network::LiquidTestnet,
|
||||
BNetwork::Signet => return None,
|
||||
BNetwork::Regtest => Network::LiquidRegtest,
|
||||
})
|
||||
{
|
||||
Some(pegout)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -33,7 +42,7 @@ pub fn get_pegout_data(
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct PegoutValue {
|
||||
pub genesis_hash: String,
|
||||
pub scriptpubkey: bitcoin::Script,
|
||||
pub scriptpubkey: bitcoin::ScriptBuf,
|
||||
pub scriptpubkey_asm: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub scriptpubkey_address: Option<String>,
|
||||
@ -44,12 +53,12 @@ impl PegoutValue {
|
||||
let pegoutdata = get_pegout_data(txout, network, parent_network)?;
|
||||
|
||||
// pending https://github.com/ElementsProject/rust-elements/pull/69 is merged
|
||||
let scriptpubkey = bitcoin::Script::from(pegoutdata.script_pubkey.into_bytes());
|
||||
let address = bitcoin::Address::from_script(&scriptpubkey, parent_network);
|
||||
let scriptpubkey = bitcoin::ScriptBuf::from(pegoutdata.script_pubkey.into_bytes());
|
||||
let address = bitcoin::Address::from_script(&scriptpubkey, parent_network).ok();
|
||||
|
||||
Some(PegoutValue {
|
||||
genesis_hash: pegoutdata.genesis_hash.to_hex(),
|
||||
scriptpubkey_asm: scriptpubkey.to_asm(),
|
||||
scriptpubkey_asm: scriptpubkey.to_asm_string(),
|
||||
scriptpubkey_address: address.map(|s| s.to_string()),
|
||||
scriptpubkey,
|
||||
})
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{cmp, fs, path, thread};
|
||||
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use bitcoin::hashes::hex::FromHex;
|
||||
use elements::AssetId;
|
||||
|
||||
use crate::errors::*;
|
||||
@ -70,7 +70,7 @@ impl AssetRegistry {
|
||||
continue;
|
||||
}
|
||||
|
||||
let asset_id = AssetId::from_hex(
|
||||
let asset_id = AssetId::from_str(
|
||||
path.file_stem()
|
||||
.unwrap() // cannot fail if extension() succeeded
|
||||
.to_str()
|
||||
|
||||
@ -11,7 +11,7 @@ use std::io::Cursor;
|
||||
use std::path::PathBuf;
|
||||
use std::thread;
|
||||
|
||||
use crate::chain::{Block, BlockHash};
|
||||
use crate::chain::{Block, BlockHash, BlockSizeCompat};
|
||||
use crate::daemon::Daemon;
|
||||
use crate::errors::*;
|
||||
use crate::util::{spawn_thread, HeaderEntry, SyncChannel};
|
||||
@ -82,7 +82,7 @@ pub fn bitcoind_sequential_fetcher(
|
||||
.zip(entries)
|
||||
.map(|(block, entry)| BlockEntry {
|
||||
entry: entry.clone(), // TODO: remove this clone()
|
||||
size: block.size() as u32,
|
||||
size: block.get_block_size() as u32,
|
||||
block,
|
||||
})
|
||||
.collect();
|
||||
@ -138,7 +138,7 @@ fn bitcoind_fetcher(
|
||||
.zip(entries)
|
||||
.map(|(block, entry)| BlockEntry {
|
||||
entry: entry.clone(), // TODO: remove this clone()
|
||||
size: block.size() as u32,
|
||||
size: block.get_block_size() as u32,
|
||||
block,
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -12,7 +12,7 @@ use std::ops::Bound::{Excluded, Unbounded};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::chain::{deserialize, Network, OutPoint, Transaction, TxOut, Txid};
|
||||
use crate::chain::{deserialize, Network, OutPoint, Transaction, TxOut, Txid, TxidCompat};
|
||||
use crate::config::Config;
|
||||
use crate::daemon::Daemon;
|
||||
use crate::errors::*;
|
||||
@ -481,7 +481,7 @@ impl Mempool {
|
||||
let mut txids = Vec::with_capacity(txs.len());
|
||||
// Phase 1: add to txstore
|
||||
for tx in txs {
|
||||
let txid = tx.txid();
|
||||
let txid = tx.get_txid();
|
||||
// Only push if it doesn't already exist.
|
||||
// This is important now that update doesn't lock during
|
||||
// the entire function body.
|
||||
@ -526,7 +526,10 @@ impl Mempool {
|
||||
fee: feeinfo.fee,
|
||||
vsize: feeinfo.vsize,
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
value: prevouts.values().map(|prevout| prevout.value).sum(),
|
||||
value: prevouts
|
||||
.values()
|
||||
.map(|prevout| prevout.value.to_sat())
|
||||
.sum(),
|
||||
});
|
||||
|
||||
self.feeinfo.insert(txid, feeinfo);
|
||||
@ -534,6 +537,10 @@ impl Mempool {
|
||||
// An iterator over (ScriptHash, TxHistoryInfo)
|
||||
let spending = prevouts.into_iter().map(|(input_index, prevout)| {
|
||||
let txi = tx.input.get(input_index as usize).unwrap();
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let value = prevout.value.to_sat();
|
||||
#[cfg(feature = "liquid")]
|
||||
let value = prevout.value;
|
||||
(
|
||||
compute_script_hash(&prevout.script_pubkey),
|
||||
TxHistoryInfo::Spending(SpendingInfo {
|
||||
@ -541,7 +548,7 @@ impl Mempool {
|
||||
vin: input_index,
|
||||
prev_txid: full_hash(&txi.previous_output.txid[..]),
|
||||
prev_vout: txi.previous_output.vout,
|
||||
value: prevout.value,
|
||||
value,
|
||||
}),
|
||||
)
|
||||
});
|
||||
@ -555,12 +562,16 @@ impl Mempool {
|
||||
.enumerate()
|
||||
.filter(|(_, txo)| is_spendable(txo) || config.index_unspendables)
|
||||
.map(|(index, txo)| {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let value = txo.value.to_sat();
|
||||
#[cfg(feature = "liquid")]
|
||||
let value = txo.value;
|
||||
(
|
||||
compute_script_hash(&txo.script_pubkey),
|
||||
TxHistoryInfo::Funding(FundingInfo {
|
||||
txid: txid_bytes,
|
||||
vout: index as u32,
|
||||
value: txo.value,
|
||||
value,
|
||||
}),
|
||||
)
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashMap};
|
||||
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::chain::{Network, OutPoint, Transaction, TxOut, Txid};
|
||||
use crate::chain::{Network, OutPoint, Transaction, TxOut, Txid, TxidCompat};
|
||||
use crate::config::Config;
|
||||
use crate::daemon::{Daemon, MempoolAcceptResult, SubmitPackageResult};
|
||||
use crate::errors::*;
|
||||
@ -161,7 +161,7 @@ impl Query {
|
||||
}
|
||||
|
||||
pub fn lookup_tx_spends(&self, tx: Transaction) -> Vec<Option<SpendingInput>> {
|
||||
let txid = tx.txid();
|
||||
let txid = tx.get_txid();
|
||||
|
||||
tx.output
|
||||
.par_iter()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
use bitcoin::util::merkleblock::MerkleBlock;
|
||||
use bitcoin::merkle_tree::MerkleBlock;
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
use bitcoin::VarInt;
|
||||
use itertools::Itertools;
|
||||
use rayon::prelude::*;
|
||||
@ -10,7 +11,7 @@ use sha2::{Digest, Sha256};
|
||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||
#[cfg(feature = "liquid")]
|
||||
use elements::{
|
||||
encode::{deserialize, serialize},
|
||||
encode::{deserialize, serialize, VarInt},
|
||||
AssetId,
|
||||
};
|
||||
|
||||
@ -20,7 +21,7 @@ use std::path::Path;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::chain::{
|
||||
BlockHash, BlockHeader, Network, OutPoint, Script, Transaction, TxOut, Txid, Value,
|
||||
BlockHash, BlockHeader, Network, OutPoint, Script, Transaction, TxOut, Txid, TxidCompat, Value,
|
||||
};
|
||||
use crate::config::Config;
|
||||
use crate::daemon::Daemon;
|
||||
@ -1233,7 +1234,7 @@ impl ChainQuery {
|
||||
let _timer = self.start_timer("lookup_txn");
|
||||
self.lookup_raw_txn(txid, blockhash).map(|rawtx| {
|
||||
let txn: Transaction = deserialize(&rawtx).expect("failed to parse Transaction");
|
||||
assert_eq!(*txid, txn.txid());
|
||||
assert_eq!(*txid, txn.get_txid());
|
||||
txn
|
||||
})
|
||||
}
|
||||
@ -1390,7 +1391,7 @@ fn add_blocks(block_entries: &[BlockEntry], iconfig: &IndexerConfig) -> Vec<DBRo
|
||||
.map(|b| {
|
||||
let mut rows = vec![];
|
||||
let blockhash = full_hash(&b.entry.hash()[..]);
|
||||
let txids: Vec<Txid> = b.block.txdata.iter().map(|tx| tx.txid()).collect();
|
||||
let txids: Vec<Txid> = b.block.txdata.iter().map(|tx| tx.get_txid()).collect();
|
||||
for tx in &b.block.txdata {
|
||||
add_transaction(tx, blockhash, &mut rows, iconfig);
|
||||
}
|
||||
@ -1420,7 +1421,7 @@ fn add_transaction(
|
||||
rows.push(TxRow::new(tx).into_row());
|
||||
}
|
||||
|
||||
let txid = full_hash(&tx.txid()[..]);
|
||||
let txid = full_hash(&tx.get_txid()[..]);
|
||||
for (txo_index, txo) in tx.output.iter().enumerate() {
|
||||
if is_spendable(txo) {
|
||||
rows.push(TxOutRow::new(&txid, txo_index, txo).into_row());
|
||||
@ -1552,7 +1553,7 @@ fn index_transaction(
|
||||
// H{funding-scripthash}{funding-height}{funding-block-pos}F{funding-txid:vout} → ""
|
||||
// persist "edges" for fast is-this-TXO-spent check
|
||||
// S{funding-txid:vout}{spending-txid:vin} → ""
|
||||
let txid = full_hash(&tx.txid()[..]);
|
||||
let txid = full_hash(&tx.get_txid()[..]);
|
||||
let script_callback = |script_hash| {
|
||||
if let Operation::DeleteBlocksWithHistory(tx) = op {
|
||||
tx.send(script_hash).expect("unbounded channel won't fail");
|
||||
@ -1560,6 +1561,10 @@ fn index_transaction(
|
||||
};
|
||||
for (txo_index, txo) in tx.output.iter().enumerate() {
|
||||
if is_spendable(txo) || iconfig.index_unspendables {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let value = txo.value.to_sat();
|
||||
#[cfg(feature = "liquid")]
|
||||
let value = txo.value;
|
||||
let history = TxHistoryRow::new(
|
||||
&txo.script_pubkey,
|
||||
confirmed_height,
|
||||
@ -1567,7 +1572,7 @@ fn index_transaction(
|
||||
TxHistoryInfo::Funding(FundingInfo {
|
||||
txid,
|
||||
vout: txo_index as u32,
|
||||
value: txo.value,
|
||||
value,
|
||||
}),
|
||||
);
|
||||
script_callback(history.key.hash);
|
||||
@ -1588,6 +1593,11 @@ fn index_transaction(
|
||||
.get(&txi.previous_output)
|
||||
.unwrap_or_else(|| panic!("missing previous txo {}", txi.previous_output));
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let prev_value = prev_txo.value.to_sat();
|
||||
#[cfg(feature = "liquid")]
|
||||
let prev_value = prev_txo.value;
|
||||
|
||||
let history = TxHistoryRow::new(
|
||||
&prev_txo.script_pubkey,
|
||||
confirmed_height,
|
||||
@ -1597,7 +1607,7 @@ fn index_transaction(
|
||||
vin: txi_index as u32,
|
||||
prev_txid: full_hash(&txi.previous_output.txid[..]),
|
||||
prev_vout: txi.previous_output.vout,
|
||||
value: prev_txo.value,
|
||||
value: prev_value,
|
||||
}),
|
||||
);
|
||||
script_callback(history.key.hash);
|
||||
@ -1664,7 +1674,7 @@ struct TxRow {
|
||||
|
||||
impl TxRow {
|
||||
fn new(txn: &Transaction) -> TxRow {
|
||||
let txid = full_hash(&txn.txid()[..]);
|
||||
let txid = full_hash(&txn.get_txid()[..]);
|
||||
TxRow {
|
||||
key: TxRowKey { code: b'T', txid },
|
||||
value: serialize(txn),
|
||||
@ -1697,7 +1707,7 @@ struct TxConfRow {
|
||||
|
||||
impl TxConfRow {
|
||||
fn new(txn: &Transaction, blockhash: FullHash) -> TxConfRow {
|
||||
let txid = full_hash(&txn.txid()[..]);
|
||||
let txid = full_hash(&txn.get_txid()[..]);
|
||||
TxConfRow {
|
||||
key: TxConfKey {
|
||||
code: b'C',
|
||||
|
||||
266
src/rest.rs
266
src/rest.rs
@ -1,4 +1,8 @@
|
||||
use crate::chain::{address, BlockHash, Network, OutPoint, Script, Transaction, TxIn, TxOut, Txid};
|
||||
#[cfg(feature = "liquid")]
|
||||
use crate::chain::address;
|
||||
use crate::chain::{
|
||||
BlockHash, Network, OutPoint, Script, Transaction, TxIn, TxOut, Txid, TxidCompat,
|
||||
};
|
||||
use crate::config::{Config, BITCOIND_SUBVER, VERSION_STRING};
|
||||
use crate::errors;
|
||||
use crate::metrics::Metrics;
|
||||
@ -6,15 +10,17 @@ use crate::new_index::{compute_script_hash, Query, SpendingInput, Utxo};
|
||||
use crate::util::{
|
||||
create_socket, electrum_merkle, extract_tx_prevouts, full_hash, get_innerscripts, get_tx_fee,
|
||||
has_prevout, is_coinbase, transaction_sigop_count, BlockHeaderMeta, BlockId, FullHash,
|
||||
ScriptToAddr, ScriptToAsm, TransactionStatus,
|
||||
ScriptToAddr, ScriptToAsm, SegwitDetection, TransactionStatus,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
use {bitcoin::consensus::encode, std::str::FromStr};
|
||||
use bitcoin::consensus::encode;
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitcoin::blockdata::opcodes;
|
||||
use bitcoin::hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin::hashes::Error as HashError;
|
||||
use bitcoin::hashes::Hash;
|
||||
use hex::{self, FromHexError};
|
||||
use hyper::{
|
||||
header::HeaderValue,
|
||||
@ -91,29 +97,30 @@ impl BlockValue {
|
||||
#[cfg_attr(feature = "liquid", allow(unused_variables))]
|
||||
fn new(blockhm: BlockHeaderMeta) -> Self {
|
||||
let header = blockhm.header_entry.header();
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let version = header.version.to_consensus() as u32;
|
||||
#[cfg(feature = "liquid")]
|
||||
let version = header.version;
|
||||
|
||||
BlockValue {
|
||||
id: header.block_hash().to_hex(),
|
||||
id: header.block_hash().to_string(),
|
||||
height: blockhm.header_entry.height() as u32,
|
||||
version: {
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
{
|
||||
header.version as u32
|
||||
}
|
||||
},
|
||||
version,
|
||||
timestamp: header.time,
|
||||
tx_count: blockhm.meta.tx_count,
|
||||
size: blockhm.meta.size,
|
||||
weight: blockhm.meta.weight,
|
||||
merkle_root: header.merkle_root.to_hex(),
|
||||
previousblockhash: if header.prev_blockhash != BlockHash::default() {
|
||||
Some(header.prev_blockhash.to_hex())
|
||||
merkle_root: header.merkle_root.to_string(),
|
||||
previousblockhash: if header.prev_blockhash != BlockHash::all_zeros() {
|
||||
Some(header.prev_blockhash.to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
mediantime: blockhm.mtp,
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
bits: header.bits,
|
||||
bits: header.bits.to_consensus(),
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
nonce: header.nonce,
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
@ -130,9 +137,9 @@ impl BlockValue {
|
||||
///
|
||||
/// https://github.com/bitcoin/bitcoin/blob/v25.0/src/rpc/blockchain.cpp#L75-L97
|
||||
#[cfg_attr(feature = "liquid", allow(dead_code))]
|
||||
fn difficulty_new(bh: &bitcoin::BlockHeader) -> f64 {
|
||||
let mut n_shift = (bh.bits >> 24) & 0xff;
|
||||
let mut d_diff = (0x0000ffff as f64) / ((bh.bits & 0x00ffffff) as f64);
|
||||
fn difficulty_new(bh: &bitcoin::block::Header) -> f64 {
|
||||
let mut n_shift = (bh.bits.to_consensus() >> 24) & 0xff;
|
||||
let mut d_diff = (0x0000ffff as f64) / ((bh.bits.to_consensus() & 0x00ffffff) as f64);
|
||||
|
||||
while n_shift < 29 {
|
||||
d_diff *= 256.0;
|
||||
@ -188,15 +195,30 @@ impl TransactionValue {
|
||||
|
||||
let fee = get_tx_fee(&tx, &prevouts, config.network_type);
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let size = tx.total_size() as u32;
|
||||
#[cfg(feature = "liquid")]
|
||||
let size = tx.size() as u32;
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let weight = tx.weight().to_wu() as u32;
|
||||
#[cfg(feature = "liquid")]
|
||||
let weight = tx.weight() as u32;
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let version = tx.version.0 as u32;
|
||||
#[cfg(feature = "liquid")]
|
||||
let version = tx.version;
|
||||
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
Ok(TransactionValue {
|
||||
txid: tx.txid(),
|
||||
version: tx.version as u32,
|
||||
locktime: tx.lock_time,
|
||||
txid: tx.get_txid(),
|
||||
version,
|
||||
locktime: tx.lock_time.to_consensus_u32(),
|
||||
vin: vins,
|
||||
vout: vouts,
|
||||
size: tx.size() as u32,
|
||||
weight: tx.weight() as u32,
|
||||
size,
|
||||
weight,
|
||||
sigops,
|
||||
fee,
|
||||
status: Some(TransactionStatus::from(blockid)),
|
||||
@ -261,7 +283,7 @@ impl TxInValue {
|
||||
.map(ScriptToAsm::to_asm),
|
||||
|
||||
is_coinbase,
|
||||
sequence: txin.sequence,
|
||||
sequence: txin.sequence.to_consensus_u32(),
|
||||
#[cfg(feature = "liquid")]
|
||||
is_pegin: txin.is_pegin,
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -312,7 +334,7 @@ struct TxOutValue {
|
||||
impl TxOutValue {
|
||||
fn new(txout: &TxOut, config: &Config) -> Self {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let value = txout.value;
|
||||
let value = txout.value.to_sat();
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
let value = txout.value.explicit();
|
||||
@ -324,7 +346,7 @@ impl TxOutValue {
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
let asset = match txout.asset {
|
||||
Asset::Explicit(value) => Some(value.to_hex()),
|
||||
Asset::Explicit(value) => Some(value.to_string()),
|
||||
_ => None,
|
||||
};
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -355,16 +377,14 @@ impl TxOutValue {
|
||||
"p2pkh"
|
||||
} else if script.is_p2sh() {
|
||||
"p2sh"
|
||||
} else if script.is_v0_p2wpkh() {
|
||||
} else if script.segwit_is_p2wpkh() {
|
||||
"v0_p2wpkh"
|
||||
} else if script.is_v0_p2wsh() {
|
||||
} else if script.segwit_is_p2wsh() {
|
||||
"v0_p2wsh"
|
||||
} else if is_v1_p2tr(script) {
|
||||
} else if script.segwit_is_p2tr() {
|
||||
"v1_p2tr"
|
||||
} else if is_anchor(script) {
|
||||
"anchor"
|
||||
} else if script.is_provably_unspendable() {
|
||||
"provably_unspendable"
|
||||
} else if is_bare_multisig(script) {
|
||||
"multisig"
|
||||
} else {
|
||||
@ -391,13 +411,9 @@ impl TxOutValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn is_v1_p2tr(script: &Script) -> bool {
|
||||
script.len() == 34
|
||||
&& script[0] == opcodes::all::OP_PUSHNUM_1.into_u8()
|
||||
&& script[1] == opcodes::all::OP_PUSHBYTES_32.into_u8()
|
||||
}
|
||||
fn is_bare_multisig(script: &Script) -> bool {
|
||||
let len = script.len();
|
||||
let bytes = script.as_bytes();
|
||||
// 1-of-1 multisig is 37 bytes
|
||||
// Max is 15 pubkeys
|
||||
// Min is 1
|
||||
@ -406,20 +422,21 @@ fn is_bare_multisig(script: &Script) -> bool {
|
||||
// OP_M ... OP_N OP_CHECKMULTISIG
|
||||
// is bare multisig
|
||||
len >= 37
|
||||
&& script[len - 1] == opcodes::all::OP_CHECKMULTISIG.into_u8()
|
||||
&& script[len - 2] >= opcodes::all::OP_PUSHNUM_1.into_u8()
|
||||
&& script[len - 2] <= opcodes::all::OP_PUSHNUM_15.into_u8()
|
||||
&& script[0] >= opcodes::all::OP_PUSHNUM_1.into_u8()
|
||||
&& script[0] <= script[len - 2]
|
||||
&& bytes[len - 1] == opcodes::all::OP_CHECKMULTISIG.to_u8()
|
||||
&& bytes[len - 2] >= opcodes::all::OP_PUSHNUM_1.to_u8()
|
||||
&& bytes[len - 2] <= opcodes::all::OP_PUSHNUM_15.to_u8()
|
||||
&& bytes[0] >= opcodes::all::OP_PUSHNUM_1.to_u8()
|
||||
&& bytes[0] <= bytes[len - 2]
|
||||
}
|
||||
|
||||
fn is_anchor(script: &Script) -> bool {
|
||||
let len = script.len();
|
||||
let bytes = script.as_bytes();
|
||||
let len = bytes.len();
|
||||
len == 4
|
||||
&& script[0] == opcodes::all::OP_PUSHNUM_1.into_u8()
|
||||
&& script[1] == opcodes::all::OP_PUSHBYTES_2.into_u8()
|
||||
&& script[2] == 0x4e
|
||||
&& script[3] == 0x73
|
||||
&& bytes[0] == opcodes::all::OP_PUSHNUM_1.to_u8()
|
||||
&& bytes[1] == opcodes::all::OP_PUSHBYTES_2.to_u8()
|
||||
&& bytes[2] == 0x4e
|
||||
&& bytes[3] == 0x73
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -485,7 +502,7 @@ impl From<Utxo> for UtxoValue {
|
||||
},
|
||||
#[cfg(feature = "liquid")]
|
||||
asset: match utxo.asset {
|
||||
Asset::Explicit(asset) => Some(asset.to_hex()),
|
||||
Asset::Explicit(asset) => Some(asset.to_string()),
|
||||
_ => None,
|
||||
},
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -495,7 +512,7 @@ impl From<Utxo> for UtxoValue {
|
||||
},
|
||||
#[cfg(feature = "liquid")]
|
||||
nonce: match utxo.nonce {
|
||||
Nonce::Explicit(nonce) => Some(nonce.to_hex()),
|
||||
Nonce::Explicit(nonce) => Some(hex::encode(nonce)),
|
||||
_ => None,
|
||||
},
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -742,7 +759,7 @@ fn handle_request(
|
||||
) {
|
||||
(&Method::GET, Some(&"blocks"), Some(&"tip"), Some(&"hash"), None, None) => http_message(
|
||||
StatusCode::OK,
|
||||
query.chain().best_hash().to_hex(),
|
||||
query.chain().best_hash().to_string(),
|
||||
TTL_SHORT,
|
||||
),
|
||||
|
||||
@ -763,10 +780,10 @@ fn handle_request(
|
||||
.header_by_height(height)
|
||||
.ok_or_else(|| HttpError::not_found("Block not found".to_string()))?;
|
||||
let ttl = ttl_by_depth(Some(height), query);
|
||||
http_message(StatusCode::OK, header.hash().to_hex(), ttl)
|
||||
http_message(StatusCode::OK, header.hash().to_string(), ttl)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), None, None, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let blockhm = query
|
||||
.chain()
|
||||
.get_block_with_meta(&hash)
|
||||
@ -775,13 +792,13 @@ fn handle_request(
|
||||
json_response(block_value, TTL_LONG)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"status"), None, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let status = query.chain().get_block_status(&hash);
|
||||
let ttl = ttl_by_depth(status.height, query);
|
||||
json_response(status, ttl)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"txids"), None, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let txids = query
|
||||
.chain()
|
||||
.get_block_txids(&hash)
|
||||
@ -789,7 +806,7 @@ fn handle_request(
|
||||
json_response(txids, TTL_LONG)
|
||||
}
|
||||
(&Method::GET, Some(&INTERNAL_PREFIX), Some(&"block"), Some(hash), Some(&"txs"), None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let block_id = query.chain().blockid_by_hash(&hash);
|
||||
let txs = query
|
||||
.chain()
|
||||
@ -803,7 +820,7 @@ fn handle_request(
|
||||
json_response(prepare_txs(txs, query, config), ttl)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"header"), None, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let header = query
|
||||
.chain()
|
||||
.get_block_header(&hash)
|
||||
@ -813,7 +830,7 @@ fn handle_request(
|
||||
http_message(StatusCode::OK, header_hex, TTL_LONG)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"raw"), None, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let raw = query
|
||||
.chain()
|
||||
.get_block_raw(&hash)
|
||||
@ -827,7 +844,7 @@ fn handle_request(
|
||||
.unwrap())
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"txid"), Some(index), None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let index: usize = index.parse()?;
|
||||
let txids = query
|
||||
.chain()
|
||||
@ -836,10 +853,10 @@ fn handle_request(
|
||||
if index >= txids.len() {
|
||||
bail!(HttpError::not_found("tx index out of range".to_string()));
|
||||
}
|
||||
http_message(StatusCode::OK, txids[index].to_hex(), TTL_LONG)
|
||||
http_message(StatusCode::OK, txids[index].to_string(), TTL_LONG)
|
||||
}
|
||||
(&Method::GET, Some(&"block"), Some(hash), Some(&"txs"), start_index, None) => {
|
||||
let hash = BlockHash::from_hex(hash)?;
|
||||
let hash = hash.parse::<BlockHash>()?;
|
||||
let txids = query
|
||||
.chain()
|
||||
.get_block_txids(&hash)
|
||||
@ -1105,7 +1122,7 @@ fn handle_request(
|
||||
last_seen_txid,
|
||||
) => {
|
||||
let script_hash = to_scripthash(script_type, script_str, config.network_type)?;
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
let max_txs = query_params
|
||||
.get("max_txs")
|
||||
.and_then(|s| s.parse::<usize>().ok())
|
||||
@ -1151,7 +1168,7 @@ fn handle_request(
|
||||
last_seen_txid,
|
||||
) => {
|
||||
let script_hash = to_scripthash(script_type, script_str, config.network_type)?;
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
let max_txs = cmp::min(
|
||||
config.rest_default_max_address_summary_txs,
|
||||
query_params
|
||||
@ -1232,7 +1249,7 @@ fn handle_request(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
let max_txs = cmp::min(
|
||||
config.rest_default_max_address_summary_txs,
|
||||
query_params
|
||||
@ -1332,7 +1349,7 @@ fn handle_request(
|
||||
json_response(results, TTL_SHORT)
|
||||
}
|
||||
(&Method::GET, Some(&"tx"), Some(hash), None, None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let tx = query
|
||||
.lookup_txn(&hash)
|
||||
.ok_or_else(|| HttpError::not_found("Transaction not found".to_string()))?;
|
||||
@ -1357,7 +1374,7 @@ fn handle_request(
|
||||
|
||||
match txid_strings
|
||||
.into_iter()
|
||||
.map(|txid| Txid::from_hex(&txid))
|
||||
.map(|txid| txid.parse::<Txid>())
|
||||
.collect::<Result<Vec<Txid>, _>>()
|
||||
{
|
||||
Ok(txids) => {
|
||||
@ -1376,7 +1393,7 @@ fn handle_request(
|
||||
}
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(out_type @ &"hex"), None, None)
|
||||
| (&Method::GET, Some(&"tx"), Some(hash), Some(out_type @ &"raw"), None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let rawtx = query
|
||||
.lookup_raw_txn(&hash)
|
||||
.ok_or_else(|| HttpError::not_found("Transaction not found".to_string()))?;
|
||||
@ -1396,20 +1413,20 @@ fn handle_request(
|
||||
.unwrap())
|
||||
}
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(&"status"), None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let status = query.get_tx_status(&hash);
|
||||
let ttl = ttl_by_depth(status.block_height, query);
|
||||
json_response(status, ttl)
|
||||
}
|
||||
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(&"merkle-proof"), None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let blockid = query.chain().tx_confirming_block(&hash).ok_or_else(|| {
|
||||
HttpError::not_found("Transaction not found or is unconfirmed".to_string())
|
||||
})?;
|
||||
let (merkle, pos) =
|
||||
electrum_merkle::get_tx_merkle_proof(query.chain(), &hash, &blockid.hash)?;
|
||||
let merkle: Vec<String> = merkle.into_iter().map(|txid| txid.to_hex()).collect();
|
||||
let merkle: Vec<String> = merkle.into_iter().map(|txid| txid.to_string()).collect();
|
||||
let ttl = ttl_by_depth(Some(blockid.height), query);
|
||||
json_response(
|
||||
json!({ "block_height": blockid.height, "merkle": merkle, "pos": pos }),
|
||||
@ -1418,7 +1435,7 @@ fn handle_request(
|
||||
}
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(&"merkleblock-proof"), None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
|
||||
let merkleblock = query.chain().get_merkleblock_proof(&hash).ok_or_else(|| {
|
||||
HttpError::not_found("Transaction not found or is unconfirmed".to_string())
|
||||
@ -1435,7 +1452,7 @@ fn handle_request(
|
||||
)
|
||||
}
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(&"outspend"), Some(index), None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let outpoint = OutPoint {
|
||||
txid: hash,
|
||||
vout: index.parse::<u32>()?,
|
||||
@ -1450,7 +1467,7 @@ fn handle_request(
|
||||
json_response(spend, ttl)
|
||||
}
|
||||
(&Method::GET, Some(&"tx"), Some(hash), Some(&"outspends"), None, None) => {
|
||||
let hash = Txid::from_hex(hash)?;
|
||||
let hash = hash.parse::<Txid>()?;
|
||||
let tx = query
|
||||
.lookup_txn(&hash)
|
||||
.ok_or_else(|| HttpError::not_found("Transaction not found".to_string()))?;
|
||||
@ -1477,7 +1494,7 @@ fn handle_request(
|
||||
let txid = query
|
||||
.broadcast_raw(&txhex)
|
||||
.map_err(|err| HttpError::from(err.description().to_string()))?;
|
||||
http_message(StatusCode::OK, txid.to_hex(), 0)
|
||||
http_message(StatusCode::OK, txid.to_string(), 0)
|
||||
}
|
||||
(&Method::POST, Some(&"txs"), Some(&"test"), None, None, None) => {
|
||||
let txhexes: Vec<String> =
|
||||
@ -1507,7 +1524,7 @@ fn handle_request(
|
||||
)))
|
||||
} else {
|
||||
// must be a valid hex string
|
||||
Vec::<u8>::from_hex(txhex)
|
||||
hex::decode(txhex)
|
||||
.map_err(|_| {
|
||||
HttpError::from(format!("Invalid transaction hex for item {}", index))
|
||||
})
|
||||
@ -1557,7 +1574,7 @@ fn handle_request(
|
||||
)))
|
||||
} else {
|
||||
// must be a valid hex string
|
||||
Vec::<u8>::from_hex(txhex)
|
||||
hex::decode(txhex)
|
||||
.map_err(|_| {
|
||||
HttpError::from(format!("Invalid transaction hex for item {}", index))
|
||||
})
|
||||
@ -1586,7 +1603,8 @@ fn handle_request(
|
||||
let spends: Vec<Vec<SpendingValue>> = txid_strings
|
||||
.into_iter()
|
||||
.map(|txid_str| {
|
||||
Txid::from_hex(txid_str)
|
||||
txid_str
|
||||
.parse::<Txid>()
|
||||
.ok()
|
||||
.and_then(|txid| query.lookup_txn(&txid))
|
||||
.map_or_else(Vec::new, |tx| {
|
||||
@ -1617,7 +1635,8 @@ fn handle_request(
|
||||
let spends: Vec<Vec<SpendingValue>> = txid_strings
|
||||
.into_iter()
|
||||
.map(|txid_str| {
|
||||
Txid::from_hex(&txid_str)
|
||||
txid_str
|
||||
.parse::<Txid>()
|
||||
.ok()
|
||||
.and_then(|txid| query.lookup_txn(&txid))
|
||||
.map_or_else(Vec::new, |tx| {
|
||||
@ -1653,7 +1672,7 @@ fn handle_request(
|
||||
let index_part = parts.next();
|
||||
|
||||
if let (Some(hash), Some(index)) = (hash_part, index_part) {
|
||||
if let (Ok(txid), Ok(vout)) = (Txid::from_hex(hash), index.parse::<u32>()) {
|
||||
if let (Ok(txid), Ok(vout)) = (hash.parse::<Txid>(), index.parse::<u32>()) {
|
||||
let outpoint = OutPoint { txid, vout };
|
||||
return query
|
||||
.lookup_spend(&outpoint)
|
||||
@ -1674,7 +1693,7 @@ fn handle_request(
|
||||
json_response(query.mempool().txids(), TTL_SHORT)
|
||||
}
|
||||
(&Method::GET, Some(&"mempool"), Some(&"txids"), Some(&"page"), last_seen_txid, None) => {
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
let max_txs = query_params
|
||||
.get("max_txs")
|
||||
.and_then(|s| s.parse::<usize>().ok())
|
||||
@ -1707,7 +1726,7 @@ fn handle_request(
|
||||
|
||||
match txid_strings
|
||||
.into_iter()
|
||||
.map(|txid| Txid::from_hex(&txid))
|
||||
.map(|txid| txid.parse::<Txid>())
|
||||
.collect::<Result<Vec<Txid>, _>>()
|
||||
{
|
||||
Ok(txids) => {
|
||||
@ -1732,7 +1751,7 @@ fn handle_request(
|
||||
last_seen_txid,
|
||||
None,
|
||||
) => {
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
let max_txs = query_params
|
||||
.get("max_txs")
|
||||
.and_then(|s| s.parse::<usize>().ok())
|
||||
@ -1784,7 +1803,7 @@ fn handle_request(
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
(&Method::GET, Some(&"asset"), Some(asset_str), None, None, None) => {
|
||||
let asset_id = AssetId::from_hex(asset_str)?;
|
||||
let asset_id = AssetId::from_str(asset_str)?;
|
||||
let asset_entry = query
|
||||
.lookup_asset(&asset_id)?
|
||||
.ok_or_else(|| HttpError::not_found("Asset id not found".to_string()))?;
|
||||
@ -1794,7 +1813,7 @@ fn handle_request(
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
(&Method::GET, Some(&"asset"), Some(asset_str), Some(&"txs"), None, None) => {
|
||||
let asset_id = AssetId::from_hex(asset_str)?;
|
||||
let asset_id = AssetId::from_str(asset_str)?;
|
||||
|
||||
let mut txs = vec![];
|
||||
|
||||
@ -1838,8 +1857,8 @@ fn handle_request(
|
||||
Some(&"chain"),
|
||||
last_seen_txid,
|
||||
) => {
|
||||
let asset_id = AssetId::from_hex(asset_str)?;
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| Txid::from_hex(txid).ok());
|
||||
let asset_id = AssetId::from_str(asset_str)?;
|
||||
let last_seen_txid = last_seen_txid.and_then(|txid| txid.parse::<Txid>().ok());
|
||||
|
||||
let mut txs = query
|
||||
.chain()
|
||||
@ -1873,7 +1892,7 @@ fn handle_request(
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
(&Method::GET, Some(&"asset"), Some(asset_str), Some(&"txs"), Some(&"mempool"), None) => {
|
||||
let asset_id = AssetId::from_hex(asset_str)?;
|
||||
let asset_id = AssetId::from_str(asset_str)?;
|
||||
|
||||
let txs = query
|
||||
.mempool()
|
||||
@ -1887,7 +1906,7 @@ fn handle_request(
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
(&Method::GET, Some(&"asset"), Some(asset_str), Some(&"supply"), param, None) => {
|
||||
let asset_id = AssetId::from_hex(asset_str)?;
|
||||
let asset_id = AssetId::from_str(asset_str)?;
|
||||
let asset_entry = query
|
||||
.lookup_asset(&asset_id)?
|
||||
.ok_or_else(|| HttpError::not_found("Asset id not found".to_string()))?;
|
||||
@ -2007,30 +2026,38 @@ fn to_scripthash(
|
||||
|
||||
fn address_to_scripthash(addr: &str, network: Network) -> Result<FullHash, HttpError> {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let addr = address::Address::from_str(addr)?;
|
||||
#[cfg(feature = "liquid")]
|
||||
let addr = address::Address::parse_with_params(addr, network.address_params())?;
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let is_expected_net = {
|
||||
let addr_network = Network::from(addr.network);
|
||||
|
||||
let addr = {
|
||||
use bitcoin::address::NetworkUnchecked;
|
||||
let unchecked: bitcoin::Address<NetworkUnchecked> = addr.parse()?;
|
||||
let bnetwork = bitcoin::Network::from(network);
|
||||
// Testnet, Regtest and Signet all share the same version bytes,
|
||||
// `addr_network` will be detected as Testnet for all of them.
|
||||
addr_network == network
|
||||
|| (addr_network == Network::Testnet
|
||||
&& matches!(
|
||||
network,
|
||||
Network::Regtest | Network::Signet | Network::Testnet4
|
||||
))
|
||||
// so we need to allow require_network to succeed for all testnet-family networks
|
||||
let testnet_family = [
|
||||
bitcoin::Network::Testnet,
|
||||
bitcoin::Network::Regtest,
|
||||
bitcoin::Network::Signet,
|
||||
bitcoin::Network::Testnet4,
|
||||
];
|
||||
if testnet_family.contains(&bnetwork) {
|
||||
// Try each testnet-family network
|
||||
testnet_family
|
||||
.iter()
|
||||
.find_map(|&net| unchecked.clone().require_network(net).ok())
|
||||
.ok_or_else(|| HttpError::from("Address on invalid network".to_string()))?
|
||||
} else {
|
||||
unchecked
|
||||
.require_network(bnetwork)
|
||||
.map_err(|_| HttpError::from("Address on invalid network".to_string()))?
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
let is_expected_net = addr.params == network.address_params();
|
||||
|
||||
if !is_expected_net {
|
||||
bail!(HttpError::from("Address on invalid network".to_string()))
|
||||
}
|
||||
let addr = {
|
||||
let addr = address::Address::parse_with_params(addr, network.address_params())?;
|
||||
if addr.params != network.address_params() {
|
||||
return Err(HttpError::from("Address on invalid network".to_string()));
|
||||
}
|
||||
addr
|
||||
};
|
||||
|
||||
Ok(compute_script_hash(&addr.script_pubkey()))
|
||||
}
|
||||
@ -2073,26 +2100,19 @@ impl From<ParseIntError> for HttpError {
|
||||
HttpError::from("Invalid number".to_string())
|
||||
}
|
||||
}
|
||||
impl From<HashError> for HttpError {
|
||||
fn from(_e: HashError) -> Self {
|
||||
//HttpError::from(e.description().to_string())
|
||||
HttpError::from("Invalid hash string".to_string())
|
||||
}
|
||||
}
|
||||
impl From<FromHexError> for HttpError {
|
||||
fn from(_e: FromHexError) -> Self {
|
||||
//HttpError::from(e.description().to_string())
|
||||
HttpError::from("Invalid hex string".to_string())
|
||||
}
|
||||
}
|
||||
impl From<bitcoin::hashes::hex::Error> for HttpError {
|
||||
fn from(_e: bitcoin::hashes::hex::Error) -> Self {
|
||||
//HttpError::from(e.description().to_string())
|
||||
HttpError::from("Invalid hex string".to_string())
|
||||
impl From<bitcoin::hashes::hex::HexToArrayError> for HttpError {
|
||||
fn from(_e: bitcoin::hashes::hex::HexToArrayError) -> Self {
|
||||
HttpError::from("Invalid hex hash".to_string())
|
||||
}
|
||||
}
|
||||
impl From<bitcoin::util::address::Error> for HttpError {
|
||||
fn from(_e: bitcoin::util::address::Error) -> Self {
|
||||
impl From<bitcoin::address::ParseError> for HttpError {
|
||||
fn from(_e: bitcoin::address::ParseError) -> Self {
|
||||
//HttpError::from(e.description().to_string())
|
||||
HttpError::from("Invalid Bitcoin address".to_string())
|
||||
}
|
||||
@ -2299,8 +2319,8 @@ mod tests {
|
||||
),
|
||||
];
|
||||
|
||||
let to_bh = |b| bitcoin::BlockHeader {
|
||||
version: 1,
|
||||
let to_bh = |b| bitcoin::block::Header {
|
||||
version: bitcoin::block::Version::ONE,
|
||||
prev_blockhash: "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
@ -2308,7 +2328,7 @@ mod tests {
|
||||
.parse()
|
||||
.unwrap(),
|
||||
time: 0,
|
||||
bits: b,
|
||||
bits: bitcoin::CompactTarget::from_consensus(b),
|
||||
nonce: 0,
|
||||
};
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use bitcoin::hashes::Hash;
|
||||
|
||||
use crate::chain::{BlockHash, BlockHeader};
|
||||
use crate::errors::*;
|
||||
use crate::new_index::BlockEntry;
|
||||
@ -73,7 +75,7 @@ impl HeaderList {
|
||||
HeaderList {
|
||||
headers: vec![],
|
||||
heights: HashMap::new(),
|
||||
tip: BlockHash::default(),
|
||||
tip: BlockHash::all_zeros(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +91,7 @@ impl HeaderList {
|
||||
|
||||
let mut blockhash = tip_hash;
|
||||
let mut headers_chain: Vec<BlockHeader> = vec![];
|
||||
let null_hash = BlockHash::default();
|
||||
let null_hash = BlockHash::all_zeros();
|
||||
|
||||
while blockhash != null_hash {
|
||||
let header = headers_map.remove(&blockhash).unwrap_or_else(|| {
|
||||
@ -136,7 +138,7 @@ impl HeaderList {
|
||||
Some(h) => h.header.prev_blockhash,
|
||||
None => return vec![], // hashed_headers is empty
|
||||
};
|
||||
let null_hash = BlockHash::default();
|
||||
let null_hash = BlockHash::all_zeros();
|
||||
let new_height: usize = if prev_blockhash == null_hash {
|
||||
0
|
||||
} else {
|
||||
@ -175,7 +177,7 @@ impl HeaderList {
|
||||
let expected_prev_blockhash = if height > 0 {
|
||||
*self.headers[height - 1].hash()
|
||||
} else {
|
||||
BlockHash::default()
|
||||
BlockHash::all_zeros()
|
||||
};
|
||||
assert_eq!(entry.header().prev_blockhash, expected_prev_blockhash);
|
||||
height
|
||||
@ -230,7 +232,10 @@ impl HeaderList {
|
||||
pub fn tip(&self) -> &BlockHash {
|
||||
assert_eq!(
|
||||
self.tip,
|
||||
self.headers.last().map(|h| *h.hash()).unwrap_or_default()
|
||||
self.headers
|
||||
.last()
|
||||
.map(|h| *h.hash())
|
||||
.unwrap_or(BlockHash::all_zeros())
|
||||
);
|
||||
&self.tip
|
||||
}
|
||||
@ -306,9 +311,13 @@ pub struct BlockHeaderMeta {
|
||||
|
||||
impl From<&BlockEntry> for BlockMeta {
|
||||
fn from(b: &BlockEntry) -> BlockMeta {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let weight = b.block.weight().to_wu() as u32;
|
||||
#[cfg(feature = "liquid")]
|
||||
let weight = b.block.weight() as u32;
|
||||
BlockMeta {
|
||||
tx_count: b.block.txdata.len() as u32,
|
||||
weight: b.block.weight() as u32,
|
||||
weight,
|
||||
size: b.size,
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,9 @@ pub struct TxFeeInfo {
|
||||
impl TxFeeInfo {
|
||||
pub fn new(tx: &Transaction, prevouts: &HashMap<u32, &TxOut>, network: Network) -> Self {
|
||||
let fee = get_tx_fee(tx, prevouts, network);
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let vsize = tx.weight().to_wu() / 4;
|
||||
#[cfg(feature = "liquid")]
|
||||
let vsize = tx.weight() / 4;
|
||||
|
||||
TxFeeInfo {
|
||||
@ -24,12 +27,15 @@ impl TxFeeInfo {
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
pub fn get_tx_fee(tx: &Transaction, prevouts: &HashMap<u32, &TxOut>, _network: Network) -> u64 {
|
||||
if tx.is_coin_base() {
|
||||
if tx.is_coinbase() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let total_in: u64 = prevouts.values().map(|prevout| prevout.value).sum();
|
||||
let total_out: u64 = tx.output.iter().map(|vout| vout.value).sum();
|
||||
let total_in: u64 = prevouts
|
||||
.values()
|
||||
.map(|prevout| prevout.value.to_sat())
|
||||
.sum();
|
||||
let total_out: u64 = tx.output.iter().map(|vout| vout.value.to_sat()).sum();
|
||||
total_in - total_out
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ pub mod fees;
|
||||
|
||||
pub use self::block::{BlockHeaderMeta, BlockId, BlockMeta, BlockStatus, HeaderEntry, HeaderList};
|
||||
pub use self::fees::get_tx_fee;
|
||||
pub use self::script::{get_innerscripts, ScriptToAddr, ScriptToAsm};
|
||||
pub use self::script::{get_innerscripts, ScriptToAddr, ScriptToAsm, SegwitDetection};
|
||||
pub use self::transaction::{
|
||||
extract_tx_prevouts, has_prevout, is_coinbase, is_spendable, serialize_outpoint,
|
||||
sigops::transaction_sigop_count, TransactionStatus, TxInput,
|
||||
@ -194,12 +194,12 @@ pub fn create_socket(addr: &SocketAddr) -> Socket {
|
||||
///
|
||||
/// Copied from https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/master/json/src/lib.rs
|
||||
pub mod serde_hex {
|
||||
use bitcoin::hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin::hashes::hex::FromHex;
|
||||
use serde::de::Error;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S: Serializer>(b: &[u8], s: S) -> Result<S::Ok, S::Error> {
|
||||
s.serialize_str(&b.to_hex())
|
||||
s.serialize_str(&hex::encode(b))
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
|
||||
@ -208,14 +208,14 @@ pub mod serde_hex {
|
||||
}
|
||||
|
||||
pub mod opt {
|
||||
use bitcoin::hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin::hashes::hex::FromHex;
|
||||
use serde::de::Error;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S: Serializer>(b: &Option<Vec<u8>>, s: S) -> Result<S::Ok, S::Error> {
|
||||
match *b {
|
||||
None => s.serialize_none(),
|
||||
Some(ref b) => s.serialize_str(&b.to_hex()),
|
||||
Some(ref b) => s.serialize_str(&hex::encode(b)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,52 @@ pub struct InnerScripts {
|
||||
pub witness_script: Option<Script>,
|
||||
}
|
||||
|
||||
// Extension trait for segwit script detection that works across bitcoin and elements
|
||||
pub trait SegwitDetection {
|
||||
fn segwit_is_p2wpkh(&self) -> bool;
|
||||
fn segwit_is_p2wsh(&self) -> bool;
|
||||
fn segwit_is_p2tr(&self) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
impl SegwitDetection for bitcoin::Script {
|
||||
fn segwit_is_p2wpkh(&self) -> bool {
|
||||
self.is_p2wpkh()
|
||||
}
|
||||
fn segwit_is_p2wsh(&self) -> bool {
|
||||
self.is_p2wsh()
|
||||
}
|
||||
fn segwit_is_p2tr(&self) -> bool {
|
||||
self.is_p2tr()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
impl SegwitDetection for bitcoin::ScriptBuf {
|
||||
fn segwit_is_p2wpkh(&self) -> bool {
|
||||
self.is_p2wpkh()
|
||||
}
|
||||
fn segwit_is_p2wsh(&self) -> bool {
|
||||
self.is_p2wsh()
|
||||
}
|
||||
fn segwit_is_p2tr(&self) -> bool {
|
||||
self.is_p2tr()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
impl SegwitDetection for elements::Script {
|
||||
fn segwit_is_p2wpkh(&self) -> bool {
|
||||
self.is_v0_p2wpkh()
|
||||
}
|
||||
fn segwit_is_p2wsh(&self) -> bool {
|
||||
self.is_v0_p2wsh()
|
||||
}
|
||||
fn segwit_is_p2tr(&self) -> bool {
|
||||
self.is_v1_p2tr()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ScriptToAsm: std::fmt::Debug {
|
||||
fn to_asm(&self) -> String {
|
||||
let asm = format!("{:?}", self);
|
||||
@ -16,6 +62,7 @@ pub trait ScriptToAsm: std::fmt::Debug {
|
||||
}
|
||||
}
|
||||
impl ScriptToAsm for bitcoin::Script {}
|
||||
impl ScriptToAsm for bitcoin::ScriptBuf {}
|
||||
#[cfg(feature = "liquid")]
|
||||
impl ScriptToAsm for elements::Script {}
|
||||
|
||||
@ -25,7 +72,9 @@ pub trait ScriptToAddr {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
impl ScriptToAddr for bitcoin::Script {
|
||||
fn to_address_str(&self, network: Network) -> Option<String> {
|
||||
bitcoin::Address::from_script(self, network.into()).map(|s| s.to_string())
|
||||
bitcoin::Address::from_script(self, bitcoin::Network::from(network))
|
||||
.ok()
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -41,7 +90,11 @@ pub fn get_innerscripts(txin: &TxIn, prevout: &TxOut) -> InnerScripts {
|
||||
// Wrapped redeemScript for P2SH spends
|
||||
let redeem_script = if prevout.script_pubkey.is_p2sh() {
|
||||
if let Some(Ok(PushBytes(redeemscript))) = txin.script_sig.instructions().last() {
|
||||
Some(Script::from(redeemscript.to_vec()))
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let bytes = redeemscript.as_bytes().to_vec();
|
||||
#[cfg(feature = "liquid")]
|
||||
let bytes = redeemscript.to_vec();
|
||||
Some(Script::from(bytes))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -50,9 +103,9 @@ pub fn get_innerscripts(txin: &TxIn, prevout: &TxOut) -> InnerScripts {
|
||||
};
|
||||
|
||||
// Wrapped witnessScript for P2WSH or P2SH-P2WSH spends
|
||||
let witness_script = if prevout.script_pubkey.is_v0_p2wsh()
|
||||
|| prevout.script_pubkey.is_v1_p2tr()
|
||||
|| redeem_script.as_ref().is_some_and(|s| s.is_v0_p2wsh())
|
||||
let witness_script = if prevout.script_pubkey.segwit_is_p2wsh()
|
||||
|| prevout.script_pubkey.segwit_is_p2tr()
|
||||
|| redeem_script.as_ref().is_some_and(|s| s.segwit_is_p2wsh())
|
||||
{
|
||||
let witness = &txin.witness;
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -64,7 +117,7 @@ pub fn get_innerscripts(txin: &TxIn, prevout: &TxOut) -> InnerScripts {
|
||||
#[cfg(feature = "liquid")]
|
||||
let wit_to_vec = Clone::clone;
|
||||
|
||||
let inner_script_slice = if prevout.script_pubkey.is_v1_p2tr() {
|
||||
let inner_script_slice = if prevout.script_pubkey.segwit_is_p2tr() {
|
||||
// Witness stack is potentially very large
|
||||
// so we avoid to_vec() or iter().collect() for performance
|
||||
let w_len = witness.len();
|
||||
|
||||
@ -4,15 +4,16 @@ use crate::util::BlockId;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
use bitcoin::hashes::hex::FromHex;
|
||||
|
||||
#[cfg(feature = "liquid")]
|
||||
lazy_static! {
|
||||
static ref REGTEST_INITIAL_ISSUANCE_PREVOUT: Txid =
|
||||
Txid::from_hex("50cdc410c9d0d61eeacc531f52d2c70af741da33af127c364e52ac1ee7c030a5").unwrap();
|
||||
"50cdc410c9d0d61eeacc531f52d2c70af741da33af127c364e52ac1ee7c030a5"
|
||||
.parse()
|
||||
.unwrap();
|
||||
static ref TESTNET_INITIAL_ISSUANCE_PREVOUT: Txid =
|
||||
Txid::from_hex("0c52d2526a5c9f00e9fb74afd15dd3caaf17c823159a514f929ae25193a43a52").unwrap();
|
||||
"0c52d2526a5c9f00e9fb74afd15dd3caaf17c823159a514f929ae25193a43a52"
|
||||
.parse()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -70,9 +71,9 @@ pub fn has_prevout(txin: &TxIn) -> bool {
|
||||
|
||||
pub fn is_spendable(txout: &TxOut) -> bool {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
return !txout.script_pubkey.is_provably_unspendable();
|
||||
return !txout.script_pubkey.is_op_return();
|
||||
#[cfg(feature = "liquid")]
|
||||
return !txout.is_fee() && !txout.script_pubkey.is_provably_unspendable();
|
||||
return !txout.is_fee() && !txout.script_pubkey.is_op_return();
|
||||
}
|
||||
|
||||
/// Extract the previous TxOuts of a Transaction's TxIns
|
||||
@ -117,14 +118,14 @@ where
|
||||
|
||||
pub(super) mod sigops {
|
||||
use crate::chain::{
|
||||
hashes::hex::FromHex,
|
||||
opcodes::{
|
||||
all::{OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, OP_CHECKSIG, OP_CHECKSIGVERIFY},
|
||||
All,
|
||||
},
|
||||
opcodes::all::{OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, OP_CHECKSIG, OP_CHECKSIGVERIFY},
|
||||
script::{self, Instruction},
|
||||
Transaction, TxOut, Witness,
|
||||
};
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
use bitcoin::opcodes::Opcode;
|
||||
#[cfg(feature = "liquid")]
|
||||
use elements::opcodes::All as Opcode;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Get sigop count for transaction. prevout_map must have all the prevouts.
|
||||
@ -136,7 +137,7 @@ pub(super) mod sigops {
|
||||
let mut prevouts = Vec::with_capacity(input_count);
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let is_coinbase_or_pegin = tx.is_coin_base();
|
||||
let is_coinbase_or_pegin = tx.is_coinbase();
|
||||
#[cfg(feature = "liquid")]
|
||||
let is_coinbase_or_pegin = tx.is_coinbase() || tx.input.iter().any(|input| input.is_pegin);
|
||||
|
||||
@ -154,9 +155,12 @@ pub(super) mod sigops {
|
||||
get_sigop_cost(tx, &prevouts, true, true)
|
||||
}
|
||||
|
||||
fn decode_pushnum(op: &All) -> Option<u8> {
|
||||
fn decode_pushnum(op: &Opcode) -> Option<u8> {
|
||||
// 81 = OP_1, 96 = OP_16
|
||||
// 81 -> 1, so... 81 - 80 -> 1
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let self_u8 = op.to_u8();
|
||||
#[cfg(feature = "liquid")]
|
||||
let self_u8 = op.into_u8();
|
||||
match self_u8 {
|
||||
81..=96 => Some(self_u8 - 80),
|
||||
@ -216,7 +220,7 @@ pub(super) mod sigops {
|
||||
|
||||
fn get_p2sh_sigop_count(tx: &Transaction, previous_outputs: &[&TxOut]) -> usize {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
if tx.is_coin_base() {
|
||||
if tx.is_coinbase() {
|
||||
return 0;
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -229,9 +233,14 @@ pub(super) mod sigops {
|
||||
if let Some(Ok(script::Instruction::PushBytes(redeem))) =
|
||||
input.script_sig.instructions().last()
|
||||
{
|
||||
let script =
|
||||
script::Script::from_byte_iter(redeem.iter().map(|v| Ok(*v))).unwrap(); // I only return Ok, so it won't error
|
||||
n += count_sigops(&script, true);
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
let script = script::Script::from_bytes(redeem.as_bytes());
|
||||
#[cfg(feature = "liquid")]
|
||||
let script = script::Script::from(redeem.to_vec());
|
||||
#[allow(clippy::needless_borrow)]
|
||||
{
|
||||
n += count_sigops(&script, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -256,6 +265,9 @@ pub(super) mod sigops {
|
||||
#[inline]
|
||||
fn last_pushdata(script: &script::Script) -> Option<&[u8]> {
|
||||
match script.instructions().last() {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
Some(Ok(Instruction::PushBytes(bytes))) => Some(bytes.as_bytes()),
|
||||
#[cfg(feature = "liquid")]
|
||||
Some(Ok(Instruction::PushBytes(bytes))) => Some(bytes),
|
||||
_ => None,
|
||||
}
|
||||
@ -269,20 +281,36 @@ pub(super) mod sigops {
|
||||
) -> usize {
|
||||
let mut n = 0;
|
||||
|
||||
let script = if prevout.script_pubkey.is_witness_program() {
|
||||
prevout.script_pubkey.clone()
|
||||
let script_owned;
|
||||
let script: &script::Script = if prevout.script_pubkey.is_witness_program() {
|
||||
&prevout.script_pubkey
|
||||
} else if prevout.script_pubkey.is_p2sh()
|
||||
&& is_push_only(script_sig)
|
||||
&& !script_sig.is_empty()
|
||||
{
|
||||
script::Script::from_byte_iter(
|
||||
last_pushdata(script_sig).unwrap().iter().map(|v| Ok(*v)),
|
||||
)
|
||||
.unwrap()
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
{
|
||||
script_owned =
|
||||
script::ScriptBuf::from(last_pushdata(script_sig).unwrap().to_vec());
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
{
|
||||
script_owned =
|
||||
script::Script::from(last_pushdata(script_sig).unwrap().to_vec());
|
||||
}
|
||||
&script_owned
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
if script.is_p2wsh() {
|
||||
let bytes = script.as_bytes();
|
||||
n += sig_ops(witness, bytes[0], &bytes[2..]);
|
||||
} else if script.is_p2wpkh() {
|
||||
n += 1;
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
if script.is_v0_p2wsh() {
|
||||
let bytes = script.as_bytes();
|
||||
n += sig_ops(witness, bytes[0], &bytes[2..]);
|
||||
@ -307,7 +335,7 @@ pub(super) mod sigops {
|
||||
) -> Result<usize, script::Error> {
|
||||
let mut n_sigop_cost = get_legacy_sigop_count(tx) * 4;
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
if tx.is_coin_base() {
|
||||
if tx.is_coinbase() {
|
||||
return Ok(n_sigop_cost);
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
@ -333,6 +361,7 @@ pub(super) mod sigops {
|
||||
/// Get sigops for the Witness
|
||||
///
|
||||
/// witness_version is the raw opcode. OP_0 is 0, OP_1 is 81, etc.
|
||||
#[allow(clippy::redundant_closure)]
|
||||
fn sig_ops(witness: &Witness, witness_version: u8, witness_program: &[u8]) -> usize {
|
||||
#[cfg(feature = "liquid")]
|
||||
let last_witness = witness.script_witness.last();
|
||||
@ -340,12 +369,23 @@ pub(super) mod sigops {
|
||||
let last_witness = witness.last();
|
||||
match (witness_version, witness_program.len()) {
|
||||
(0, 20) => 1,
|
||||
(0, 32) => last_witness
|
||||
.map(|sl| sl.iter().map(|v| Ok(*v)))
|
||||
.map(script::Script::from_byte_iter)
|
||||
// I only return Ok 2 lines up, so there is no way to error
|
||||
.map(|s| count_sigops(&s.unwrap(), true))
|
||||
.unwrap_or_default(),
|
||||
(0, 32) => {
|
||||
#[cfg(not(feature = "liquid"))]
|
||||
{
|
||||
#[allow(clippy::needless_borrow)]
|
||||
last_witness
|
||||
.map(|sl| script::Script::from_bytes(sl))
|
||||
.map(|s| count_sigops(s, true))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
#[cfg(feature = "liquid")]
|
||||
{
|
||||
last_witness
|
||||
.map(|sl| script::Script::from(sl.clone()))
|
||||
.map(|s| count_sigops(&s, true))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user