commit 4e1f47bcc56639427b99de6bff49830ee586b63d
parent 68bbc03b5ca437704281ba69808325ff2f3c9fb1
Author: Antoine A <>
Date: Fri, 12 Nov 2021 10:55:17 +0100
Clean code and start benchmarking
Diffstat:
| M | Cargo.lock | | | 496 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
| M | Cargo.toml | | | 10 | ++++++++-- |
| A | benches/metadata.rs | | | 27 | +++++++++++++++++++++++++++ |
| A | src/lib.rs | | | 178 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/main.rs | | | 195 | ++++++++++++++----------------------------------------------------------------- |
5 files changed, 657 insertions(+), 249 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -32,6 +32,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38de00daab4eac7d753e97697066238d67ce9d7e2d823ab4f72fe14af29f3f33"
[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -113,19 +124,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
-name = "block-buffer"
-version = "0.9.0"
+name = "bs58"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+
+[[package]]
+name = "bstr"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
- "generic-array",
+ "lazy_static",
+ "memchr",
+ "regex-automata",
+ "serde",
]
[[package]]
-name = "bs58"
-version = "0.4.0"
+name = "bumpalo"
+version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
@@ -134,10 +154,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
+name = "cast"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
+dependencies = [
+ "rustc_version",
+]
+
+[[package]]
name = "cc"
-version = "1.0.71"
+version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
+checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
@@ -146,10 +175,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
-name = "cfg_aliases"
-version = "0.1.1"
+name = "clap"
+version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "bitflags",
+ "textwrap",
+ "unicode-width",
+]
[[package]]
name = "clipboard-win"
@@ -163,12 +197,105 @@ dependencies = [
]
[[package]]
-name = "cpufeatures"
-version = "0.2.1"
+name = "criterion"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
+checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [
- "libc",
+ "atty",
+ "cast",
+ "clap",
+ "criterion-plot",
+ "csv",
+ "itertools",
+ "lazy_static",
+ "num-traits",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_cbor",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
+dependencies = [
+ "cast",
+ "itertools",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
+dependencies = [
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "csv"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
+dependencies = [
+ "bstr",
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
]
[[package]]
@@ -179,11 +306,10 @@ dependencies = [
"bitcoin-bech32",
"bitcoincore-rpc",
"bs58",
+ "criterion",
"digest",
"fastrand",
"rustyline",
- "sha2",
- "static_init",
]
[[package]]
@@ -217,6 +343,12 @@ dependencies = [
]
[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -274,6 +406,12 @@ dependencies = [
]
[[package]]
+name = "half"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+
+[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -283,6 +421,15 @@ dependencies = [
]
[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -292,12 +439,30 @@ dependencies = [
]
[[package]]
+name = "itertools"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
+dependencies = [
+ "either",
+]
+
+[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
+name = "js-sys"
+version = "0.3.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
name = "jsonrpc"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -310,19 +475,16 @@ dependencies = [
]
[[package]]
-name = "libc"
-version = "0.2.107"
+name = "lazy_static"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
-name = "lock_api"
-version = "0.4.5"
+name = "libc"
+version = "0.2.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
-dependencies = [
- "scopeguard",
-]
+checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
[[package]]
name = "log"
@@ -371,34 +533,56 @@ dependencies = [
]
[[package]]
-name = "opaque-debug"
-version = "0.3.0"
+name = "num-traits"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
[[package]]
-name = "parking_lot"
-version = "0.11.2"
+name = "num_cpus"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core",
+ "hermit-abi",
+ "libc",
]
[[package]]
-name = "parking_lot_core"
-version = "0.8.5"
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
+[[package]]
+name = "plotters"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
dependencies = [
- "cfg-if",
- "instant",
- "libc",
- "redox_syscall",
- "smallvec",
- "winapi",
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
+dependencies = [
+ "plotters-backend",
]
[[package]]
@@ -430,6 +614,31 @@ dependencies = [
]
[[package]]
+name = "rayon"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -449,6 +658,36 @@ dependencies = [
]
[[package]]
+name = "regex"
+version = "1.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+dependencies = [
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
name = "rustyline"
version = "9.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -479,6 +718,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -504,6 +752,12 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
+
+[[package]]
name = "serde"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -513,6 +767,16 @@ dependencies = [
]
[[package]]
+name = "serde_cbor"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
+dependencies = [
+ "half",
+ "serde",
+]
+
+[[package]]
name = "serde_derive"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -535,67 +799,45 @@ dependencies = [
]
[[package]]
-name = "sha2"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
-dependencies = [
- "block-buffer",
- "cfg-if",
- "cpufeatures",
- "digest",
- "opaque-debug",
-]
-
-[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
-name = "static_init"
-version = "1.0.1"
+name = "str-buf"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a12a91dc56a0b47b48a3150157803b02cf82aa4c15ed499cb9b7ee0ff39941b1"
-dependencies = [
- "bitflags",
- "cfg_aliases",
- "libc",
- "parking_lot",
- "parking_lot_core",
- "static_init_macro",
- "winapi",
-]
+checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
[[package]]
-name = "static_init_macro"
-version = "1.0.1"
+name = "syn"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b3fb6e118f42ea83548bb2194a79f5cbc8866fc38d87f6548139a7fac10e732"
+checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
dependencies = [
- "cfg_aliases",
- "memchr",
"proc-macro2",
"quote",
- "syn",
+ "unicode-xid",
]
[[package]]
-name = "str-buf"
-version = "1.0.5"
+name = "textwrap"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
[[package]]
-name = "syn"
-version = "1.0.81"
+name = "tinytemplate"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
+ "serde",
+ "serde_json",
]
[[package]]
@@ -635,12 +877,87 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
+name = "wasm-bindgen"
+version = "0.2.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
+dependencies = [
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
+
+[[package]]
+name = "web-sys"
+version = "0.3.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -657,6 +974,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
@@ -7,12 +7,18 @@ edition = "2021"
[dependencies]
bitcoincore-rpc = "0.14.0"
-sha2 = "0.9.8"
bs58 = "0.4.0"
fastrand = "1.5.0"
digest = "0.9.0"
argh = "0.1.6"
rustyline = "9.0.0"
bitcoin-bech32 = "0.12.1"
-static_init = "1.0.1"
+
+[dev-dependencies]
+# statistics-driven micro-benchmarks
+criterion = "0.3.5"
+
+[[bench]]
+name = "metadata"
+harness = false
diff --git a/benches/metadata.rs b/benches/metadata.rs
@@ -0,0 +1,27 @@
+use bitcoin_bech32::constants::Network;
+use criterion::{criterion_group, criterion_main, Criterion};
+use depolymerization::{
+ decode_segwit_msg, encode_segwit_msg,
+ utils::{rand_addresses, rand_key},
+};
+
+fn criterion_benchmark(c: &mut Criterion) {
+ let mut group = c.benchmark_group("SegWit addresses");
+ group.bench_function("encode", |b| {
+ b.iter_batched(
+ rand_key,
+ |key| encode_segwit_msg(Network::Bitcoin, &key),
+ criterion::BatchSize::SmallInput,
+ );
+ });
+ group.bench_function("decode", |b| {
+ b.iter_batched(
+ || rand_addresses(&rand_key()),
+ |addrs| decode_segwit_msg(&addrs),
+ criterion::BatchSize::SmallInput,
+ );
+ });
+}
+
+criterion_group!(benches, criterion_benchmark);
+criterion_main!(benches);
diff --git a/src/lib.rs b/src/lib.rs
@@ -0,0 +1,178 @@
+use std::{collections::BTreeMap, iter::repeat_with};
+
+use bitcoin_bech32::{constants::Network, u5, WitnessProgram};
+use bitcoincore_rpc::bitcoin::Amount;
+
+pub fn segwit_min_amount() -> Amount {
+ // https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp
+ return Amount::from_sat(294);
+}
+
+fn encode_segwit_address(
+ network: Network,
+ is_first: bool,
+ magic_id: &[u8; 4],
+ key_half: &[u8; 16],
+) -> String {
+ // Combine magic_it and the key half
+ let mut buf = vec![0u8; 20];
+ buf[..4].copy_from_slice(magic_id);
+ buf[4..].copy_from_slice(key_half);
+ // Toggle first bit for ordering
+ if is_first {
+ buf[0] &= 0b0111_1111 // Unset first bit
+ } else {
+ buf[0] |= 0b1000_0000 // Set first bit
+ }
+ // Encode into an fake segwit address
+ WitnessProgram::new(u5::try_from_u8(0).unwrap(), buf, network)
+ .unwrap()
+ .to_address()
+}
+
+pub fn encode_segwit_msg(network: Network, msg: &[u8; 32]) -> [String; 2] {
+ // Generate a random magic identifier
+ let mut magic_id = [0; 4];
+ // TODO use secure os based random
+ magic_id.fill_with(|| fastrand::u8(..));
+ // Split key in half;
+ let mut split = ([0; 16], [0; 16]);
+ split.0.copy_from_slice(&msg[..16]);
+ split.1.copy_from_slice(&msg[16..]);
+ [
+ encode_segwit_address(network, true, &magic_id, &split.0),
+ encode_segwit_address(network, false, &magic_id, &split.1),
+ ]
+}
+
+#[derive(Debug, Clone)]
+pub enum DecodeError {
+ MissingSeqWitAddress,
+ MagicIdCollision,
+}
+
+pub fn decode_segwit_msg(segwit_addrs: &[impl AsRef<str>]) -> Result<[u8; 32], DecodeError> {
+ if segwit_addrs.len() < 2 {
+ return Err(DecodeError::MissingSeqWitAddress);
+ }
+
+ let decoded: Vec<[u8; 20]> = segwit_addrs
+ .into_iter()
+ .filter_map(|addr| {
+ WitnessProgram::from_address(addr.as_ref())
+ .ok()
+ .and_then(|wp| {
+ let pg = wp.program();
+ if pg.len() == 20 {
+ let mut buf = [0; 20];
+ buf.copy_from_slice(pg);
+ Some(buf)
+ } else {
+ None
+ }
+ })
+ })
+ .collect();
+
+ if decoded.len() < 2 {
+ return Err(DecodeError::MissingSeqWitAddress);
+ }
+
+ let mut parts: Vec<(bool, [u8; 4], &[u8; 16])> = decoded
+ .iter()
+ .map(|c| {
+ let mut magic_id: [u8; 4] = c[..4].try_into().unwrap();
+ let key_half: &[u8; 16] = c[4..].try_into().unwrap();
+ let is_first = !c[0] & 0b1000_0000 == 0;
+ // Clear first bit
+ magic_id[0] &= 0b0111_1111;
+ (is_first, magic_id, key_half)
+ })
+ .collect();
+ let mut map = BTreeMap::new();
+
+ for (_, magic, _) in &parts {
+ match map.get_mut(magic) {
+ Some(prev) => *prev = true,
+ None => {
+ map.insert(*magic, false);
+ }
+ }
+ }
+ map.retain(|_, many| *many);
+ assert_eq!(map.len(), 1, "Two possible magic id");
+ let magic_id = map.into_keys().next().unwrap();
+ parts.retain(|(_, magic, _)| *magic == magic_id);
+ assert_eq!(parts.len(), 2, "Magic ID collision");
+
+ let mut key = [0; 32];
+ for (is_first, _, half) in parts {
+ key[is_first as usize * 16..][..16].copy_from_slice(half);
+ }
+ Ok(key)
+}
+
+pub mod utils {
+ use std::iter::repeat_with;
+
+ use bitcoin_bech32::{constants::Network, u5, WitnessProgram};
+
+ use crate::encode_segwit_msg;
+
+ pub fn rand_key() -> [u8; 32] {
+ let mut key = [0; 32];
+ key.fill_with(|| fastrand::u8(..));
+ key
+ }
+
+ pub fn rand_addresses(key: &[u8; 32]) -> Vec<String> {
+ let mut rng_address: Vec<String> = std::iter::repeat_with(|| {
+ let key: Vec<u8> = repeat_with(|| fastrand::u8(..)).take(20).collect();
+ WitnessProgram::new(u5::try_from_u8(0).unwrap(), key, Network::Bitcoin)
+ .unwrap()
+ .to_address()
+ })
+ .take(2)
+ .collect();
+
+ let mut addresses = encode_segwit_msg(Network::Bitcoin, &key).to_vec();
+ addresses.append(&mut rng_address);
+ fastrand::shuffle(&mut addresses);
+ addresses
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use bitcoin_bech32::constants::Network;
+
+ use crate::{
+ decode_segwit_msg, encode_segwit_msg,
+ utils::{rand_addresses, rand_key},
+ };
+
+ #[test]
+ fn test_shuffle() {
+ for _ in 0..1000 {
+ let key = rand_key();
+ let mut addresses = encode_segwit_msg(Network::Bitcoin, &key);
+ fastrand::shuffle(&mut addresses);
+ let decoded =
+ decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
+ .unwrap();
+ assert_eq!(key, decoded);
+ }
+ }
+
+ #[test]
+ fn test_shuffle_many() {
+ for _ in 0..1000 {
+ let key = rand_key();
+ let addresses = rand_addresses(&key);
+ let decoded =
+ decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
+ .unwrap();
+ assert_eq!(key, decoded);
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
@@ -1,8 +1,4 @@
-use std::{
- collections::{BTreeMap, HashSet},
- iter::repeat_with,
- path::PathBuf,
-};
+use std::{collections::HashSet, iter::repeat_with, path::PathBuf, str::FromStr};
use bitcoin_bech32::{constants::Network, u5, WitnessProgram};
use bitcoincore_rpc::{
@@ -10,19 +6,31 @@ use bitcoincore_rpc::{
jsonrpc::serde_json::Value,
Auth, Client, RpcApi,
};
-use static_init::dynamic;
-
-// https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp
-#[dynamic]
-static LEGACY_MIN_AMOUNT: Amount = Amount::from_sat(546);
-#[dynamic]
-static SEGWIT_MIN_AMOUNT: Amount = Amount::from_sat(294);
+use depolymerization::{decode_segwit_msg, encode_segwit_msg, segwit_min_amount};
const CLIENT: &str = "client";
const WIRE: &str = "wire";
-const DATA_PATH: &str = "C:/Users/antoi/AppData/Roaming/Bitcoin/regtest";
const RPC_URL: &str = "http://localhost:18443";
+fn get_data_path() -> PathBuf {
+ // https://github.com/bitcoin/bitcoin/blob/master/doc/bitcoin-conf.md#:~:text=By%20default%2C%20the%20configuration%20file,file%3E%20option%20in%20the%20bitcoin.
+ if cfg!(target_os = "windows") {
+ PathBuf::from_str(&std::env::var("APPDATA").unwrap())
+ .unwrap()
+ .join("Bitcoin")
+ } else if cfg!(target_os = "linux") {
+ PathBuf::from_str(&std::env::var("HOME").unwrap())
+ .unwrap()
+ .join(".bitcoin")
+ } else if cfg!(target_os = "macos") {
+ PathBuf::from_str(&std::env::var("HOME").unwrap())
+ .unwrap()
+ .join("Library/Application Support/Bitcoin")
+ } else {
+ unimplemented!("Only windows, linux or macos")
+ }
+}
+
#[derive(argh::FromArgs)]
/// Bitcoin metadata tester
struct Args {
@@ -38,158 +46,17 @@ struct Args {
#[argh(option)]
msg: Option<String>,
}
-
-fn encode_segwit_address(
- network: Network,
- is_first: bool,
- magic_id: &[u8; 4],
- key_half: &[u8; 16],
-) -> String {
- // Combine magic_it and the key half
- let mut buf = vec![0u8; 20];
- buf[..4].copy_from_slice(magic_id);
- buf[4..].copy_from_slice(key_half);
- // Toggle first bit for ordering
- if is_first {
- buf[0] &= 0b0111_1111 // Unset first bit
- } else {
- buf[0] |= 0b1000_0000 // Set first bit
- }
- // Encode into an fake segwit address
- WitnessProgram::new(u5::try_from_u8(0).unwrap(), buf, network)
- .unwrap()
- .to_address()
-}
-
-fn encode_segwit_key(network: Network, key: &[u8; 32]) -> [String; 2] {
- // Generate a random magic identifier
- let mut magic_id = [0; 4];
- // TODO use secure os based random
- magic_id.fill_with(|| fastrand::u8(..));
- // Split key in half;
- let mut split = ([0; 16], [0; 16]);
- split.0.copy_from_slice(&key[..16]);
- split.1.copy_from_slice(&key[16..]);
- [
- encode_segwit_address(network, true, &magic_id, &split.0),
- encode_segwit_address(network, false, &magic_id, &split.1),
- ]
-}
-
-#[derive(Debug, Clone)]
-pub enum DecodeError {
- MissingSeqWitAddress,
- MagicIdCollision,
-}
-
-fn decode_segwit_msg(segwit_addrs: &[&str]) -> Result<[u8; 32], DecodeError> {
- if segwit_addrs.len() < 2 {
- return Err(DecodeError::MissingSeqWitAddress);
- }
-
- let decoded: Vec<[u8; 20]> = segwit_addrs
- .into_iter()
- .filter_map(|addr| {
- WitnessProgram::from_address(addr).ok().and_then(|wp| {
- let pg = wp.program();
- if pg.len() == 20 {
- let mut buf = [0; 20];
- buf.copy_from_slice(pg);
- Some(buf)
- } else {
- None
- }
- })
- })
- .collect();
-
- if decoded.len() < 2 {
- return Err(DecodeError::MissingSeqWitAddress);
- }
-
- let mut parts: Vec<(bool, [u8; 4], &[u8; 16])> = decoded
- .iter()
- .map(|c| {
- let mut magic_id: [u8; 4] = c[..4].try_into().unwrap();
- let key_half: &[u8; 16] = c[4..].try_into().unwrap();
- let is_first = !c[0] & 0b1000_0000 == 0;
- // Clear first bit
- magic_id[0] &= 0b0111_1111;
- (is_first, magic_id, key_half)
- })
- .collect();
- let mut map = BTreeMap::new();
-
- for (_, magic, _) in &parts {
- match map.get_mut(magic) {
- Some(prev) => *prev = true,
- None => {
- map.insert(*magic, false);
- }
- }
- }
- map.retain(|_, many| *many);
- assert_eq!(map.len(), 1, "Two possible magic id");
- let magic_id = map.into_keys().next().unwrap();
- parts.retain(|(_, magic, _)| *magic == magic_id);
- assert_eq!(parts.len(), 2, "Magic ID collision");
-
- let mut key = [0; 32];
- for (is_first, _, half) in parts {
- key[is_first as usize * 16..][..16].copy_from_slice(half);
- }
- Ok(key)
-}
-
-#[test]
-fn test_shuffle() {
- for _ in 0..1000 {
- let mut key = [0; 32];
- key.fill_with(|| fastrand::u8(..));
- let mut addresses = encode_segwit_key(Network::Bitcoin, &key);
- fastrand::shuffle(&mut addresses);
- let decoded =
- decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
- .unwrap();
- assert_eq!(key, decoded);
- }
-}
-
-#[test]
-fn test_shuffle_many() {
- for _ in 0..1000 {
- let mut rng_address: Vec<String> = std::iter::repeat_with(|| {
- let key: Vec<u8> = repeat_with(|| fastrand::u8(..)).take(20).collect();
- WitnessProgram::new(u5::try_from_u8(0).unwrap(), key, Network::Bitcoin)
- .unwrap()
- .to_address()
- })
- .take(2)
- .collect();
-
- let mut key = [0; 32];
- key.fill_with(|| fastrand::u8(..));
- let mut addresses = encode_segwit_key(Network::Bitcoin, &key).to_vec();
- addresses.append(&mut rng_address);
- fastrand::shuffle(&mut addresses);
- let decoded =
- decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
- .unwrap();
- assert_eq!(key, decoded);
- }
-}
-
fn common_rpc() -> Client {
Client::new(
RPC_URL,
- Auth::CookieFile(PathBuf::from(DATA_PATH).join(".cookie")),
+ Auth::CookieFile(get_data_path().join("regtest").join(".cookie")),
)
.expect("Failed to open common client")
}
fn wallet_rpc(wallet: &str) -> Client {
Client::new(
&format!("{}/wallet/{}", RPC_URL, wallet),
- Auth::CookieFile(PathBuf::from(DATA_PATH).join(".cookie")),
+ Auth::CookieFile(get_data_path().join("regtest").join(".cookie")),
)
.expect(&format!("Failed to open wallet '{}' client", wallet))
}
@@ -224,9 +91,13 @@ fn send_with_metadata(
amount: Amount,
metadata: &[u8],
) -> bitcoincore_rpc::Result<Txid> {
- let addresses = encode_segwit_key(Network::Regtest, &metadata.try_into().unwrap());
+ let addresses = encode_segwit_msg(Network::Regtest, &metadata.try_into().unwrap());
let mut recipients = vec![(to.to_string(), amount)];
- recipients.extend(addresses.into_iter().map(|addr| (addr, *SEGWIT_MIN_AMOUNT)));
+ recipients.extend(
+ addresses
+ .into_iter()
+ .map(|addr| (addr, segwit_min_amount())),
+ );
send_many(rpc, recipients)
}
@@ -243,7 +114,7 @@ fn last_metadata(rpc: &Client) -> bitcoincore_rpc::Result<Vec<u8>> {
.unwrap()
.into_iter()
.filter_map(|it| {
- if it["value"].as_f64().unwrap() == SEGWIT_MIN_AMOUNT.as_btc() {
+ if it["value"].as_f64().unwrap() == segwit_min_amount().as_btc() {
Some(it["scriptPubKey"]["address"].as_str().unwrap())
} else {
None
@@ -256,7 +127,7 @@ fn last_metadata(rpc: &Client) -> bitcoincore_rpc::Result<Vec<u8>> {
fn main() {
{
let existing_wallets: HashSet<String> =
- std::fs::read_dir(PathBuf::from(DATA_PATH).join("wallets"))
+ std::fs::read_dir(get_data_path().join("regtest").join("wallets"))
.unwrap()
.filter_map(|it| it.ok())
.map(|it| it.file_name().to_string_lossy().to_string())
@@ -309,7 +180,7 @@ fn main() {
send_with_metadata(
&client_rpc,
&wire_addr,
- *LEGACY_MIN_AMOUNT,
+ Amount::from_sat(4200),
line.as_bytes(),
)
.unwrap();
@@ -328,7 +199,7 @@ fn main() {
} else {
// Send metadata
let metadata: Vec<u8> = repeat_with(|| fastrand::u8(..)).take(32).collect();
- send_with_metadata(&client_rpc, &wire_addr, *LEGACY_MIN_AMOUNT, &metadata).unwrap();
+ send_with_metadata(&client_rpc, &wire_addr, Amount::from_sat(4200), &metadata).unwrap();
// Mine one block
client_rpc.generate_to_address(1, &client_addr).unwrap();
// Read metadata