diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..72a7bff
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/side.iml b/.idea/side.iml
new file mode 100644
index 0000000..fdaf31c
--- /dev/null
+++ b/.idea/side.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 9967c7c..63dc326 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -91,9 +91,9 @@ dependencies = [
[[package]]
name = "anstyle-query"
-version = "1.0.3"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [
"windows-sys 0.52.0",
]
@@ -108,6 +108,12 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
[[package]]
name = "ark-ec"
version = "0.4.2"
@@ -225,6 +231,12 @@ dependencies = [
"rand 0.8.5",
]
+[[package]]
+name = "arrayvec"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+
[[package]]
name = "async-channel"
version = "1.9.0"
@@ -244,7 +256,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -282,10 +294,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
-name = "backtrace"
-version = "0.3.72"
+name = "aws-lc-rs"
+version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
+checksum = "bf7d844e282b4b56750b2d4e893b2205581ded8709fddd2b6aa5418c150ca877"
+dependencies = [
+ "aws-lc-sys",
+ "mirai-annotations",
+ "paste",
+ "zeroize",
+]
+
+[[package]]
+name = "aws-lc-sys"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3a2c29203f6bf296d01141cc8bb9dbd5ecd4c27843f2ee0767bcd5985a927da"
+dependencies = [
+ "bindgen",
+ "cc",
+ "cmake",
+ "dunce",
+ "fs_extra",
+ "libc",
+ "paste",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
@@ -302,6 +341,22 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+[[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.0",
+]
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
[[package]]
name = "base64"
version = "0.13.1"
@@ -326,12 +381,104 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+[[package]]
+name = "bdk"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fc1fc1a92e0943bfbcd6eb7d32c1b2a79f2f1357eb1e2eee9d7f36d6d7ca44a"
+dependencies = [
+ "async-trait",
+ "bdk-macros",
+ "bip39",
+ "bitcoin 0.30.2",
+ "electrum-client 0.18.0",
+ "getrandom 0.2.15",
+ "js-sys",
+ "log",
+ "miniscript 10.0.0",
+ "rand 0.8.5",
+ "serde",
+ "serde_json",
+ "sled",
+ "tokio",
+]
+
+[[package]]
+name = "bdk-macros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81c1980e50ae23bb6efa9283ae8679d6ea2c6fa6a99fe62533f65f4a25a1a56c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "bdk_chain"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "163b064557cee078e8ee5dd2c88944204506f7b2b1524f78e8fcba38c346da7b"
+dependencies = [
+ "bitcoin 0.32.2",
+ "miniscript 12.0.0",
+ "serde",
+]
+
+[[package]]
+name = "bdk_esplora"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "089babab213bbb32518bad79a7313ebb4c85a52c18c8b558402dfa810c27de3f"
+dependencies = [
+ "async-trait",
+ "bdk_chain",
+ "esplora-client",
+ "futures",
+ "miniscript 12.0.0",
+]
+
+[[package]]
+name = "bdk_sqlite"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0926dc5778fb3c5afaf7def9ed9b9c9d9fe9e3ba499e09cb816d3de43211be71"
+dependencies = [
+ "bdk_chain",
+ "rusqlite",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "bdk_wallet"
+version = "1.0.0-alpha.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2926afdbfc54ebf7df2caa51af5be4435b90c01c6fbe5578b51b7c2c0a264bd9"
+dependencies = [
+ "bdk_chain",
+ "bip39",
+ "bitcoin 0.32.2",
+ "getrandom 0.2.15",
+ "js-sys",
+ "miniscript 12.0.0",
+ "rand 0.8.5",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "bech32"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
+[[package]]
+name = "bech32"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d"
+
[[package]]
name = "bft-crdt-derive"
version = "0.1.0"
@@ -370,12 +517,111 @@ dependencies = [
"serde",
]
+[[package]]
+name = "bindgen"
+version = "0.69.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
+dependencies = [
+ "bitflags 2.5.0",
+ "cexpr",
+ "clang-sys",
+ "itertools",
+ "lazy_static",
+ "lazycell",
+ "log",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn 2.0.67",
+ "which",
+]
+
+[[package]]
+name = "bip39"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
+dependencies = [
+ "bitcoin_hashes 0.11.0",
+ "serde",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "bitcoin"
+version = "0.30.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462"
+dependencies = [
+ "base64 0.13.1",
+ "bech32 0.9.1",
+ "bitcoin-private",
+ "bitcoin_hashes 0.12.0",
+ "hex_lit",
+ "secp256k1 0.27.0",
+ "serde",
+]
+
+[[package]]
+name = "bitcoin"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6"
+dependencies = [
+ "base58ck",
+ "base64 0.21.7",
+ "bech32 0.11.0",
+ "bitcoin-internals",
+ "bitcoin-io",
+ "bitcoin-units",
+ "bitcoin_hashes 0.14.0",
+ "hex-conservative",
+ "hex_lit",
+ "secp256k1 0.29.0",
+ "serde",
+]
+
+[[package]]
+name = "bitcoin-internals"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitcoin-io"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56"
+
[[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.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb54da0b28892f3c52203a7191534033e051b6f4b52bc15480681b57b7e036f5"
+dependencies = [
+ "bitcoin-internals",
+ "serde",
+]
+
+[[package]]
+name = "bitcoin_hashes"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4"
+
[[package]]
name = "bitcoin_hashes"
version = "0.12.0"
@@ -383,6 +629,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501"
dependencies = [
"bitcoin-private",
+ "serde",
+]
+
+[[package]]
+name = "bitcoin_hashes"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16"
+dependencies = [
+ "bitcoin-io",
+ "hex-conservative",
+ "serde",
]
[[package]]
@@ -426,9 +684,9 @@ dependencies = [
[[package]]
name = "blst"
-version = "0.3.11"
+version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b"
+checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32"
dependencies = [
"cc",
"glob",
@@ -468,9 +726,23 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
+checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
+dependencies = [
+ "jobserver",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
[[package]]
name = "cfg-if"
@@ -518,6 +790,17 @@ dependencies = [
"half",
]
+[[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
[[package]]
name = "clap"
version = "3.2.25"
@@ -532,9 +815,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.4"
+version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
dependencies = [
"clap_builder",
"clap_derive",
@@ -542,26 +825,26 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.2"
+version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
dependencies = [
"anstream",
"anstyle",
- "clap_lex 0.7.0",
+ "clap_lex 0.7.1",
"strsim",
]
[[package]]
name = "clap_derive"
-version = "4.5.4"
+version = "4.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -575,9 +858,18 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
+
+[[package]]
+name = "cmake"
+version = "0.1.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
+dependencies = [
+ "cc",
+]
[[package]]
name = "colorchoice"
@@ -625,6 +917,16 @@ dependencies = [
"unicode-segmentation",
]
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
@@ -640,6 +942,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "criterion"
version = "0.4.0"
@@ -763,7 +1074,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -774,7 +1085,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -828,15 +1139,15 @@ dependencies = [
[[package]]
name = "derive_more"
-version = "0.99.17"
+version = "0.99.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
dependencies = [
"convert_case 0.4.0",
"proc-macro2",
"quote",
"rustc_version",
- "syn 1.0.109",
+ "syn 2.0.67",
]
[[package]]
@@ -881,6 +1192,12 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
[[package]]
name = "dyn-clone"
version = "1.0.17"
@@ -922,6 +1239,42 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
+[[package]]
+name = "electrum-client"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bc133f1c8d829d254f013f946653cbeb2b08674b960146361d1e9b67733ad19"
+dependencies = [
+ "bitcoin 0.30.2",
+ "bitcoin-private",
+ "byteorder",
+ "libc",
+ "log",
+ "rustls 0.21.12",
+ "serde",
+ "serde_json",
+ "webpki",
+ "webpki-roots 0.22.6",
+ "winapi",
+]
+
+[[package]]
+name = "electrum-client"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c7b1f8783238bb18e6e137875b0a66f3dffe6c7ea84066e05d033cf180b150f"
+dependencies = [
+ "bitcoin 0.32.2",
+ "byteorder",
+ "libc",
+ "log",
+ "rustls 0.23.10",
+ "serde",
+ "serde_json",
+ "webpki-roots 0.25.4",
+ "winapi",
+]
+
[[package]]
name = "elliptic-curve"
version = "0.13.8"
@@ -942,6 +1295,15 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "encoding_rs"
+version = "0.8.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "enfync"
version = "0.1.6"
@@ -962,6 +1324,30 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "esplora-client"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69c6d27ef4ff21019edd98aa92199757e10a88065bbfcef6bb750ca6ec5e4a45"
+dependencies = [
+ "bitcoin 0.32.2",
+ "hex-conservative",
+ "log",
+ "minreq",
+ "reqwest",
+ "serde",
+]
+
[[package]]
name = "event-listener"
version = "2.5.3"
@@ -1004,6 +1390,18 @@ dependencies = [
"wasmtimer",
]
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
[[package]]
name = "fastcrypto"
version = "0.1.8"
@@ -1016,7 +1414,7 @@ dependencies = [
"ark-serialize",
"auto_ops",
"base64ct",
- "bech32",
+ "bech32 0.9.1",
"bincode",
"blake2",
"blst",
@@ -1042,7 +1440,7 @@ dependencies = [
"rfc6979",
"rsa",
"schemars",
- "secp256k1",
+ "secp256k1 0.27.0",
"serde",
"serde_json",
"serde_with 2.3.3",
@@ -1068,6 +1466,12 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
[[package]]
name = "ff"
version = "0.13.0"
@@ -1084,6 +1488,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
[[package]]
name = "form_urlencoded"
version = "1.2.1"
@@ -1093,6 +1512,22 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "fs_extra"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
+
[[package]]
name = "futures"
version = "0.3.30"
@@ -1149,7 +1584,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -1182,6 +1617,15 @@ dependencies = [
"slab",
]
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1241,6 +1685,25 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "h2"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap 2.2.6",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
[[package]]
name = "half"
version = "2.4.1"
@@ -1271,6 +1734,18 @@ name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
+dependencies = [
+ "hashbrown 0.14.5",
+]
[[package]]
name = "heck"
@@ -1299,12 +1774,27 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+[[package]]
+name = "hex-conservative"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd"
+dependencies = [
+ "arrayvec",
+]
+
[[package]]
name = "hex-literal"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
+[[package]]
+name = "hex_lit"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
+
[[package]]
name = "hkdf"
version = "0.12.4"
@@ -1323,6 +1813,15 @@ dependencies = [
"digest 0.10.7",
]
+[[package]]
+name = "home"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "http"
version = "0.2.12"
@@ -1335,10 +1834,64 @@ dependencies = [
]
[[package]]
-name = "httparse"
-version = "1.8.0"
+name = "http-body"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+dependencies = [
+ "bytes",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+]
[[package]]
name = "iana-time-zone"
@@ -1407,6 +1960,21 @@ dependencies = [
"serde",
]
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
@@ -1428,6 +1996,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+[[package]]
+name = "jobserver"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "js-sys"
version = "0.3.69"
@@ -1452,15 +2029,31 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
dependencies = [
- "spin",
+ "spin 0.5.2",
]
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+[[package]]
+name = "libloading"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
+dependencies = [
+ "cfg-if",
+ "windows-targets 0.52.5",
+]
+
[[package]]
name = "libm"
version = "0.2.8"
@@ -1477,6 +2070,23 @@ dependencies = [
"libc",
]
+[[package]]
+name = "libsqlite3-sys"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
[[package]]
name = "lock_api"
version = "0.4.12"
@@ -1495,19 +2105,69 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
-version = "2.7.2"
+version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniscript"
+version = "10.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1eb102b66b2127a872dbcc73095b7b47aeb9d92f7b03c2b2298253ffc82c7594"
+dependencies = [
+ "bitcoin 0.30.2",
+ "bitcoin-private",
+ "serde",
+]
+
+[[package]]
+name = "miniscript"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b59c67956fd276ceec0cf194fbf80754ef4d88a496d5cf5e4fdf33561466183d"
+dependencies = [
+ "bech32 0.11.0",
+ "bitcoin 0.32.2",
+ "serde",
+]
[[package]]
name = "miniz_oxide"
-version = "0.7.3"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
+[[package]]
+name = "minreq"
+version = "2.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fdef521c74c2884a4f3570bcdb6d2a77b3c533feb6b27ac2ae72673cc221c64"
+dependencies = [
+ "base64 0.12.3",
+ "log",
+ "once_cell",
+ "rustls 0.21.12",
+ "rustls-webpki 0.101.7",
+ "serde",
+ "serde_json",
+ "webpki-roots 0.25.4",
+]
+
[[package]]
name = "mio"
version = "0.8.11"
@@ -1519,6 +2179,39 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "mirai-annotations"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
+
+[[package]]
+name = "native-tls"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@@ -1604,9 +2297,9 @@ dependencies = [
[[package]]
name = "object"
-version = "0.35.0"
+version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
+checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [
"memchr",
]
@@ -1629,6 +2322,50 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+[[package]]
+name = "openssl"
+version = "0.10.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
+dependencies = [
+ "bitflags 2.5.0",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.67",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
[[package]]
name = "option-ext"
version = "0.2.0"
@@ -1659,6 +2396,17 @@ dependencies = [
"sha2 0.10.8",
]
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core 0.8.6",
+]
+
[[package]]
name = "parking_lot"
version = "0.12.3"
@@ -1666,7 +2414,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
- "parking_lot_core",
+ "parking_lot_core 0.9.10",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "winapi",
]
[[package]]
@@ -1677,7 +2439,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall",
+ "redox_syscall 0.5.2",
"smallvec",
"windows-targets 0.52.5",
]
@@ -1756,6 +2518,12 @@ dependencies = [
"spki 0.7.3",
]
+[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
[[package]]
name = "plotters"
version = "0.3.6"
@@ -1796,6 +2564,16 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+[[package]]
+name = "prettyplease"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.67",
+]
+
[[package]]
name = "primeorder"
version = "0.13.6"
@@ -1817,9 +2595,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.84"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@@ -1951,14 +2729,23 @@ checksum = "a25d631e41bfb5fdcde1d4e2215f62f7f0afa3ff11e26563765bd6ea1d229aeb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
name = "redox_syscall"
-version = "0.5.1"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [
"bitflags 2.5.0",
]
@@ -2003,6 +2790,47 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+[[package]]
+name = "reqwest"
+version = "0.11.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
+dependencies = [
+ "base64 0.21.7",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-tls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
+ "tokio",
+ "tokio-native-tls",
+ "tokio-socks",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
[[package]]
name = "rfc6979"
version = "0.4.0"
@@ -2013,6 +2841,21 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "ring"
+version = "0.17.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "getrandom 0.2.15",
+ "libc",
+ "spin 0.9.8",
+ "untrusted",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "rsa"
version = "0.8.2"
@@ -2034,12 +2877,32 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "rusqlite"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
+dependencies = [
+ "bitflags 2.5.0",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "smallvec",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
[[package]]
name = "rustc_version"
version = "0.4.0"
@@ -2049,6 +2912,83 @@ dependencies = [
"semver",
]
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags 2.5.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.21.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
+dependencies = [
+ "log",
+ "ring",
+ "rustls-webpki 0.101.7",
+ "sct",
+]
+
+[[package]]
+name = "rustls"
+version = "0.23.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402"
+dependencies = [
+ "aws-lc-rs",
+ "log",
+ "once_cell",
+ "rustls-pki-types",
+ "rustls-webpki 0.102.4",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+dependencies = [
+ "base64 0.21.7",
+]
+
+[[package]]
+name = "rustls-pki-types"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
+
+[[package]]
+name = "rustls-webpki"
+version = "0.101.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.102.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e"
+dependencies = [
+ "aws-lc-rs",
+ "ring",
+ "rustls-pki-types",
+ "untrusted",
+]
+
[[package]]
name = "ryu"
version = "1.0.18"
@@ -2064,6 +3004,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "schannel"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "schemars"
version = "0.8.21"
@@ -2085,7 +3034,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2094,6 +3043,16 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "sct"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
[[package]]
name = "sec1"
version = "0.7.3"
@@ -2114,9 +3073,22 @@ version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f"
dependencies = [
- "bitcoin_hashes",
+ "bitcoin_hashes 0.12.0",
"rand 0.8.5",
- "secp256k1-sys",
+ "secp256k1-sys 0.8.1",
+ "serde",
+]
+
+[[package]]
+name = "secp256k1"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3"
+dependencies = [
+ "bitcoin_hashes 0.14.0",
+ "rand 0.8.5",
+ "secp256k1-sys 0.10.0",
+ "serde",
]
[[package]]
@@ -2128,6 +3100,38 @@ dependencies = [
"cc",
]
+[[package]]
+name = "secp256k1-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
+dependencies = [
+ "bitflags 2.5.0",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "semver"
version = "1.0.23"
@@ -2151,7 +3155,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2162,7 +3166,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2186,6 +3190,18 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
[[package]]
name = "serde_with"
version = "2.3.3"
@@ -2229,7 +3245,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2241,7 +3257,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2311,18 +3327,32 @@ dependencies = [
"lazy_static",
]
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "side-node"
version = "0.1.0"
dependencies = [
+ "anyhow",
"async-trait",
+ "bdk",
+ "bdk_esplora",
+ "bdk_sqlite",
+ "bdk_wallet",
"bft-crdt-derive",
"bft-json-crdt",
- "clap 4.5.4",
+ "bitcoin 0.32.2",
+ "clap 4.5.7",
"dirs",
+ "electrum-client 0.20.0",
"ezsockets",
"fastcrypto",
"indexmap 2.2.6",
+ "reqwest",
"serde",
"serde_json",
"sha256",
@@ -2372,6 +3402,22 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "sled"
+version = "0.34.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
+dependencies = [
+ "crc32fast",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "fs2",
+ "fxhash",
+ "libc",
+ "log",
+ "parking_lot 0.11.2",
+]
+
[[package]]
name = "smallvec"
version = "1.13.2"
@@ -2394,6 +3440,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
[[package]]
name = "spki"
version = "0.6.0"
@@ -2428,9 +3480,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5"
[[package]]
name = "subtle-ng"
@@ -2451,15 +3503,54 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.66"
+version = "2.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
+checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "textwrap"
version = "0.16.1"
@@ -2483,7 +3574,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2574,16 +3665,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.37.0"
+version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
+checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
- "parking_lot",
+ "parking_lot 0.12.3",
"pin-project-lite",
"signal-hook-registry",
"socket2",
@@ -2593,13 +3684,35 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "2.2.0"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
+]
+
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-socks"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0"
+dependencies = [
+ "either",
+ "futures-util",
+ "thiserror",
+ "tokio",
]
[[package]]
@@ -2632,6 +3745,19 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "tokio-util"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "toml"
version = "0.8.14"
@@ -2674,9 +3800,15 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
- "winnow 0.6.12",
+ "winnow 0.6.13",
]
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
[[package]]
name = "tracing"
version = "0.1.40"
@@ -2696,7 +3828,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -2734,6 +3866,12 @@ dependencies = [
"tracing-log",
]
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
[[package]]
name = "tungstenite"
version = "0.20.1"
@@ -2773,9 +3911,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
-version = "0.1.23"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
@@ -2787,10 +3925,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
-name = "url"
-version = "2.5.0"
+name = "untrusted"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
+[[package]]
+name = "url"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
"idna",
@@ -2805,9 +3949,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8parse"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
@@ -2824,6 +3968,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
[[package]]
name = "version_check"
version = "0.9.4"
@@ -2840,6 +3990,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@@ -2879,7 +4038,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
"wasm-bindgen-shared",
]
@@ -2913,7 +4072,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2932,7 +4091,7 @@ checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf"
dependencies = [
"futures",
"js-sys",
- "parking_lot",
+ "parking_lot 0.12.3",
"pin-utils",
"slab",
"wasm-bindgen",
@@ -2948,6 +4107,43 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "webpki"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.22.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
+dependencies = [
+ "webpki",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.25.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
+
+[[package]]
+name = "which"
+version = "4.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
+dependencies = [
+ "either",
+ "home",
+ "once_cell",
+ "rustix",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -3138,13 +4334,23 @@ dependencies = [
[[package]]
name = "winnow"
-version = "0.6.12"
+version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ff33f391015ecab21cd092389215eb265ef9496a9a07b6bee7d3529831deda"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
dependencies = [
"memchr",
]
+[[package]]
+name = "winreg"
+version = "0.50.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "zerocopy"
version = "0.7.34"
@@ -3162,7 +4368,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
[[package]]
@@ -3182,5 +4388,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.66",
+ "syn 2.0.67",
]
diff --git a/README.md b/README.md
index d1c46d9..1c6f6ac 100644
--- a/README.md
+++ b/README.md
@@ -50,11 +50,29 @@ Next dev tasks:
### Side Watcher
-The Side Watcher is a simple relayer node that sits between the Side Chain (Cosmos) and the decentralized Side Nodes. At the moment, it simply relays transactions between nodes via a websocket.
+The Side Watcher is a simple relayer node that sits between the Side Chain (Cosmos) and the decentralized Side Nodes. At the moment, it simply relays transactions between nodes via a websocket. We aim to eliminate this component from the architecture, but for the moment it simplifies networking and consensus agreement while we experiment with higher-value concepts.
-Next, the Side Watcher needs to:
+To fulfill the promises in the Lite Paper, the Side Watcher needs to:
-[ ] make a block for the P2P when the Side Chain creates a block (see litepaper)
+[ ] make a block for the P2P when the Side Chain creates a block
[ ] submit P2P chain data to the Side Chain
Later, we will aim to remove the Side Watcher from the architecture, by (a) moving to pure P2P transactions between Side Nodes, and (b) doing leader election of a Side Node to reach agreement on the submitted block.
+
+## Bitcoin integration
+
+There is a Bitcoin client integrated into the node, which can do simple coin transfers using esplora and the Mutinynet server's Signet (30 second blocktime).
+
+The client's demo driver can be run by doing:
+
+```
+cargo run -- init dave
+cargo run -- init sammy
+cargo run -- btc
+```
+
+You'll need to have funded the "dave" address prior to running the `btc` command - otherwise the transfer will fail gracefully.
+
+I was using this primarily as a way to experiment with constructing and broadcasting Bitcoin transactions, with the hope that it would be possible to move on to more advanced constructions (e.g. state channels). However, now that I look at all the options, it seems that multi-party state channels in Bitcoin are (probably) impossible to construct.
+
+There is a second, unused Bitcoin client in place which uses Blockstream's Electrum server, but this didn't seem to be working properly with respect to Signet Bitcoin network during my testing, so I went with the esplora / Mutiny version instead.
diff --git a/crates/bft-json-crdt/bft-crdt-derive/src/lib.rs b/crates/bft-json-crdt/bft-crdt-derive/src/lib.rs
index 656cb77..7118722 100644
--- a/crates/bft-json-crdt/bft-crdt-derive/src/lib.rs
+++ b/crates/bft-json-crdt/bft-crdt-derive/src/lib.rs
@@ -11,7 +11,7 @@ use syn::{
/// Helper to get tokenstream representing the parent crate
fn get_crate_name() -> TokenStream {
- let cr8 = crate_name("bft-json-crdt").unwrap_or(FoundCrate::Itself);
+ let cr8 = crate_name("bft-json-bft-crdt").unwrap_or(FoundCrate::Itself);
match cr8 {
FoundCrate::Itself => quote! { ::bft_json_crdt },
FoundCrate::Name(name) => {
@@ -109,13 +109,19 @@ pub fn derive_json_crdt(input: OgTokenStream) -> OgTokenStream {
}
}
- impl #impl_generics std::fmt::Debug for #ident #ty_generics #where_clause {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let mut fields = Vec::new();
- #(fields.push(format!("{}", #ident_strings.to_string()));)*
- write!(f, "{{ {:?} }}", fields.join(", "))
- }
- }
+ // I'm pulling this out so that we can see actual CRD content in debug output.
+ //
+ // The plan is to mostly get rid of the macros anyway, so it's a reasonable first step.
+ // It could (alternately) be just as good to keep the macros and change this function to
+ // output actual field content instead of just field names.
+ //
+ // impl #impl_generics std::fmt::Debug for #ident #ty_generics #where_clause {
+ // fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ // let mut fields = Vec::new();
+ // #(fields.push(format!("{}", #ident_strings.to_string()));)*
+ // write!(f, "{{ {:?} }}", fields.join(", "))
+ // }
+ // }
impl #impl_generics #crate_name::json_crdt::CrdtNode for #ident #ty_generics #where_clause {
fn apply(&mut self, op: #crate_name::op::Op<#crate_name::json_crdt::JsonValue>) -> #crate_name::json_crdt::OpState {
diff --git a/crates/bft-json-crdt/src/json_crdt.rs b/crates/bft-json-crdt/src/json_crdt.rs
index 4f3648b..638ba71 100644
--- a/crates/bft-json-crdt/src/json_crdt.rs
+++ b/crates/bft-json-crdt/src/json_crdt.rs
@@ -18,7 +18,7 @@ use fastcrypto::{
// Verifier,
};
// TODO: serde's json object serialization and deserialization (correctly) do not define anything
-// object field order in JSON objects. However, the hash check impl in bft-json-crdt does take order
+// object field order in JSON objects. However, the hash check impl in bft-json-bft-crdt does take order
// into account. This is going to cause problems later for non-Rust implementations, BFT hash checking
// currently depends on JSON serialization/deserialization object order. This shouldn't be the case
// but I've hacked in an IndexMap for the moment to get the PoC working. To see the problem, replace this with
@@ -549,7 +549,7 @@ mod test {
#[test]
fn test_derive_basic() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Player {
x: LwwRegisterCrdt,
y: LwwRegisterCrdt,
@@ -564,14 +564,14 @@ mod test {
#[test]
fn test_derive_nested() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Position {
x: LwwRegisterCrdt,
y: LwwRegisterCrdt,
}
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Player {
pos: Position,
balance: LwwRegisterCrdt,
@@ -589,7 +589,7 @@ mod test {
#[test]
fn test_lww_ops() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Test {
a: LwwRegisterCrdt,
b: LwwRegisterCrdt,
@@ -649,7 +649,7 @@ mod test {
#[test]
fn test_vec_and_map_ops() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Test {
a: ListCrdt,
}
@@ -689,14 +689,14 @@ mod test {
#[test]
fn test_causal_field_dependency() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Item {
name: LwwRegisterCrdt,
soulbound: LwwRegisterCrdt,
}
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Player {
inventory: ListCrdt- ,
balance: LwwRegisterCrdt,
@@ -755,7 +755,7 @@ mod test {
#[test]
fn test_2d_grid() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Game {
grid: ListCrdt>>,
}
@@ -816,7 +816,7 @@ mod test {
#[test]
fn test_arb_json() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Test {
reg: LwwRegisterCrdt,
}
@@ -852,13 +852,13 @@ mod test {
#[test]
fn test_wrong_json_types() {
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Nested {
list: ListCrdt,
}
#[add_crdt_fields]
- #[derive(Clone, CrdtNode)]
+ #[derive(Clone, CrdtNode, Debug)]
struct Test {
reg: LwwRegisterCrdt,
strct: ListCrdt,
diff --git a/crates/bft-json-crdt/tests/byzantine.rs b/crates/bft-json-crdt/tests/byzantine.rs
index f195da1..d2044ec 100644
--- a/crates/bft-json-crdt/tests/byzantine.rs
+++ b/crates/bft-json-crdt/tests/byzantine.rs
@@ -20,7 +20,7 @@ use serde_json::json;
// 5. block actual messages from honest actors (eclipse attack)
#[add_crdt_fields]
-#[derive(Clone, CrdtNode)]
+#[derive(Clone, CrdtNode, Debug)]
struct ListExample {
list: ListCrdt,
}
@@ -91,13 +91,13 @@ fn test_forge_update() {
}
#[add_crdt_fields]
-#[derive(Clone, CrdtNode)]
+#[derive(Clone, CrdtNode, Debug)]
struct Nested {
a: Nested2,
}
#[add_crdt_fields]
-#[derive(Clone, CrdtNode)]
+#[derive(Clone, CrdtNode, Debug)]
struct Nested2 {
b: LwwRegisterCrdt,
}
diff --git a/crates/bft-json-crdt/tests/editing-trace.js b/crates/bft-json-crdt/tests/editing-trace.js
index 42da951..a77d4cb 100644
--- a/crates/bft-json-crdt/tests/editing-trace.js
+++ b/crates/bft-json-crdt/tests/editing-trace.js
@@ -259796,7 +259796,7 @@ function insertAt(idx, elt) {
const pos = new_log.findIndex(log => log[0] === parent_id)
new_log.push([ID_COUNTER, pos, 0, elt])
crdt.splice(raw_i + 1, 0, { deleted: false, content: elt, id: ID_COUNTER })
- // console.log(`insert at ${idx} translated as op [${ID_COUNTER}, ${pos}, ${0}, ${escape(elt)}] found at ${raw_i + 1}::`, crdt[raw_i + 1])
+ // console.log(`insert at ${idx} translated as op [${ID_COUNTER}, ${pos}, ${0}, ${escape(elt)}] found at ${raw_i + 1}::`, bft-crdt[raw_i + 1])
return
}
@@ -259816,7 +259816,7 @@ function deleteAt(idx) {
const pos = new_log.findIndex(log => log[0] === our_id)
new_log.push([ID_COUNTER, pos, 1]);
crdt[raw_i].deleted = true
- // console.log(`delete at ${idx} translated as op [${ID_COUNTER}, ${pos}, ${1}] found at ${raw_i} with our_id ${our_id}::`, crdt[raw_i])
+ // console.log(`delete at ${idx} translated as op [${ID_COUNTER}, ${pos}, ${1}] found at ${raw_i} with our_id ${our_id}::`, bft-crdt[raw_i])
return
}
@@ -259853,7 +259853,7 @@ function rawJSString(edits) {
// deleteAt(edit[0])
// }
// }
-// console.log(crdt)
+// console.log(bft-crdt)
// rawJSString(mock_edits)
// console.log(new_log)
// const subset = edits.slice(0, 50000)
diff --git a/side-node/Cargo.lock b/side-node/Cargo.lock
deleted file mode 100644
index 37680ea..0000000
--- a/side-node/Cargo.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "side-node"
-version = "0.1.0"
diff --git a/side-node/Cargo.toml b/side-node/Cargo.toml
index d202bb5..8f0254a 100644
--- a/side-node/Cargo.toml
+++ b/side-node/Cargo.toml
@@ -6,22 +6,31 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+anyhow = "1.0.86"
async-trait = "0.1.52"
+bdk = { version = "0.29.0", default-feature = false, features = ["all-keys"] }
+bdk_esplora = "0.15.0"
+bdk_sqlite = "0.2.0"
+bdk_wallet = { version = "1.0.0-alpha.13", features = ["all-keys"] }
bft-json-crdt = { path = "../crates/bft-json-crdt" }
bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" }
+bitcoin = { version = "0.32.2", features = ["rand"] }
clap = { version = "4.5.4", features = ["derive"] }
dirs = "5.0.1"
+electrum-client = "0.20"
ezsockets = { version = "*", features = ["client"] }
fastcrypto = "0.1.8"
+indexmap = { version = "2.2.6", features = ["serde"] }
+reqwest = { version = "*", features = ["blocking"] }
# serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.117"
sha256 = "1.5.0"
tokio = { version = "1.37.0", features = ["full"] }
+toml = "0.8.14"
tracing = "0.1.32"
# tracing-subscriber = "0.3.9"
-toml = "0.8.14"
-indexmap = { version = "2.2.6", features = ["serde"] }
+
[dev-dependencies]
uuid = { version = "1.8.0", features = ["v4"] }
diff --git a/side-node/src/keys.rs b/side-node/src/bft_crdt/keys.rs
similarity index 79%
rename from side-node/src/keys.rs
rename to side-node/src/bft_crdt/keys.rs
index 4f0ef34..078ac68 100644
--- a/side-node/src/keys.rs
+++ b/side-node/src/bft_crdt/keys.rs
@@ -8,7 +8,7 @@ use bft_json_crdt::keypair::{make_keypair, Ed25519KeyPair};
use fastcrypto::traits::EncodeDecodeBase64;
/// Writes a new Ed25519 keypair to the file at key_path.
-pub(crate) fn write(key_path: PathBuf) -> Result<(), std::io::Error> {
+pub(crate) fn write(key_path: &PathBuf) -> Result<(), std::io::Error> {
let keys = make_keypair();
let mut file = File::create(key_path)?;
@@ -17,10 +17,10 @@ pub(crate) fn write(key_path: PathBuf) -> Result<(), std::io::Error> {
Ok(())
}
-pub(crate) fn load_from_file(side_dir: PathBuf) -> Ed25519KeyPair {
+pub(crate) fn load_from_file(side_dir: &PathBuf) -> Ed25519KeyPair {
let key_path = crate::utils::side_paths(side_dir.clone()).0;
- let data = fs::read_to_string(key_path).expect("couldn't read key file");
+ let data = fs::read_to_string(key_path).expect("couldn't read bft-bft-crdt key file");
println!("data: {:?}", data);
Ed25519KeyPair::decode_base64(&data).expect("couldn't load keypair from file")
diff --git a/side-node/src/crdt.rs b/side-node/src/bft_crdt/mod.rs
similarity index 78%
rename from side-node/src/crdt.rs
rename to side-node/src/bft_crdt/mod.rs
index 847b151..8dbc346 100644
--- a/side-node/src/crdt.rs
+++ b/side-node/src/bft_crdt/mod.rs
@@ -5,8 +5,11 @@ use bft_json_crdt::{
};
use serde::{Deserialize, Serialize};
+pub mod keys;
+pub mod websocket;
+
#[add_crdt_fields]
-#[derive(Clone, CrdtNode, Serialize, Deserialize)]
+#[derive(Clone, CrdtNode, Serialize, Deserialize, Debug)]
pub struct TransactionList {
pub list: ListCrdt,
}
@@ -19,7 +22,7 @@ impl TransactionList {
/// A fake Transaction struct we can use as a simulated payload
#[add_crdt_fields]
-#[derive(Clone, CrdtNode, Serialize, Deserialize, PartialEq)]
+#[derive(Clone, CrdtNode, Serialize, Deserialize, PartialEq, Debug)]
pub struct Transaction {
from: String,
to: String,
diff --git a/side-node/src/websocket.rs b/side-node/src/bft_crdt/websocket.rs
similarity index 76%
rename from side-node/src/websocket.rs
rename to side-node/src/bft_crdt/websocket.rs
index de6ee5d..52b30dd 100644
--- a/side-node/src/websocket.rs
+++ b/side-node/src/bft_crdt/websocket.rs
@@ -5,19 +5,17 @@ use tokio::sync::mpsc;
use crate::utils;
-pub struct WebSocketClient {
+pub struct Client {
incoming_sender: mpsc::Sender,
- handle: ezsockets::Client,
+ handle: ezsockets::Client,
}
-impl WebSocketClient {
+impl Client {
/// Start the websocket client
- pub async fn new(
- incoming_sender: mpsc::Sender,
- ) -> ezsockets::Client {
+ pub async fn new(incoming_sender: mpsc::Sender) -> ezsockets::Client {
let config = ClientConfig::new("ws://localhost:8080/websocket");
let (handle, future) = ezsockets::connect(
- |client| WebSocketClient {
+ |client| Client {
incoming_sender,
handle: client,
},
@@ -32,14 +30,14 @@ impl WebSocketClient {
}
#[async_trait]
-impl ezsockets::ClientExt for WebSocketClient {
+impl ezsockets::ClientExt for Client {
// Right now we're only using the Call type for sending signed ops
// change this to an enum if we need to send other types of calls, and
// match on it.
type Call = String;
- /// When we receive a text message, apply the crdt operation contained in it to our
- /// local crdt.
+ /// When we receive a text message, apply the bft-crdt operation contained in it to our
+ /// local bft-crdt.
async fn on_text(&mut self, text: String) -> Result<(), ezsockets::Error> {
let string_sha = utils::shassy(text.clone());
println!("received text, sha: {string_sha}");
@@ -47,9 +45,7 @@ impl ezsockets::ClientExt for WebSocketClient {
let object_sha = utils::shappy(incoming.clone());
println!("deserialized: {}", object_sha);
if string_sha != object_sha {
- println!("SHA mismatch: {string_sha} != {object_sha}");
- println!("text: {text}");
- println!("incoming: {incoming:?}");
+ panic!("sha mismatch: {string_sha} != {object_sha}, bft-bft-crdt has failed");
}
self.incoming_sender.send(incoming).await?;
Ok(())
diff --git a/side-node/src/bitcoin/clients/electrum.rs b/side-node/src/bitcoin/clients/electrum.rs
new file mode 100644
index 0000000..a4a0a9a
--- /dev/null
+++ b/side-node/src/bitcoin/clients/electrum.rs
@@ -0,0 +1,101 @@
+use crate::{bitcoin, utils};
+use bdk::bitcoin::psbt::PartiallySignedTransaction;
+use bdk::bitcoin::Network;
+use bdk::database::MemoryDatabase;
+use bdk::keys::ExtendedKey;
+use bdk::template::Bip84;
+use bdk::wallet::AddressIndex::{self, New};
+use bdk::wallet::AddressInfo;
+use bdk::{blockchain::ElectrumBlockchain, electrum_client, SyncOptions};
+use bdk::{FeeRate, KeychainKind, SignOptions, TransactionDetails, Wallet};
+
+/// DEPRECATED
+///
+/// This is a bdk example that uses the Electrum client to interact with the Bitcoin network.
+/// Electrum is a light client that connects to a server to get information about the Bitcoin network.
+/// The BDK itself does not have the ability to connect to e.g. esplora servers. As the Blockstream Electrum Signet
+/// server does not appear to be picking up transactions properly at the moment, I've shifted over to using
+/// the (more complex) `bdk_wallet` crate and the esplora client there (see the other bitcoin client).
+///
+/// Note:the types below are all completely different than the types in `bdk_wallet`.
+pub async fn run() -> Result<(), anyhow::Error> {
+ let dave = utils::home(&"dave".to_string());
+ let sammy = utils::home(&"sammy".to_string());
+ let dave_key = bitcoin::keys::load_from_file(&dave).unwrap();
+ let sammy_key = bitcoin::keys::load_from_file(&sammy).unwrap();
+
+ let dave_wallet = create_wallet(dave_key)?;
+ let sammy_wallet = create_wallet(sammy_key)?;
+
+ let dave_address = dave_wallet.get_address(AddressIndex::Peek(0))?.to_string();
+ let sammy_address = sammy_wallet.get_address(AddressIndex::Peek(0))?.to_string();
+
+ println!("Dave's address: {}", dave_address);
+ println!("Sammy's address: {}", sammy_address);
+
+ let blockchain = ElectrumBlockchain::from(electrum_client::Client::new(
+ "ssl://electrum.blockstream.info:60002",
+ )?);
+
+ println!("Syncing...");
+ dave_wallet.sync(&blockchain, SyncOptions::default())?;
+
+ display_balance(&dave_wallet);
+ display_balance(&sammy_wallet);
+
+ let (mut psbt, details) =
+ build_sending_tx(&dave_wallet, sammy_wallet.get_address(New)?).expect("psbt build error");
+
+ println!("About to sign the transaction: {:?}", details);
+
+ dave_wallet.sign(&mut psbt, SignOptions::default())?;
+ let _signed_tx = psbt.extract_tx();
+
+ // println!("Broadcasting...");
+ // blockchain.broadcast(&signed_tx).expect("broadcast error");
+ // println!("Transaction ID: {:?}", signed_tx.txid());
+ Ok(())
+}
+
+/// Create a BDK wallet using BIP 84 descriptor ("m/84h/1h/0h/0" and "m/84h/1h/0h/1")
+pub fn create_wallet(xkey: ExtendedKey) -> anyhow::Result> {
+ let xprv = xkey
+ .into_xprv(Network::Testnet)
+ .expect("couldn't turn xkey into xprv");
+
+ let external_descriptor = Bip84(xprv, KeychainKind::External);
+ let internal_descriptor = Some(Bip84(xprv, KeychainKind::Internal));
+
+ let wallet = Wallet::new(
+ external_descriptor,
+ internal_descriptor,
+ Network::Testnet,
+ MemoryDatabase::default(),
+ )?;
+
+ Ok(wallet)
+}
+
+fn display_balance(wallet: &Wallet) {
+ println!(
+ "Wallet balance for {} after syncing: {:?} sats on network {}",
+ wallet
+ .get_address(bdk::wallet::AddressIndex::Peek(0))
+ .expect("couldn't get address"),
+ wallet.get_balance().expect("couldn't show balance"),
+ wallet.network(),
+ );
+}
+
+fn build_sending_tx(
+ wallet: &Wallet,
+ recipient: AddressInfo,
+) -> anyhow::Result<(PartiallySignedTransaction, TransactionDetails), anyhow::Error> {
+ let mut builder = wallet.build_tx();
+ builder
+ .add_recipient(recipient.script_pubkey(), 1000)
+ .enable_rbf()
+ .do_not_spend_change()
+ .fee_rate(FeeRate::from_sat_per_vb(7.0));
+ Ok(builder.finish()?)
+}
diff --git a/side-node/src/bitcoin/clients/esplora.rs b/side-node/src/bitcoin/clients/esplora.rs
new file mode 100644
index 0000000..038d0a7
--- /dev/null
+++ b/side-node/src/bitcoin/clients/esplora.rs
@@ -0,0 +1,188 @@
+use std::{collections::BTreeSet, fs, io::Write};
+
+use bdk::keys::bip39::Mnemonic;
+use bdk_esplora::{
+ esplora_client::{self, AsyncClient},
+ EsploraAsyncExt,
+};
+use bdk_wallet::{
+ bitcoin::{Address, Amount, Network, Script},
+ chain::ConfirmationTimeHeightAnchor,
+ keys::{DerivableKey, ExtendedKey},
+ wallet::AddressInfo,
+ KeychainKind, SignOptions, Wallet,
+};
+
+use bdk_sqlite::{rusqlite::Connection, Store};
+
+use crate::utils;
+
+const STOP_GAP: usize = 50;
+const PARALLEL_REQUESTS: usize = 5;
+
+/// A wallet that uses the Esplora client to interact with the Bitcoin network.
+pub struct EsploraWallet {
+ client: AsyncClient,
+ db: Store,
+ name: String,
+ wallet: Wallet,
+}
+
+impl EsploraWallet {
+ /// Builds and signs a send transaction to send coins between addresses.
+ ///
+ /// Does NOT send it, you must call `broadcast` to do that.
+ ///
+ /// We could split the creation and signing easily if needed.
+ pub(crate) fn build_and_sign_send_tx(
+ &mut self,
+ recipient: Address,
+ amount: Amount,
+ ) -> Result {
+ let mut tx_builder = self.wallet.build_tx();
+ tx_builder
+ .add_recipient(recipient.script_pubkey(), amount)
+ .enable_rbf();
+ let mut psbt = tx_builder.finish()?;
+ let finalized = self.wallet.sign(&mut psbt, SignOptions::default())?;
+ assert!(finalized);
+ let tx = psbt.extract_tx()?;
+ Ok(tx)
+ }
+
+ /// Syncs the wallet with the latest state of the Bitcoin blockchain
+ pub(crate) async fn sync(&mut self) -> Result<(), anyhow::Error> {
+ print!("Syncing...");
+
+ fn generate_inspect(
+ kind: KeychainKind,
+ ) -> impl FnMut(u32, &Script) + Send + Sync + 'static {
+ let mut once = Some(());
+ let mut stdout = std::io::stdout();
+ move |spk_i, _| {
+ match once.take() {
+ Some(_) => print!("\nScanning keychain [{:?}]", kind),
+ None => print!(" {:<3}", spk_i),
+ };
+ stdout.flush().expect("must flush");
+ }
+ }
+ let request = self
+ .wallet
+ .start_full_scan()
+ .inspect_spks_for_all_keychains({
+ let mut once = BTreeSet::::new();
+ move |keychain, spk_i, _| {
+ match once.insert(keychain) {
+ true => print!("\nScanning keychain [{:?}]", keychain),
+ false => print!(" {:<3}", spk_i),
+ }
+ std::io::stdout().flush().expect("must flush")
+ }
+ })
+ .inspect_spks_for_keychain(
+ KeychainKind::External,
+ generate_inspect(KeychainKind::External),
+ )
+ .inspect_spks_for_keychain(
+ KeychainKind::Internal,
+ generate_inspect(KeychainKind::Internal),
+ );
+ let mut update = self
+ .client
+ .full_scan(request, STOP_GAP, PARALLEL_REQUESTS)
+ .await?;
+ let now = std::time::UNIX_EPOCH.elapsed().unwrap().as_secs();
+ let _ = update.graph_update.update_last_seen_unconfirmed(now);
+ self.wallet.apply_update(update)?;
+ self.persist_local()?;
+ println!("Sync complete for {}", self.name);
+ Ok(())
+ }
+
+ fn persist_local(&mut self) -> Result<(), anyhow::Error> {
+ Ok(if let Some(changeset) = self.wallet.take_staged() {
+ self.db.write(&changeset)?;
+ })
+ }
+
+ /// Gets the next unused address from the wallet.
+ pub(crate) fn next_unused_address(&mut self) -> Result {
+ let address = self.wallet.next_unused_address(KeychainKind::External);
+ self.persist_local()?;
+ println!(
+ "Generated address: https://mutinynet.com/address/{}",
+ address
+ );
+ Ok(address)
+ }
+
+ /// Returns the balance of the wallet.
+ pub(crate) fn balance(&self) -> bdk_wallet::wallet::Balance {
+ self.wallet.balance()
+ }
+
+ /// Broadcasts a signed transaction to the network.
+ pub(crate) async fn broadcast(
+ &self,
+ tx: &bitcoin::Transaction,
+ ) -> Result<(), esplora_client::Error> {
+ println!(
+ "{} broadcasting tx https://mutinynet.com/tx/{}",
+ self.name,
+ tx.compute_txid()
+ );
+ self.client.broadcast(tx).await
+ }
+}
+
+/// Creates a Bitcoin descriptor wallet with the mnemonic in the given user directory.
+pub(crate) fn create_wallet(name: &str, network: Network) -> anyhow::Result {
+ let keys_dir = utils::home(name);
+
+ let mnemonic_path = crate::utils::side_paths(keys_dir).1; // TODO: this tuple stinks
+ let mnemonic_words = fs::read_to_string(mnemonic_path).expect("couldn't read bitcoin key file");
+
+ println!("Creating wallet from mnemonic: {mnemonic_words}");
+ let mnemonic = Mnemonic::parse(mnemonic_words).unwrap();
+
+ // Generate the extended key
+ let xkey: ExtendedKey = mnemonic
+ .into_extended_key()
+ .expect("couldn't turn mnemonic into xkey");
+
+ let xprv = xkey
+ .into_xprv(Network::Signet)
+ .expect("problem converting xkey to xprv")
+ .to_string();
+
+ println!("Setting up esplora database for {name}");
+
+ let db_path = format!("/tmp/{name}-bdk-esplora-async-example.sqlite");
+ let conn = Connection::open(db_path)?;
+ let mut db = Store::new(conn)?;
+ let external_descriptor = format!("wpkh({xprv}/84'/1'/0'/0/*)");
+ let internal_descriptor = format!("wpkh({xprv}/84'/1'/0'/1/*)");
+ let changeset = db.read().expect("couldn't read esplora database");
+
+ let wallet = Wallet::new_or_load(
+ &external_descriptor,
+ &internal_descriptor,
+ changeset,
+ network,
+ )
+ .expect("problem setting up wallet");
+
+ let client = esplora_client::Builder::new("https://mutinynet.com/api")
+ .build_async()
+ .expect("couldn't build esplora client");
+
+ let esplora = EsploraWallet {
+ name: name.to_string(),
+ wallet,
+ db,
+ client,
+ };
+
+ Ok(esplora)
+}
diff --git a/side-node/src/bitcoin/clients/mod.rs b/side-node/src/bitcoin/clients/mod.rs
new file mode 100644
index 0000000..960b8ac
--- /dev/null
+++ b/side-node/src/bitcoin/clients/mod.rs
@@ -0,0 +1,2 @@
+pub mod electrum;
+pub mod esplora;
diff --git a/side-node/src/bitcoin/driver.rs b/side-node/src/bitcoin/driver.rs
new file mode 100644
index 0000000..3286043
--- /dev/null
+++ b/side-node/src/bitcoin/driver.rs
@@ -0,0 +1,62 @@
+use std::str::FromStr;
+
+use bdk_wallet::bitcoin::{Address, Amount, Network};
+
+use crate::bitcoin::clients;
+
+/// Demonstrates the use of bdk with the Esplora client.
+///
+/// This is more complex than the bare `bdk` crate, but the esplora client works.
+///
+/// Also, it very handily works with the mutinynet.com esplora server, which is configured
+/// with 30 second block times.
+pub(crate) async fn run() -> Result<(), anyhow::Error> {
+ simple_transfer().await
+}
+
+async fn simple_transfer() -> Result<(), anyhow::Error> {
+ let mut dave = clients::esplora::create_wallet("dave", Network::Signet)?;
+ let mut sammy = clients::esplora::create_wallet("sammy", Network::Signet)?;
+
+ let _next_address = dave.next_unused_address()?;
+
+ let dave_balance = dave.balance();
+ println!(
+ "Dave wallet balance before syncing: {} sats",
+ dave_balance.total()
+ );
+
+ dave.sync().await?;
+
+ let dave_balance = dave.balance();
+ println!("Wallet balance after syncing: {} sats", dave_balance);
+
+ let sammy_address = sammy.next_unused_address()?.address;
+ println!("Sammy's address: {}", sammy_address);
+
+ let sammy_balance = sammy.balance();
+ println!(
+ "Sammy wallet balance before syncing: {} sats",
+ sammy_balance
+ );
+
+ sammy.sync().await?;
+
+ let sammy_balance = sammy.balance();
+ println!("Sammy wallet balance after syncing: {} sats", sammy_balance);
+
+ let send_amount = Amount::from_sat(500);
+
+ if dave_balance.total() < send_amount {
+ println!(
+ "Please send at least {} sats to the receiving address",
+ send_amount
+ );
+ std::process::exit(0);
+ }
+
+ let tx = dave.build_and_sign_send_tx(sammy_address, send_amount)?;
+ dave.broadcast(&tx).await?;
+
+ Ok(())
+}
diff --git a/side-node/src/bitcoin/keys.rs b/side-node/src/bitcoin/keys.rs
new file mode 100644
index 0000000..920e942
--- /dev/null
+++ b/side-node/src/bitcoin/keys.rs
@@ -0,0 +1,50 @@
+use bdk::{
+ keys::{
+ bip39::{Language, Mnemonic, WordCount},
+ DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey,
+ },
+ miniscript,
+};
+
+use std::{
+ fs::{self, File},
+ io::Write,
+ path::PathBuf,
+};
+
+pub fn make_mnemonic() -> String {
+ let mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+ Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
+ mnemonic.to_string()
+}
+
+/// Write the mnemonic to a file in the node's side directory
+///
+/// TODO: obviously spitting the mnemonic out to the console is not for production
+pub(crate) fn write(mnemonic_path: &PathBuf) -> Result<(), std::io::Error> {
+ let mnemonic = make_mnemonic();
+ let mut file = File::create(mnemonic_path)?;
+ println!("mnemonic: {mnemonic}");
+ file.write(mnemonic.as_bytes())?;
+
+ Ok(())
+}
+
+/// Creates Signet Bitcoin descriptors from a mnemonic
+pub fn get(mnemonic_words: String) -> anyhow::Result {
+ let mnemonic = Mnemonic::parse(mnemonic_words).unwrap();
+
+ // Generate the extended key
+ let xkey: ExtendedKey = mnemonic
+ .into_extended_key()
+ .expect("couldn't turn mnemonic into xkey");
+
+ Ok(xkey)
+}
+
+pub(crate) fn load_from_file(side_dir: &PathBuf) -> anyhow::Result {
+ let mnemonic_path = crate::utils::side_paths(side_dir.clone()).1; // TODO: this tuple stinks
+ let mnemonic_words = fs::read_to_string(mnemonic_path).expect("couldn't read bitcoin key file");
+ println!("Creating wallet from mnemonic: {mnemonic_words}");
+ get(mnemonic_words)
+}
diff --git a/side-node/src/bitcoin/mod.rs b/side-node/src/bitcoin/mod.rs
new file mode 100644
index 0000000..784440b
--- /dev/null
+++ b/side-node/src/bitcoin/mod.rs
@@ -0,0 +1,3 @@
+pub mod clients;
+pub mod driver;
+pub mod keys;
diff --git a/side-node/src/cli/mod.rs b/side-node/src/cli/mod.rs
index cf50b6f..d20431d 100644
--- a/side-node/src/cli/mod.rs
+++ b/side-node/src/cli/mod.rs
@@ -17,6 +17,9 @@ pub(crate) struct Args {
#[derive(Subcommand)]
pub(crate) enum Commands {
+ /// Placeholder for future BTC commands
+ Btc {},
+
/// runs the Side Node
Run { name: String },
diff --git a/side-node/src/init/mod.rs b/side-node/src/init/mod.rs
index cca68ee..c1997dd 100644
--- a/side-node/src/init/mod.rs
+++ b/side-node/src/init/mod.rs
@@ -2,16 +2,19 @@ use std::path::PathBuf;
use config::SideNodeConfig;
-use crate::{keys, utils};
+use crate::{bft_crdt, bitcoin, utils};
pub(crate) mod config;
pub(crate) fn init(home: PathBuf, config: SideNodeConfig) -> Result<(), std::io::Error> {
ensure_side_directory_exists(&home)?;
- let (key_path, config_path) = utils::side_paths(home.clone());
+ let (bft_crdt_key_path, bitcoin_key_path, config_path) = utils::side_paths(home.clone());
- println!("Writing key to: {:?}", key_path);
- keys::write(key_path)?;
+ println!("Writing bft bft-crdt key to: {:?}", bft_crdt_key_path);
+ bft_crdt::keys::write(&bft_crdt_key_path)?;
+
+ println!("Writing bitcoin key to: {:?}", bitcoin_key_path);
+ bitcoin::keys::write(&bitcoin_key_path)?;
println!("Writing config to: {:?}", config_path);
config::write_toml(&config, &config_path).expect("unable to write config file");
@@ -20,7 +23,7 @@ pub(crate) fn init(home: PathBuf, config: SideNodeConfig) -> Result<(), std::io:
}
/// Ensures that the directory at side_dir exists, so we have a place
-/// to store our key file and config file.
+/// to store our key files and config file.
fn ensure_side_directory_exists(side_dir: &PathBuf) -> Result<(), std::io::Error> {
if side_dir.exists() {
return Ok(());
@@ -53,6 +56,24 @@ mod tests {
(SideNodeConfig { name: name.clone() }, name)
}
+ #[test]
+ fn creates_bitcoin_keys() {
+ let (config, name) = side_node_config();
+ let side_dir = format!("/tmp/side/{name}");
+
+ let mut bitcoin_keys_path = PathBuf::new();
+ bitcoin_keys_path.push(side_dir.clone());
+ bitcoin_keys_path.push(utils::BITCOIN_KEY_FILE);
+
+ let _ = init(PathBuf::from_str(&side_dir).unwrap(), config);
+ assert!(bitcoin_keys_path.exists());
+
+ // check that the pem is readable
+ // let data = fs::read_to_string(bitcoin_keys_path).expect("couldn't read key file");
+ // let keys = Ed25519KeyPair::decode_base64(&data).expect("couldn't load keypair from file");
+ // assert_eq!(keys.public().as_bytes().len(), 32);
+ }
+
#[test]
fn creates_side_node_directory() {
let (config, name) = side_node_config();
@@ -67,13 +88,13 @@ mod tests {
}
#[test]
- fn creates_key_file() {
+ fn creates_bft_crdt_key_file() {
let (config, name) = side_node_config();
let side_dir = format!("/tmp/side/{name}");
let mut key_file_path = PathBuf::new();
key_file_path.push(side_dir.clone());
- key_file_path.push(utils::KEY_FILE);
+ key_file_path.push(utils::BFT_CRDT_KEY_FILE);
let _ = init(PathBuf::from_str(&side_dir).unwrap(), config);
assert!(key_file_path.exists());
diff --git a/side-node/src/lib.rs b/side-node/src/lib.rs
index cb199a4..643805b 100644
--- a/side-node/src/lib.rs
+++ b/side-node/src/lib.rs
@@ -1,18 +1,17 @@
+use bft_crdt::websocket;
+use bft_crdt::TransactionList;
use bft_json_crdt::json_crdt::{BaseCrdt, SignedOp};
use cli::{parse_args, Commands};
-use crdt::TransactionList;
use node::SideNode;
use tokio::{sync::mpsc, task};
-use websocket::WebSocketClient;
+pub mod bft_crdt;
+pub mod bitcoin;
pub(crate) mod cli;
-pub mod crdt;
pub(crate) mod init;
-pub mod keys;
pub mod node;
pub(crate) mod stdin;
pub mod utils;
-pub mod websocket;
#[tokio::main]
pub async fn run() {
@@ -30,16 +29,21 @@ pub async fn run() {
let mut node = setup(name).await;
node.start().await;
}
+ Some(Commands::Btc {}) => {
+ let _ = bitcoin::driver::run().await;
+ }
None => println!("No command provided. Exiting. See --help for more information."),
}
}
-/// Wire everything up outside the application so we can test more easily later
+/// Wire everything up outside the application so that we can test more easily later
async fn setup(name: &String) -> SideNode {
- // First, load up the keys and create a bft-crdt
+ // First, load up the keys and create a bft-bft-crdt
let side_dir = utils::home(name);
- let keys = keys::load_from_file(side_dir);
- let crdt = BaseCrdt::::new(&keys);
+ let bft_crdt_keys = bft_crdt::keys::load_from_file(&side_dir);
+ let keys = bitcoin::keys::load_from_file(&side_dir).unwrap();
+ let bitcoin_wallet = bitcoin::clients::electrum::create_wallet(keys).unwrap();
+ let crdt = BaseCrdt::::new(&bft_crdt_keys);
// Channels for internal communication, and a tokio task for stdin input
let (incoming_sender, incoming_receiver) = mpsc::channel::(32);
@@ -49,8 +53,15 @@ async fn setup(name: &String) -> SideNode {
});
// Finally, create the node and return it
- let handle = WebSocketClient::new(incoming_sender).await;
- let node = SideNode::new(crdt, keys, incoming_receiver, stdin_receiver, handle);
+ let handle = websocket::Client::new(incoming_sender).await;
+ let node = SideNode::new(
+ crdt,
+ bft_crdt_keys,
+ bitcoin_wallet,
+ incoming_receiver,
+ stdin_receiver,
+ handle,
+ );
println!("Node setup complete.");
node
}
diff --git a/side-node/src/node.rs b/side-node/src/node.rs
index 35eee2d..9cde341 100644
--- a/side-node/src/node.rs
+++ b/side-node/src/node.rs
@@ -1,28 +1,32 @@
+use bdk::database::MemoryDatabase;
use bft_json_crdt::json_crdt::{BaseCrdt, SignedOp};
use fastcrypto::ed25519::Ed25519KeyPair;
use tokio::sync::mpsc;
-use crate::{crdt::TransactionList, utils, websocket::WebSocketClient};
+use crate::{bft_crdt::websocket::Client, bft_crdt::TransactionList, utils};
pub struct SideNode {
crdt: BaseCrdt,
- keys: fastcrypto::ed25519::Ed25519KeyPair,
+ bft_crdt_keys: fastcrypto::ed25519::Ed25519KeyPair,
+ bitcoin_wallet: bdk::Wallet,
incoming_receiver: mpsc::Receiver,
stdin_receiver: std::sync::mpsc::Receiver,
- handle: ezsockets::Client,
+ handle: ezsockets::Client,
}
impl SideNode {
pub fn new(
crdt: BaseCrdt,
- keys: Ed25519KeyPair,
+ bft_crdt_keys: Ed25519KeyPair,
+ bitcoin_wallet: bdk::Wallet,
incoming_receiver: mpsc::Receiver,
stdin_receiver: std::sync::mpsc::Receiver,
- handle: ezsockets::Client,
+ handle: ezsockets::Client,
) -> Self {
let node = Self {
crdt,
- keys,
+ bft_crdt_keys,
+ bitcoin_wallet,
incoming_receiver,
stdin_receiver,
handle,
@@ -36,7 +40,7 @@ impl SideNode {
loop {
match self.stdin_receiver.try_recv() {
Ok(stdin) => {
- let transaction = utils::fake_transaction_json(stdin);
+ let transaction = utils::fake_generic_transaction_json(stdin);
let json = serde_json::to_value(transaction).unwrap();
let signed_op = self.add_transaction_local(json);
println!("STDIN: {}", utils::shappy(signed_op.clone()));
@@ -80,7 +84,7 @@ impl SideNode {
.doc
.list
.insert(last.id, transaction)
- .sign(&self.keys);
+ .sign(&self.bft_crdt_keys);
// self.trace_crdt();
signed_op
}
diff --git a/side-node/src/stdin.rs b/side-node/src/stdin.rs
index 9d74705..b71083f 100644
--- a/side-node/src/stdin.rs
+++ b/side-node/src/stdin.rs
@@ -5,7 +5,6 @@ pub(crate) fn input(stdin_sender: std::sync::mpsc::Sender) {
let stdin = std::io::stdin();
let lines = stdin.lock().lines();
for line in lines {
- println!("We're in stdin_input");
let line = line.unwrap();
stdin_sender.send(line).unwrap();
}
diff --git a/side-node/src/utils.rs b/side-node/src/utils.rs
index 17fb4cb..6ed33b8 100644
--- a/side-node/src/utils.rs
+++ b/side-node/src/utils.rs
@@ -1,23 +1,27 @@
-use std::path::PathBuf;
-
use bft_json_crdt::json_crdt::SignedOp;
use serde_json::{json, Value};
+use std::path::PathBuf;
-pub(crate) const KEY_FILE: &str = "keys.pem";
+pub(crate) const BITCOIN_KEY_FILE: &str = "bitcoin_keys.pem";
+pub(crate) const BFT_CRDT_KEY_FILE: &str = "keys.pem";
pub(crate) const CONFIG_FILE: &str = "config.toml";
/// Returns the path to the key file and config for this host OS.
-pub(crate) fn side_paths(prefix: PathBuf) -> (PathBuf, PathBuf) {
- let mut key_path = prefix.clone();
- key_path.push(KEY_FILE);
+pub(crate) fn side_paths(prefix: PathBuf) -> (PathBuf, PathBuf, PathBuf) {
+ let mut bft_crdt_key_path = prefix.clone();
+ bft_crdt_key_path.push(BFT_CRDT_KEY_FILE);
+
+ let mut bitcoin_key_path = prefix.clone();
+ bitcoin_key_path.push(BITCOIN_KEY_FILE);
let mut config_path = prefix.clone();
config_path.push(CONFIG_FILE);
- (key_path, config_path)
+ (bft_crdt_key_path, bitcoin_key_path, config_path)
}
-pub(crate) fn home(name: &String) -> std::path::PathBuf {
+/// Returns the path to the home directory for this host OS and the given node name
+pub(crate) fn home(name: &str) -> std::path::PathBuf {
let mut path = dirs::home_dir().unwrap();
path.push(".side");
path.push(name);
@@ -25,7 +29,7 @@ pub(crate) fn home(name: &String) -> std::path::PathBuf {
}
/// Generate a fake transaction with customizable from_pubkey String
-pub fn fake_transaction_json(from: String) -> Value {
+pub fn fake_generic_transaction_json(from: String) -> Value {
json!({
"from": from,
"to": "Bob",
diff --git a/side-node/tests/crdt.rs b/side-node/tests/crdt.rs
index d9f0a1c..51408ca 100644
--- a/side-node/tests/crdt.rs
+++ b/side-node/tests/crdt.rs
@@ -1,19 +1,19 @@
use bft_json_crdt::json_crdt::BaseCrdt;
use bft_json_crdt::keypair::make_keypair;
use bft_json_crdt::op::ROOT_ID;
-use side_node::crdt::TransactionList;
+use side_node::bft_crdt::TransactionList;
// case 1 - send valid updates
#[test]
fn test_valid_updates() {
- // Insert to crdt.doc on local node, test applying the same operation to a remote node
+ // Insert to bft-crdt.doc on local node, test applying the same operation to a remote node
// and check that the view is the same
let keypair1 = make_keypair();
let mut crdt1 = BaseCrdt::::new(&keypair1);
- let val_a = side_node::utils::fake_transaction_json(String::from("a"));
- let val_b = side_node::utils::fake_transaction_json(String::from("b"));
- let val_c = side_node::utils::fake_transaction_json(String::from("c"));
+ let val_a = side_node::utils::fake_generic_transaction_json(String::from("a"));
+ let val_b = side_node::utils::fake_generic_transaction_json(String::from("b"));
+ let val_c = side_node::utils::fake_generic_transaction_json(String::from("c"));
let _a = crdt1
.doc
diff --git a/side-node/tests/side_node.rs b/side-node/tests/side_node.rs
index a4ad31f..18f597e 100644
--- a/side-node/tests/side_node.rs
+++ b/side-node/tests/side_node.rs
@@ -2,7 +2,9 @@ use bft_json_crdt::{
json_crdt::{BaseCrdt, SignedOp},
keypair::make_keypair,
};
-use side_node::{crdt::TransactionList, node::SideNode, utils, websocket::WebSocketClient};
+use side_node::{
+ bft_crdt::websocket::Client, bft_crdt::TransactionList, bitcoin, node::SideNode, utils,
+};
use tokio::sync::mpsc;
#[tokio::test]
@@ -12,19 +14,19 @@ async fn test_distribute_via_websockets() {
assert_eq!(node1.current_sha(), node2.current_sha());
- let transaction = utils::fake_transaction_json("from_alice".to_string());
+ let transaction = utils::fake_generic_transaction_json("from_alice".to_string());
let signed_op = node1.add_transaction_local(transaction);
node2.handle_incoming(signed_op);
assert_eq!(node1.current_sha(), node2.current_sha());
- let transaction = utils::fake_transaction_json("from_alice2".to_string());
+ let transaction = utils::fake_generic_transaction_json("from_alice2".to_string());
let signed_op = node1.add_transaction_local(transaction);
node2.handle_incoming(signed_op);
assert_eq!(node1.current_sha(), node2.current_sha());
- let transaction = utils::fake_transaction_json("from_alice3".to_string());
+ let transaction = utils::fake_generic_transaction_json("from_alice3".to_string());
let signed_op = node1.add_transaction_local(transaction);
node2.handle_incoming(signed_op);
@@ -33,16 +35,26 @@ async fn test_distribute_via_websockets() {
/// Wire everything up, ignoring things we are not using in the test
async fn setup(_: &str) -> SideNode {
- // First, load up the keys and create a bft-crdt
- let keys = make_keypair();
- let crdt = BaseCrdt::::new(&keys);
+ // First, load up the keys and create a bft-bft-crdt
+ let bft_crdt_keys = make_keypair();
+ let mnemonic_words = bitcoin::keys::make_mnemonic();
+ let keys = bitcoin::keys::get(mnemonic_words).unwrap();
+ let bitcoin_wallet = bitcoin::clients::electrum::create_wallet(keys).unwrap();
+ let crdt = BaseCrdt::::new(&bft_crdt_keys);
// Channels for internal communication, and a tokio task for stdin input
let (incoming_sender, incoming_receiver) = mpsc::channel::(32);
let (_, stdin_receiver) = std::sync::mpsc::channel();
// Finally, create the node and return it
- let handle = WebSocketClient::new(incoming_sender).await;
- let node = SideNode::new(crdt, keys, incoming_receiver, stdin_receiver, handle);
+ let handle = Client::new(incoming_sender).await;
+ let node = SideNode::new(
+ crdt,
+ bft_crdt_keys,
+ bitcoin_wallet,
+ incoming_receiver,
+ stdin_receiver,
+ handle,
+ );
node
}