diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a79d581..a2f5911 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,7 +67,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [ nightly, beta, stable, 1.76.0 ] + toolchain: [ nightly, beta, stable, 1.77.0 ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master diff --git a/.rustfmt.toml b/.rustfmt.toml index 98e9b85..5704008 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,5 +1,5 @@ edition = "2021" -version = "Two" +style_edition = "2021" max_width = 100 array_width = 100 diff --git a/Cargo.lock b/Cargo.lock index 82ee3e6..cdcb918 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -144,38 +144,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "ascii" version = "1.1.0" @@ -187,15 +193,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" +checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -205,9 +211,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.20.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" +checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" dependencies = [ "bindgen", "cc", @@ -253,9 +259,9 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags", "cexpr", @@ -270,26 +276,52 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.77", + "syn 2.0.85", "which", ] [[package]] name = "bip39" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.13.0", "serde", "unicode-normalization", ] +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin-io" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative 0.1.2", +] + [[package]] name = "bitcoin_hashes" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative 0.2.1", +] [[package]] name = "bitflags" @@ -308,9 +340,9 @@ dependencies = [ [[package]] name = "bp-consensus" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3a99a46063d23d20a3177a04923652b245f31c2a04a6d0c47d5a93dc201a80" +checksum = "54db63118d55e32ea78f8775e98871d442a33e3bdef6419c7964d71b308316c0" dependencies = [ "amplify", "chrono", @@ -322,9 +354,9 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8caf04291e2703ce267b1f8baf14f03879a6d1a5afe76e011ada489f172f9" +checksum = "2e51a329150531b12243adf51d978490c796a6a20ec76c506b41c8e1226022bc" dependencies = [ "amplify", "bp-consensus", @@ -339,9 +371,9 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11fc4081db2147411381b9650765ce683e5065559f1125508696f79cc4cbfedf" +checksum = "9286fb448160672148262317f4647ebdcdd4699ed2bd34401f9799d0920cc376" dependencies = [ "amplify", "base85", @@ -353,25 +385,25 @@ dependencies = [ [[package]] name = "bp-derive" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2687829a365ba79a22d91737fa7404fd3e2aaeee6b8f5780fa3e94e6cb36c2" +checksum = "394f8a2c3f4df405aff7269d1727b463e2cf74ec35a077fe7425084cdbdd0448" dependencies = [ "amplify", "bp-consensus", "bp-invoice", "commit_verify", "hmac", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "sha2", ] [[package]] name = "bp-electrum" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ca7edfdada81772395612daccc1a62e1bb2ed99820832f329c06d6126dbeb4" +checksum = "cc58108a622b07755bf4a9468325b76e74f47042b1b493ff30a9059a20c2c34a" dependencies = [ "amplify", "bp-std", @@ -388,9 +420,9 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93ec91cf6d037996044e90223ef0fba7f8a465e24eeed73ca9651271b03a964" +checksum = "d5b002e82289784e579f130ebdc22aa0b19a7b873620ea1dab16628999ba404d" dependencies = [ "amplify", "bp-std", @@ -403,9 +435,9 @@ dependencies = [ [[package]] name = "bp-invoice" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29c4f672b4b82ce7a218b2900254ac8e4b15b0022ed13abffa722571e73d375" +checksum = "2cfe7be7b2d740de57e895f2ac93b305bbd67a2a0914dac424f8569bb9981679" dependencies = [ "amplify", "bech32", @@ -416,9 +448,9 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d607238c2bf2c34d048d14cd798a6365306e0fb6b02211235f3ccad0bc7fa8f1" +checksum = "9873cfe420f4ce5cc539c394c75df0669cdbe2c23eed1930dffe024cb0f13a57" dependencies = [ "amplify", "baid64", @@ -432,9 +464,9 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c9642f7b303791ba5696ff4be52c8d21ac2d2265bf9552692c8b03c741c11c" +checksum = "e23c585b49b6d3112b0ea1a2d2e143f493fd0ecbb3bb11bbbe41c69b63a4411c" dependencies = [ "amplify", "bp-consensus", @@ -451,7 +483,7 @@ dependencies = [ [[package]] name = "bp-wallet" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" dependencies = [ "aes-gcm", "amplify", @@ -492,9 +524,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.16" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -554,9 +586,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -564,9 +596,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -576,14 +608,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -603,9 +635,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" @@ -632,9 +664,9 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a1982dc6c54d2dcfa2bf4398d97e4e80a93f24d2537e58d6110b2b272cff0c" +checksum = "3bf08c4941e147937551f6a3d370552d67f98cf72c9eb18948142596beadd31e" dependencies = [ "amplify", "commit_encoding_derive", @@ -654,9 +686,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -717,7 +749,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -728,7 +760,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -743,13 +775,13 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e15b0f1ea4c1b7f66b86153341f08961122f5bad3fa68546b9ac5b199c99c39" +checksum = "49798157ca640745a3c898714b5805c28482295de8819cb7b2c530b8f9246df1" dependencies = [ "amplify", "bp-derive", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", ] @@ -838,9 +870,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -924,9 +956,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -940,6 +972,21 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hmac" version = "0.12.1" @@ -966,9 +1013,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1016,12 +1063,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] @@ -1066,9 +1113,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1087,9 +1134,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" @@ -1168,9 +1215,9 @@ dependencies = [ [[package]] name = "nonasync" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a84b7c873630913f738950f17412b9d5b24cad6866b98b802253f8cbbefabb" +checksum = "4b1005555d351f593bf72ffc3a89a0d42e243df004d2c4ded17699f10b562b98" dependencies = [ "amplify", ] @@ -1192,9 +1239,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -1249,28 +1296,28 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "psbt" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5b2f8fb596a1caffa486595c66eae3ebc3fb05c74063348b9a987373ba0cdb" +checksum = "1d36b72ab550141a04a368c25611bf04c87178b65d3be5165529e0b010ee551b" dependencies = [ "amplify", "base64", @@ -1279,7 +1326,7 @@ dependencies = [ "chrono", "commit_verify", "descriptors", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "strict_encoding", ] @@ -1336,9 +1383,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1348,9 +1395,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1359,9 +1406,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" @@ -1416,9 +1463,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags", "errno", @@ -1429,9 +1476,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "aws-lc-rs", "log", @@ -1445,15 +1492,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "aws-lc-rs", "ring", @@ -1469,10 +1516,11 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "secp256k1" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ + "bitcoin_hashes 0.14.0", "rand", "secp256k1-sys", "serde", @@ -1480,38 +1528,38 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] [[package]] name = "serde" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -1521,9 +1569,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -1540,15 +1588,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -1558,14 +1606,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -1574,7 +1622,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -1609,9 +1657,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a4c51f21507cf63984c367507f281215073e85b08711ed7da4fc63dbd709e0" +checksum = "ec071f3b3153217f1cb2bca5ba7ac87eeafc446cb35a5c0643dec33495a37244" dependencies = [ "amplify_derive", ] @@ -1660,14 +1708,14 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f16e8855a575633815f01482ac927ebaca3d2485aec8e17226c6826de29154e" +checksum = "8bae7475fc901144d8a35d25e36d76aa020b840f233d60532d6d52318718781b" dependencies = [ "amplify", "baid64", "half", - "indexmap 2.5.0", + "indexmap 2.6.0", "sha2", "strict_encoding", "vesper-lang", @@ -1709,9 +1757,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -1720,22 +1768,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -1807,11 +1855,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -1826,15 +1874,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -1927,9 +1975,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -1938,24 +1986,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1963,28 +2011,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -2050,6 +2098,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -2173,9 +2230,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -2198,7 +2255,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.85", ] [[package]] @@ -2206,17 +2263,3 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] diff --git a/Cargo.toml b/Cargo.toml index df8fa5b..f58993e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,24 +3,24 @@ members = ["."] exclude = ["convert"] [workspace.package] -version = "0.11.0-beta.8" +version = "0.11.0-beta.9" keywords = ["bitcoin", "wallet", "descriptor-wallet", "psbt", "taproot"] categories = ["cryptography::cryptocurrencies"] authors = ["Dr Maxim Orlovsky "] homepage = "https://lnp-bp.org" repository = "https://github.com/BP-WG/bp-wallet" -rust-version = "1.76.0" # Due to inspect_err +rust-version = "1.77.0" edition = "2021" license = "Apache-2.0" [workspace.dependencies] amplify = "4.7.0" -nonasync = "0.1.0" -bp-std = "0.11.0-beta.8" -psbt = "0.11.0-beta.8" -descriptors = "0.11.0-beta.8" -bp-esplora = { version = "0.11.0-beta.8", default-features = false, features = ["blocking"] } -bp-electrum = "0.11.0-beta.8" +nonasync = "0.1.2" +bp-std = "0.11.0-beta.9" +psbt = "0.11.0-beta.9" +descriptors = "0.11.0-beta.9" +bp-esplora = { version = "0.11.0-beta.9", default-features = false, features = ["blocking"] } +bp-electrum = "0.11.0-beta.9" serde_crate = { package = "serde", version = "1", features = ["derive"] } serde_json = "1.0.114" serde_yaml = "0.9.19" @@ -84,8 +84,9 @@ shellexpand = { version = "3.1.0", optional = true } [features] default = [] -all = ["electrum", "esplora", "mempool", "fs", "cli", "clap", "log", "client-side-validation", "strict-encoding"] -hot = ["bp-std/signers", "bip39", "rand", "aes-gcm", "rpassword"] +all = ["electrum", "esplora", "mempool", "fs", "cli", "clap", "log", "hot", "signers", "client-side-validation", "strict-encoding"] +signers = ["bp-std/signers", "bip39", "rand", "aes-gcm"] +hot = ["signers", "rpassword", "cli"] cli = ["base64", "env_logger", "clap", "shellexpand", "fs", "serde", "electrum", "esplora", "mempool", "log", "colored"] log = ["env_logger"] electrum = ["bp-electrum", "serde", "serde_json"] diff --git a/MANIFEST.yml b/MANIFEST.yml index 33b1364..3670815 100644 --- a/MANIFEST.yml +++ b/MANIFEST.yml @@ -3,7 +3,7 @@ Type: Library Kind: Free software License: Apache-2.0 Language: Rust -Compiler: 1.75 +Compiler: 1.77 Author: Maxim Orlovsky Maintained: LNP/BP Standards Association, Switzerland Maintainers: diff --git a/src/cli/command.rs b/src/cli/command.rs index 0d04b0c..bf9b5f2 100644 --- a/src/cli/command.rs +++ b/src/cli/command.rs @@ -29,7 +29,7 @@ use amplify::IoError; use bpstd::psbt::{Beneficiary, TxParams}; use bpstd::{ConsensusEncode, Derive, IdxBase, Keychain, NormalIndex, Sats, Tx, XpubDerivable}; use colored::Colorize; -use descriptors::{Descriptor, StdDescr}; +use descriptors::Descriptor; use nonasync::persistence::PersistenceError; use psbt::{ConstructionError, Payment, Psbt, PsbtConstructor, PsbtVer, UnfinalizedInputs}; use strict_encoding::Ident; @@ -207,7 +207,7 @@ impl Exec for Args { type Error = ExecError; const CONF_FILE_NAME: &'static str = "bp.toml"; - fn exec(self, mut config: Config, name: &'static str) -> Result<(), Self::Error> { + fn exec(self, mut config: Config, conf_filename: &'static str) -> Result<(), Self::Error> { match &self.command { Command::List => { let dir = self.general.base_dir(); @@ -230,18 +230,22 @@ impl Exec for Args { if !meta.is_dir() { continue; } + count += 1; let name = entry.file_name().into_string().expect("invalid directory name"); print!( "{name}{}", - if config.default_wallet == name { "\t[default]" } else { "\t\t" } + if config.default_wallet == name { "\t[default]\t" } else { "\t\t" } ); let provider = FsTextStore::new(entry.path().clone())?; - let Ok(wallet) = Wallet::::load(provider, true) else { - println!("# broken wallet descriptor"); - continue; + let wallet = match Wallet::::load(provider, true) { + Err(err) => { + error!("Error loading wallet descriptor: {err}"); + println!("# broken wallet descriptor"); + continue; + } + Ok(wallet) => wallet, }; println!("\t{}", wallet.descriptor()); - count += 1; } if count == 0 { println!("no wallets found"); @@ -250,7 +254,7 @@ impl Exec for Args { Command::Default { default } => { if let Some(default) = default { config.default_wallet = default.to_string(); - config.store(&self.conf_path(name)); + config.store(&self.conf_path(conf_filename)); } else { println!("Default wallet is '{}'", config.default_wallet); } @@ -354,9 +358,9 @@ impl Exec for Args { type Error = ExecError; const CONF_FILE_NAME: &'static str = "bp.toml"; - fn exec(mut self, config: Config, name: &'static str) -> Result<(), Self::Error> { + fn exec(mut self, config: Config, conf_filename: &'static str) -> Result<(), Self::Error> { match &self.command { - BpCommand::General(cmd) => self.translate(cmd).exec(config, name)?, + BpCommand::General(cmd) => self.translate(cmd).exec(config, conf_filename)?, BpCommand::Balance { addr: false, utxo: false, @@ -385,7 +389,7 @@ impl Exec for Args { utxo: false, }; self.sync = false; - self.exec(config, name)?; + self.exec(config, conf_filename)?; } BpCommand::Balance { addr: false, @@ -405,7 +409,7 @@ impl Exec for Args { utxo: false, }; self.sync = false; - self.exec(config, name)?; + self.exec(config, conf_filename)?; } BpCommand::Balance { addr: true, @@ -426,7 +430,7 @@ impl Exec for Args { utxo: false, }; self.sync = false; - self.exec(config, name)?; + self.exec(config, conf_filename)?; } BpCommand::History { txid, details } => { let wallet = self.bp_wallet::(&config)?; @@ -452,11 +456,11 @@ impl Exec for Args { println!( "\t* {value: >-12}ṩ\t{}\t{cp}", if *value < 0 { - "debit from" + "taken from" } else if row.operation == OpType::Credit { - "credit to " + "moved to " } else { - "change to " + "change " } ); } @@ -464,11 +468,11 @@ impl Exec for Args { println!( "\t* {value: >-12}ṩ\t{}\t{cp}", if *value > 0 { - "paid from " + "received " } else if row.operation == OpType::Credit { - "change to " + "change? " } else { - "sent to " + "paid to " } ); } @@ -513,7 +517,7 @@ impl Exec for Args { "Warning: you are not paying to anybody but just aggregating all your \ balances to a single UTXO", ); - wallet.all_utxos().map(WalletUtxo::into_outpoint).collect() + wallet.utxos().map(WalletUtxo::into_outpoint).collect() } }; diff --git a/src/cli/opts.rs b/src/cli/opts.rs index 67ff9b0..79d208d 100644 --- a/src/cli/opts.rs +++ b/src/cli/opts.rs @@ -136,13 +136,13 @@ pub struct WalletOpts { )] pub wallet_path: Option, - #[clap(flatten)] + #[command(flatten)] pub descriptor_opts: O, } #[derive(Args, Clone, PartialEq, Eq, Debug)] pub struct GeneralOpts { - /// Data directory path. + /// Data directory path /// /// Path to the directory that contains RGB stored data. #[arg( @@ -155,9 +155,13 @@ pub struct GeneralOpts { )] pub data_dir: PathBuf, - /// Network to use. + /// Network to use #[arg(short, long, global = true, default_value = "testnet3", env = "LNPBP_NETWORK")] pub network: Network, + + /// Do not add network prefix to the `--data-dir` + #[arg(long = "no-network-prefix", global = true)] + pub no_prefix: bool, } impl GeneralOpts { @@ -168,7 +172,9 @@ impl GeneralOpts { pub fn base_dir(&self) -> PathBuf { let mut dir = self.data_dir.clone(); - dir.push(self.network.to_string()); + if !self.no_prefix { + dir.push(self.network.to_string()); + } dir } diff --git a/src/hot/command.rs b/src/hot/command.rs index b5812dd..1be0fd9 100644 --- a/src/hot/command.rs +++ b/src/hot/command.rs @@ -56,6 +56,8 @@ pub struct HotArgs { #[derive(Subcommand, Clone, PartialEq, Eq, Debug, Display)] pub enum HotCommand { + /// Generate new seed file + /// /// Generate new seed and saves it as an encoded file. The password can be provided via the /// `SEED_PASSWORD` environment variable (security warning: don't set it on the command line, /// use instead the shell's builtin `read` and then export it). @@ -65,6 +67,8 @@ pub enum HotCommand { output_file: PathBuf, }, + /// Derive new extended private key from seed file + /// /// Derive new extended private key from the seed and saves it into a separate file as a new /// signing account. The seed password can be provided via the `SEED_PASSWORD` environment /// variable (security warning: don't set it on the command line, use instead the shell's @@ -95,7 +99,7 @@ pub enum HotCommand { output_file: PathBuf, }, - /// Print information about seed or the signing account + /// Print information about a seed or a signing account #[display("info")] Info { /// File containing either seed information or extended private key for the account, @@ -123,7 +127,7 @@ pub enum HotCommand { signing_account: PathBuf, }, - /// Analyze PSBT and print debug signing information + /// Analyze PSBT and print debug information #[display("sighash")] Sighash { /// File containing PSBT diff --git a/src/hot/signer.rs b/src/hot/signer.rs index ae73630..00ebeae 100644 --- a/src/hot/signer.rs +++ b/src/hot/signer.rs @@ -53,7 +53,9 @@ pub struct XprivSigner<'xpriv> { impl<'descr, 'me, D: Descriptor> Signer for ConsoleSigner<'descr, 'me, D> where Self: 'me { - type Sign<'s> = &'s XprivSigner<'s> where Self: 's + 'me; + type Sign<'s> + = &'s XprivSigner<'s> + where Self: 's + 'me; fn approve(&self, _psbt: &Psbt) -> Result, Rejected> { Ok(&self.signer) } } @@ -104,7 +106,7 @@ impl<'a, 'xpriv> Sign for &'a XprivSigner<'xpriv> { { return None; } - Some(output_pair.sign_schnorr(message.into())) + Some(output_pair.sign_schnorr(message.as_ref())) } fn sign_bip340_script_path( @@ -117,7 +119,7 @@ impl<'a, 'xpriv> Sign for &'a XprivSigner<'xpriv> { if sk.to_xonly_pk() != pk { return None; } - Some(sk.to_keypair_bip340().sign_schnorr(message.into())) + Some(sk.to_keypair_bip340().sign_schnorr(message.as_ref())) } fn should_sign_script_path( diff --git a/src/indexers/electrum.rs b/src/indexers/electrum.rs index a2cd2d1..b08b3ee 100644 --- a/src/indexers/electrum.rs +++ b/src/indexers/electrum.rs @@ -25,7 +25,8 @@ use std::str::FromStr; use bpstd::{Address, BlockHash, ConsensusEncode, Outpoint, Sats, Tx, TxIn, Txid, Weight}; use descriptors::Descriptor; -use electrum::{Client, ElectrumApi, Error, GetHistoryRes, Param}; +use electrum::{Client, ElectrumApi, GetHistoryRes, Param}; +pub use electrum::{Config, ConfigBuilder, Error, Socks5Config}; use serde_json::Value; use super::BATCH_SIZE; @@ -66,16 +67,26 @@ impl Indexer for Client { &self, descriptor: &WalletDescr, ) -> MayError, Vec> { - let mut cache = WalletCache::new_nonsync(descriptor.generator()); + let mut cache = WalletCache::new_nonsync(); + self.update::(descriptor, &mut cache).map(|_| cache) + } + + fn update, L2: Layer2>( + &self, + descriptor: &WalletDescr, + cache: &mut WalletCache, + ) -> MayError> { let mut errors = Vec::::new(); let mut address_index = BTreeMap::new(); for keychain in descriptor.keychains() { let mut empty_count = 0usize; + #[cfg(feature = "cli")] eprint!(" keychain {keychain} "); for derive in descriptor.addresses(keychain) { let script = derive.addr.script_pubkey(); + #[cfg(feature = "cli")] eprint!("."); let mut txids = Vec::new(); let Ok(hres) = @@ -271,15 +282,11 @@ impl Indexer for Client { .insert(wallet_addr.expect_transmute()); } - if errors.is_empty() { MayError::ok(cache) } else { MayError::err(cache, errors) } - } - - fn update, L2: Layer2>( - &self, - _descr: &WalletDescr, - _cache: &mut WalletCache, - ) -> MayError> { - todo!() + if errors.is_empty() { + MayError::ok(0) + } else { + MayError::err(0, errors) + } } fn publish(&self, tx: &Tx) -> Result<(), Self::Error> { diff --git a/src/indexers/esplora.rs b/src/indexers/esplora.rs index 6e6545b..a4a7349 100644 --- a/src/indexers/esplora.rs +++ b/src/indexers/esplora.rs @@ -26,7 +26,8 @@ use std::ops::{Deref, DerefMut}; use bpstd::{Address, DerivedAddr, LockTime, Outpoint, SeqNo, Tx, TxVer, Witness}; use descriptors::Descriptor; -use esplora::{BlockingClient, Error}; +use esplora::BlockingClient; +pub use esplora::{Builder, Config, Error}; #[cfg(feature = "mempool")] use super::mempool::Mempool; @@ -196,16 +197,26 @@ impl Indexer for Client { &self, descriptor: &WalletDescr, ) -> MayError, Vec> { - let mut cache = WalletCache::new_nonsync(descriptor.generator()); + let mut cache = WalletCache::new_nonsync(); + self.update::(descriptor, &mut cache).map(|_| cache) + } + + fn update, L2: Layer2>( + &self, + descriptor: &WalletDescr, + cache: &mut WalletCache, + ) -> MayError> { let mut errors = vec![]; let mut address_index = BTreeMap::new(); for keychain in descriptor.keychains() { let mut empty_count = 0usize; + #[cfg(feature = "cli")] eprint!(" keychain {keychain} "); for derive in descriptor.addresses(keychain) { let script = derive.addr.script_pubkey(); + #[cfg(feature = "cli")] eprint!("."); let mut txids = Vec::new(); match get_scripthash_txs_all(self, &derive) { @@ -302,15 +313,11 @@ impl Indexer for Client { .insert(wallet_addr.expect_transmute()); } - if errors.is_empty() { MayError::ok(cache) } else { MayError::err(cache, errors) } - } - - fn update, L2: Layer2>( - &self, - _descr: &WalletDescr, - _cache: &mut WalletCache, - ) -> MayError> { - todo!() + if errors.is_empty() { + MayError::ok(0) + } else { + MayError::err(0, errors) + } } fn publish(&self, tx: &Tx) -> Result<(), Self::Error> { self.inner.broadcast(tx) } diff --git a/src/layer2.rs b/src/layer2.rs index 3d7f2d6..fa2ea76 100644 --- a/src/layer2.rs +++ b/src/layer2.rs @@ -27,27 +27,18 @@ use std::fmt::Debug; use nonasync::persistence::{CloneNoPersistence, Persistence, Persisting}; pub trait Layer2: Debug + CloneNoPersistence + Persisting { - type Descr: Layer2Descriptor; - type Data: Layer2Data; - type Cache: Layer2Cache; + type Descr: Layer2Descriptor; + type Data: Layer2Data; + type Cache: Layer2Cache; type LoadError: error::Error; type StoreError: error::Error; } -pub trait Layer2Descriptor: Debug + CloneNoPersistence { - type LoadError: error::Error; - type StoreError: error::Error; -} +pub trait Layer2Descriptor: Debug + Clone {} -pub trait Layer2Data: Debug + CloneNoPersistence + Default { - type LoadError: error::Error; - type StoreError: error::Error; -} - -pub trait Layer2Cache: Debug + CloneNoPersistence + Default { - type LoadError: error::Error; - type StoreError: error::Error; +pub trait Layer2Data: Debug + Clone + Default {} +pub trait Layer2Cache: Debug + Clone + Default { type Tx: Layer2Tx; type Coin: Layer2Coin; } @@ -67,13 +58,41 @@ pub trait Layer2Coin: { } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(crate = "serde_crate") -)] -pub struct Empty; +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)] +pub struct Layer2Empty; + +#[cfg(feature = "serde")] +mod _empty_serde { + use std::collections::HashMap; + use std::fmt::{self, Formatter}; + + use serde_crate::de::{Error, Expected, Unexpected}; + use serde_crate::{Deserialize, Deserializer, Serialize, Serializer}; + + use super::*; + + impl Expected for Layer2Empty { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str("unit struct") } + } + + impl Serialize for Layer2Empty { + fn serialize(&self, serializer: S) -> Result + where S: Serializer { + HashMap::::new().serialize(serializer) + } + } + + impl<'de> Deserialize<'de> for Layer2Empty { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> { + let map: HashMap = Deserialize::deserialize(deserializer)?; + if !map.is_empty() { + return Err(D::Error::invalid_type(Unexpected::Map, &Layer2Empty)); + } + Ok(Layer2Empty) + } + } +} #[derive(Debug, Default)] #[cfg_attr( @@ -100,30 +119,21 @@ impl Persisting for NoLayer2 { } impl Layer2 for NoLayer2 { - type Descr = NoLayer2; - type Data = NoLayer2; - type Cache = NoLayer2; + type Descr = Layer2Empty; + type Data = Layer2Empty; + type Cache = Layer2Empty; type LoadError = Infallible; type StoreError = Infallible; } -impl Layer2Descriptor for NoLayer2 { - type LoadError = Infallible; - type StoreError = Infallible; -} +impl Layer2Descriptor for Layer2Empty {} -impl Layer2Data for NoLayer2 { - type LoadError = Infallible; - type StoreError = Infallible; -} +impl Layer2Data for Layer2Empty {} -impl Layer2Cache for NoLayer2 { - type Tx = Empty; - type Coin = Empty; - - type LoadError = Infallible; - type StoreError = Infallible; +impl Layer2Cache for Layer2Empty { + type Tx = Layer2Empty; + type Coin = Layer2Empty; } -impl Layer2Tx for Empty {} -impl Layer2Coin for Empty {} +impl Layer2Tx for Layer2Empty {} +impl Layer2Coin for Layer2Empty {} diff --git a/src/lib.rs b/src/lib.rs index 0b7a38d..e73c42a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ mod layer2; pub mod coinselect; #[cfg(feature = "cli")] pub mod cli; -#[cfg(feature = "hot")] +#[cfg(feature = "signers")] pub mod hot; mod bip43; #[cfg(feature = "fs")] @@ -52,15 +52,15 @@ pub use data::{ BlockHeight, BlockInfo, MiningInfo, Party, TxCredit, TxDebit, TxStatus, WalletAddr, WalletTx, WalletUtxo, }; -#[cfg(all(feature = "cli", feature = "hot"))] -pub use hot::{HotArgs, HotCommand}; #[cfg(feature = "hot")] +pub use hot::{HotArgs, HotCommand}; +#[cfg(feature = "signers")] pub use hot::{Seed, SeedType}; pub use indexers::Indexer; #[cfg(any(feature = "electrum", feature = "esplora", feature = "mempool"))] pub use indexers::{AnyIndexer, AnyIndexerError}; pub use layer2::{ - Layer2, Layer2Cache, Layer2Coin, Layer2Data, Layer2Descriptor, Layer2Tx, NoLayer2, + Layer2, Layer2Cache, Layer2Coin, Layer2Data, Layer2Descriptor, Layer2Empty, Layer2Tx, NoLayer2, }; pub use rows::{CoinRow, Counterparty, OpType, TxRow}; pub use util::MayError; diff --git a/src/rows.rs b/src/rows.rs index 462e87d..7356eb3 100644 --- a/src/rows.rs +++ b/src/rows.rs @@ -26,7 +26,9 @@ use std::str::FromStr; use amplify::hex::FromHex; use bpstd::{Address, DerivedAddr, Outpoint, Sats, ScriptPubkey, Txid}; -use crate::{BlockHeight, Layer2Cache, Layer2Coin, Layer2Tx, Party, TxStatus, WalletCache}; +use crate::{ + BlockHeight, Layer2Cache, Layer2Coin, Layer2Empty, Layer2Tx, Party, TxStatus, WalletCache, +}; #[cfg_attr( feature = "serde", @@ -104,11 +106,12 @@ impl FromStr for Counterparty { ) ) )] -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct TxRow { +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub struct TxRow { pub height: TxStatus, // TODO: Add date/time pub operation: OpType, + pub our_inputs: Vec, pub counterparties: Vec<(Counterparty, i64)>, pub own: Vec<(DerivedAddr, i64)>, pub txid: Txid, @@ -133,7 +136,7 @@ pub struct TxRow { ) ) )] -#[derive(Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct CoinRow { pub height: TxStatus, // TODO: Add date/time @@ -164,6 +167,12 @@ impl WalletCache { let mut row = TxRow { height: tx.status.map(|info| info.height), operation: OpType::Credit, + our_inputs: tx + .inputs + .iter() + .enumerate() + .filter_map(|(idx, inp)| inp.derived_addr().map(|_| idx as u32)) + .collect(), counterparties: none!(), own: none!(), txid: tx.txid, diff --git a/src/wallet.rs b/src/wallet.rs index 0c8462b..1976f83 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -35,8 +35,8 @@ use nonasync::persistence::{ use psbt::{PsbtConstructor, Utxo}; use crate::{ - BlockInfo, CoinRow, Indexer, Layer2, Layer2Cache, Layer2Data, Layer2Descriptor, MayError, - MiningInfo, NoLayer2, TxRow, WalletAddr, WalletTx, WalletUtxo, + BlockInfo, CoinRow, Indexer, Layer2, Layer2Cache, Layer2Data, Layer2Descriptor, Layer2Empty, + MayError, MiningInfo, NoLayer2, Party, TxRow, WalletAddr, WalletTx, WalletUtxo, }; #[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] @@ -82,7 +82,7 @@ impl<'descr, K, D: Descriptor> Iterator for AddrIter<'descr, K, D> { ) )] #[derive(Getters, Debug)] -pub struct WalletDescr +pub struct WalletDescr where D: Descriptor, L2: Layer2Descriptor, @@ -99,7 +99,7 @@ where _phantom: PhantomData, } -impl> WalletDescr { +impl> WalletDescr { pub fn new_standard(descr: D, network: Network) -> Self { WalletDescr { persistence: None, @@ -154,7 +154,7 @@ impl, L2: Layer2Descriptor> CloneNoPersistence for WalletDes persistence: None, generator: self.generator.clone(), network: self.network, - layer2: self.layer2.clone_no_persistence(), + layer2: self.layer2.clone(), _phantom: PhantomData, } } @@ -182,7 +182,7 @@ impl, L2: Layer2Descriptor> Drop for WalletDescr { } } -#[derive(Debug, Default)] +#[derive(Debug)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), @@ -196,28 +196,29 @@ pub struct WalletData { #[cfg_attr(feature = "serde", serde(skip))] persistence: Option>, + /// This field is used by applications to link data with other wallet components #[cfg_attr(feature = "serde", serde(skip))] - pub descriptor: String, + pub id: Option, pub name: String, pub tx_annotations: BTreeMap, pub txout_annotations: BTreeMap, pub txin_annotations: BTreeMap, pub addr_annotations: BTreeMap, - pub layer2_annotations: L2, pub last_used: BTreeMap, + pub layer2: L2, } impl CloneNoPersistence for WalletData { fn clone_no_persistence(&self) -> Self { Self { persistence: None, - descriptor: self.descriptor.clone(), + id: self.id.clone(), name: self.name.clone(), tx_annotations: self.tx_annotations.clone(), txout_annotations: self.txout_annotations.clone(), txin_annotations: self.txin_annotations.clone(), addr_annotations: self.addr_annotations.clone(), - layer2_annotations: self.layer2_annotations.clone_no_persistence(), + layer2: self.layer2.clone(), last_used: self.last_used.clone(), } } @@ -232,6 +233,39 @@ impl Persisting for WalletData { fn as_mut_persistence(&mut self) -> &mut Option> { &mut self.persistence } } +impl WalletData { + pub fn new_layer1() -> Self { + WalletData { + persistence: None, + id: None, + name: none!(), + tx_annotations: empty!(), + txout_annotations: empty!(), + txin_annotations: empty!(), + addr_annotations: empty!(), + layer2: none!(), + last_used: empty!(), + } + } +} + +impl WalletData { + pub fn new_layer2() -> Self + where L2: Default { + WalletData { + persistence: None, + id: None, + name: none!(), + tx_annotations: empty!(), + txout_annotations: empty!(), + txin_annotations: empty!(), + addr_annotations: empty!(), + layer2: none!(), + last_used: empty!(), + } + } +} + impl Drop for WalletData { fn drop(&mut self) { if self.is_autosave() { @@ -259,8 +293,9 @@ pub struct WalletCache { #[cfg_attr(feature = "serde", serde(skip))] persistence: Option>, + /// This field is used by applications to link data with other wallet components #[cfg_attr(feature = "serde", serde(skip))] - pub descriptor: String, + pub id: Option, pub last_block: MiningInfo, pub last_change: NormalIndex, pub headers: BTreeSet, @@ -271,10 +306,10 @@ pub struct WalletCache { } impl WalletCache { - pub(crate) fn new_nonsync>(descriptor: &D) -> Self { + pub(crate) fn new_nonsync() -> Self { WalletCache { persistence: None, - descriptor: descriptor.to_string(), + id: None, last_block: MiningInfo::genesis(), last_change: NormalIndex::ZERO, headers: none!(), @@ -308,7 +343,20 @@ impl WalletCache { }) } - pub fn utxo(&self, outpoint: Outpoint) -> Result { + pub fn has_outpoint(&self, outpoint: Outpoint) -> bool { + let Some(tx) = self.tx.get(&outpoint.txid) else { + return false; + }; + let Some(out) = tx.outputs.get(outpoint.vout.to_usize()) else { + return false; + }; + matches!(out.beneficiary, Party::Wallet(_)) + } + + #[inline] + pub fn is_unspent(&self, outpoint: Outpoint) -> bool { self.utxo.contains(&outpoint) } + + pub fn outpoint_by(&self, outpoint: Outpoint) -> Result { let tx = self.tx.get(&outpoint.txid).ok_or(NonWalletItem::NonWalletTx(outpoint.txid))?; let debit = tx .outputs @@ -324,7 +372,24 @@ impl WalletCache { }) } - pub fn all_utxos(&self) -> impl Iterator + '_ { + pub fn txos(&self) -> impl Iterator + '_ { + self.tx.iter().flat_map(|(txid, tx)| { + tx.outputs.iter().enumerate().filter_map(|(vout, out)| { + if let Party::Wallet(w) = out.beneficiary { + Some(WalletUtxo { + outpoint: Outpoint::new(*txid, vout as u32), + value: out.value, + terminal: w.terminal, + status: tx.status, + }) + } else { + None + } + }) + }) + } + + pub fn utxos(&self) -> impl Iterator + '_ { self.utxo.iter().map(|outpoint| { let tx = self.tx.get(&outpoint.txid).expect("cache data inconsistency"); let debit = tx.outputs.get(outpoint.vout_usize()).expect("cache data inconsistency"); @@ -345,14 +410,14 @@ impl CloneNoPersistence for WalletCache { fn clone_no_persistence(&self) -> Self { Self { persistence: None, - descriptor: self.descriptor.clone(), + id: self.id.clone(), last_block: self.last_block, last_change: self.last_change, headers: self.headers.clone(), tx: self.tx.clone(), utxo: self.utxo.clone(), addr: self.addr.clone(), - layer2: self.layer2.clone_no_persistence(), + layer2: self.layer2.clone(), } } } @@ -411,7 +476,7 @@ impl, L2: Layer2> PsbtConstructor for Wallet { fn descriptor(&self) -> &D { &self.descr.generator } fn utxo(&self, outpoint: Outpoint) -> Option { - self.cache.utxo(outpoint).ok().map(WalletUtxo::into_utxo) + self.cache.outpoint_by(outpoint).ok().map(WalletUtxo::into_utxo) } fn network(&self) -> Network { self.descr.network } @@ -432,9 +497,9 @@ impl, L2: Layer2> PsbtConstructor for Wallet { impl> Wallet { pub fn new_layer1(descr: D, network: Network) -> Self { Wallet { - cache: WalletCache::new_nonsync(&descr), + cache: WalletCache::new_nonsync(), + data: WalletData::new_layer1(), descr: WalletDescr::new_standard(descr, network), - data: empty!(), layer2: none!(), } } @@ -443,9 +508,9 @@ impl> Wallet { impl, L2: Layer2> Wallet { pub fn new_layer2(descr: D, l2_descr: L2::Descr, layer2: L2, network: Network) -> Self { Wallet { - cache: WalletCache::new_nonsync(&descr), + cache: WalletCache::new_nonsync(), + data: WalletData::new_layer2(), descr: WalletDescr::new_layer2(descr, l2_descr, network), - data: empty!(), layer2, } } @@ -464,14 +529,22 @@ impl, L2: Layer2> Wallet { res } - pub fn update(&mut self, indexer: &I) -> MayError<(), Vec> { - // Not yet implemented: - // self.cache.update::(&self.descr, &self.indexer) + pub fn data_l2(&self) -> &L2::Data { &self.data.layer2 } + pub fn cache_l2(&self) -> &L2::Cache { &self.cache.layer2 } - WalletCache::with::<_, K, _, L2>(&self.descr, indexer).map(|cache| { - self.cache = cache; - self.cache.mark_dirty(); - }) + pub fn with_data_l2(&mut self, f: impl FnOnce(&mut L2::Data) -> R) -> R { + let res = f(&mut self.data.layer2); + self.data.mark_dirty(); + res + } + pub fn with_cache_l2(&mut self, f: impl FnOnce(&mut L2::Cache) -> R) -> R { + let res = f(&mut self.cache.layer2); + self.cache.mark_dirty(); + res + } + + pub fn update(&mut self, indexer: &I) -> MayError<(), Vec> { + self.cache.update::(&self.descr, indexer).map(|_| ()) } pub fn to_deriver(&self) -> D @@ -538,7 +611,15 @@ impl, L2: Layer2> Wallet { self.cache.history() } - pub fn all_utxos(&self) -> impl Iterator + '_ { self.cache.all_utxos() } + pub fn has_outpoint(&self, outpoint: Outpoint) -> bool { self.cache.has_outpoint(outpoint) } + pub fn is_unspent(&self, outpoint: Outpoint) -> bool { self.cache.is_unspent(outpoint) } + + pub fn outpoint_by(&self, outpoint: Outpoint) -> Result { + self.cache.outpoint_by(outpoint) + } + + pub fn txos(&self) -> impl Iterator + '_ { self.cache.txos() } + pub fn utxos(&self) -> impl Iterator + '_ { self.cache.utxos() } pub fn coinselect<'a>( &'a self, @@ -546,7 +627,7 @@ impl, L2: Layer2> Wallet { selector: impl Fn(&WalletUtxo) -> bool + 'a, ) -> impl Iterator + '_ { let mut selected = Sats::ZERO; - self.all_utxos() + self.utxos() .filter(selector) .take_while(move |utxo| { if selected <= up_to { @@ -581,6 +662,11 @@ impl, L2: Layer2> Wallet { }) } + pub fn set_id(&mut self, id: &impl ToString) { + self.data.id = Some(id.to_string()); + self.cache.id = Some(id.to_string()); + } + pub fn make_persistent

( &mut self, provider: P,