From 003a8f1b4788d7d97edbc86b05d3435ce81319fa Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Fri, 8 Nov 2024 19:58:07 +0000 Subject: [PATCH 1/2] feat: signature on mint witness --- Cargo.lock | 921 ++++++++++++------ crates/cdk-integration-tests/src/lib.rs | 2 + .../tests/fake_wallet.rs | 105 +- crates/cdk-integration-tests/tests/mint.rs | 2 + crates/cdk-integration-tests/tests/regtest.rs | 7 +- crates/cdk-redb/src/mint/migrations.rs | 1 + .../20241108093102_mint_mint_quote_pubkey.sql | 1 + crates/cdk-sqlite/src/mint/mod.rs | 11 +- ...1108092756_wallet_mint_quote_secretkey.sql | 1 + crates/cdk-sqlite/src/wallet/mod.rs | 13 +- crates/cdk/src/error.rs | 18 +- crates/cdk/src/mint/builder.rs | 3 +- crates/cdk/src/mint/mint_nut04.rs | 9 + crates/cdk/src/mint/types.rs | 6 +- crates/cdk/src/nuts/mod.rs | 1 + crates/cdk/src/nuts/nut04.rs | 16 +- crates/cdk/src/nuts/nut06.rs | 12 + crates/cdk/src/nuts/nut20.rs | 151 +++ crates/cdk/src/wallet/mint.rs | 14 +- crates/cdk/src/wallet/types.rs | 6 +- flake.lock | 12 +- flake.nix | 2 +- 22 files changed, 1013 insertions(+), 301 deletions(-) create mode 100644 crates/cdk-sqlite/src/mint/migrations/20241108093102_mint_mint_quote_pubkey.sql create mode 100644 crates/cdk-sqlite/src/wallet/migrations/20241108092756_wallet_mint_quote_secretkey.sql create mode 100644 crates/cdk/src/nuts/nut20.rs diff --git a/Cargo.lock b/Cargo.lock index b492c5ab..d6ba00ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,13 @@ version = 3 [[package]] name = "addr2line" -version = "0.14.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -169,9 +163,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" dependencies = [ "backtrace", ] @@ -246,7 +240,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -257,7 +251,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -282,7 +276,7 @@ dependencies = [ "futures", "futures-util", "js-sys", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls 0.26.1", "tokio-socks", @@ -330,7 +324,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "itoa", "matchit", "memchr", @@ -343,7 +337,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", "tokio-tungstenite 0.20.1", "tower", @@ -370,17 +364,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.58" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88fb5a785d6b44fd9d6700935608639af1b8356de1e55d5f7c2740f4faa15d82" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.4.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -629,9 +623,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecount" @@ -718,9 +712,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.2" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -750,8 +744,8 @@ dependencies = [ "serde", "serde_json", "serde_with", - "sync_wrapper", - "thiserror", + "sync_wrapper 0.1.2", + "thiserror 1.0.69", "tokio", "tokio-tungstenite 0.19.0", "tracing", @@ -812,7 +806,7 @@ dependencies = [ "cdk", "cln-rpc 0.2.0", "futures", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -831,7 +825,7 @@ dependencies = [ "rand", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-util", @@ -881,7 +875,7 @@ dependencies = [ "cdk", "futures", "lnbits-rs", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -896,7 +890,7 @@ dependencies = [ "cdk", "fedimint-tonic-lnd", "futures", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -946,7 +940,7 @@ dependencies = [ "cdk", "futures", "phoenixd-rs", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -963,7 +957,7 @@ dependencies = [ "redb", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", "uuid", ] @@ -978,7 +972,7 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "web-sys", ] @@ -993,7 +987,7 @@ dependencies = [ "lightning-invoice", "serde_json", "sqlx", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "uuid", @@ -1010,7 +1004,7 @@ dependencies = [ "cdk", "futures", "strike-rs", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-util", "tracing", @@ -1023,6 +1017,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -1049,9 +1049,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1129,7 +1129,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1232,6 +1232,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1309,18 +1319,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1337,18 +1347,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1388,7 +1398,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1399,7 +1409,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1450,6 +1460,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -1510,9 +1531,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fedimint-tonic-lnd" @@ -1522,7 +1543,7 @@ checksum = "df03ca33b5116de3051c1e233fe341e23b04c4913c7b16042497924559bc2a2e" dependencies = [ "hex", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-rustls 0.24.2", "prost", "rustls 0.21.12", @@ -1547,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1570,9 +1591,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "form_urlencoded" @@ -1665,7 +1686,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1723,9 +1744,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.23.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1766,10 +1787,11 @@ dependencies = [ [[package]] name = "half" -version = "2.2.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ + "cfg-if", "crunchy", ] @@ -1877,11 +1899,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1960,9 +1982,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -1984,9 +2006,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -2009,7 +2031,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -2017,19 +2039,21 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.2.0", - "hyper 1.5.1", + "hyper 1.5.2", "hyper-util", - "rustls 0.22.4", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.1", "tower-service", + "webpki-roots 0.26.7", ] [[package]] @@ -2038,7 +2062,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.31", + "hyper 0.14.32", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2055,7 +2079,7 @@ dependencies = [ "futures-util", "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.1", + "hyper 1.5.2", "pin-project-lite", "socket2 0.5.8", "tokio", @@ -2086,6 +2110,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "idb" version = "0.6.4" @@ -2094,7 +2236,7 @@ checksum = "3afe8830d5802f769dc0be20a87f9f116798c896650cb6266eb5c19a3c109eed" dependencies = [ "js-sys", "num-traits", - "thiserror", + "thiserror 1.0.69", "tokio", "wasm-bindgen", "web-sys", @@ -2108,12 +2250,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2229,9 +2382,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", @@ -2268,9 +2421,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libredox" @@ -2334,6 +2487,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "ln-regtest-rs" version = "0.1.0" @@ -2448,19 +2607,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] @@ -2478,20 +2627,20 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "moka" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36506f2f935238463605f3bb13b362f1949daafc3b347d05d60ae08836db2bd2" +checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" dependencies = [ "async-io", "async-lock", @@ -2499,7 +2648,6 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "futures-util", - "num_cpus", "once_cell", "parking_lot 0.12.3", "quanta", @@ -2508,7 +2656,7 @@ dependencies = [ "skeptic", "smallvec", "tagptr", - "thiserror", + "thiserror 1.0.69", "triomphe", "uuid", ] @@ -2576,7 +2724,7 @@ dependencies = [ "async-trait", "lru", "nostr", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -2594,7 +2742,7 @@ dependencies = [ "negentropy 0.4.3", "nostr", "nostr-database", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -2612,7 +2760,7 @@ dependencies = [ "nostr-database", "nostr-relay-pool", "nostr-signer", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -2625,7 +2773,7 @@ checksum = "c1e132975a677a1c97a7695ef1161291dc06517a588b6e17e3aa05d3fb4056a0" dependencies = [ "async-utility", "nostr", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -2684,21 +2832,14 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "object" -version = "0.23.0" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] [[package]] name = "once_cell" @@ -2795,7 +2936,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec", "windows-targets 0.52.6", ] @@ -2841,20 +2982,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror", + "thiserror 2.0.9", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -2862,22 +3003,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -2907,7 +3048,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -2928,7 +3069,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3026,7 +3167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3089,7 +3230,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.90", + "syn 2.0.91", "tempfile", ] @@ -3103,7 +3244,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3142,6 +3283,58 @@ dependencies = [ "winapi", ] +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.20", + "socket2 0.5.8", + "thiserror 2.0.9", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls 0.23.20", + "rustls-pki-types", + "slab", + "thiserror 2.0.9", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.8", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.37" @@ -3212,9 +3405,9 @@ dependencies = [ [[package]] name = "redb" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b1de48a7cf7ba193e81e078d17ee2b786236eed1d3f7c60f8a09545efc4925" +checksum = "a7c2a94325f9c5826b17c42af11067230f503747f870117a28180e85696e21ba" dependencies = [ "libc", ] @@ -3254,9 +3447,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -3269,19 +3462,19 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -3295,13 +3488,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.5", ] [[package]] @@ -3312,15 +3505,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "async-compression", "base64 0.22.1", @@ -3330,8 +3523,8 @@ dependencies = [ "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", - "hyper-rustls 0.26.0", + "hyper 1.5.2", + "hyper-rustls 0.27.5", "hyper-util", "ipnet", "js-sys", @@ -3340,16 +3533,17 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", - "rustls-native-certs 0.7.3", + "quinn", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.1", "tokio-socks", "tokio-util", "tower-service", @@ -3358,7 +3552,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "webpki-roots 0.26.7", - "winreg", + "windows-registry", ] [[package]] @@ -3368,7 +3562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "887466cfa8a12c08ee4b174998135cea8ff0fd84858627cd793e56535a045bc9" dependencies = [ "idb", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", ] @@ -3434,7 +3628,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.90", + "syn 2.0.91", "walkdir", ] @@ -3464,6 +3658,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3489,15 +3689,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3526,23 +3726,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring 0.17.8", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" -version = "0.23.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring 0.17.8", @@ -3561,20 +3747,19 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.1.0", ] [[package]] @@ -3597,9 +3782,12 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -3746,7 +3934,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -3754,9 +3955,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -3764,9 +3965,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] @@ -3779,9 +3980,9 @@ checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -3799,20 +4000,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "indexmap 2.7.0", "itoa", @@ -3845,15 +4046,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.1.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", + "indexmap 2.7.0", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -3861,14 +4064,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.1.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3cee93715c2e266b9338b7544da68a9f24e227722ba482bd1c024367c77c65" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -4057,7 +4260,7 @@ dependencies = [ "sqlformat", "sqlx-rt", "stringprep", - "thiserror", + "thiserror 1.0.69", "tokio-stream", "url", "uuid", @@ -4094,6 +4297,12 @@ dependencies = [ "tokio-rustls 0.23.4", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strike-rs" version = "0.4.0" @@ -4104,14 +4313,14 @@ dependencies = [ "async-trait", "axum", "http-body-util", - "hyper 0.14.31", + "hyper 0.14.32", "log", "rand", "reqwest", "ring 0.17.8", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tower", "tower-http", @@ -4153,9 +4362,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -4168,6 +4377,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4181,9 +4410,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", - "fastrand 2.2.0", + "fastrand 2.3.0", "once_cell", - "rustix 0.38.41", + "rustix 0.38.42", "windows-sys 0.59.0", ] @@ -4193,7 +4422,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", ] [[package]] @@ -4204,7 +4442,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", ] [[package]] @@ -4248,6 +4497,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4260,9 +4519,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -4275,21 +4534,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2 0.5.8", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4304,13 +4562,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -4334,24 +4592,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.19", + "rustls 0.23.20", "tokio", ] @@ -4363,15 +4610,15 @@ checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -4413,7 +4660,7 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pki-types", "tokio", "tokio-rustls 0.26.1", @@ -4423,9 +4670,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -4457,7 +4704,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-timeout", "percent-encoding", "pin-project", @@ -4483,7 +4730,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -4560,7 +4807,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -4604,9 +4851,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" [[package]] name = "try-lock" @@ -4629,7 +4876,7 @@ dependencies = [ "rand", "rustls 0.21.12", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", "webpki", @@ -4649,7 +4896,7 @@ dependencies = [ "log", "rand", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", ] @@ -4667,10 +4914,10 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.69", "utf-8", ] @@ -4694,9 +4941,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" @@ -4755,9 +5002,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -4771,6 +5018,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -4798,7 +5057,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -4878,9 +5137,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -4889,24 +5148,23 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.47" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", @@ -4917,9 +5175,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4927,28 +5185,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -5022,6 +5290,36 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5171,14 +5469,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "winreg" -version = "0.52.0" +name = "write16" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yaml-rust" @@ -5189,6 +5489,30 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -5207,7 +5531,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", + "synstructure", ] [[package]] @@ -5216,6 +5561,28 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.91", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/crates/cdk-integration-tests/src/lib.rs b/crates/cdk-integration-tests/src/lib.rs index abca88bb..3e7c282f 100644 --- a/crates/cdk-integration-tests/src/lib.rs +++ b/crates/cdk-integration-tests/src/lib.rs @@ -160,6 +160,7 @@ pub async fn mint_proofs( amount, unit: CurrencyUnit::Sat, description, + pubkey: None, }; let mint_quote = wallet_client.post_mint_quote(request).await?; @@ -192,6 +193,7 @@ pub async fn mint_proofs( let request = MintBolt11Request { quote: mint_quote.quote, outputs: premint_secrets.blinded_messages(), + signature: None, }; let mint_response = wallet_client.post_mint(request).await?; diff --git a/crates/cdk-integration-tests/tests/fake_wallet.rs b/crates/cdk-integration-tests/tests/fake_wallet.rs index 8f34ada7..5febfdd0 100644 --- a/crates/cdk-integration-tests/tests/fake_wallet.rs +++ b/crates/cdk-integration-tests/tests/fake_wallet.rs @@ -1,12 +1,12 @@ use std::sync::Arc; -use anyhow::Result; +use anyhow::{bail, Result}; use bip39::Mnemonic; use cdk::amount::SplitTarget; use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::{ - CurrencyUnit, MeltBolt11Request, MeltQuoteState, MintQuoteState, NotificationPayload, - PreMintSecrets, State, + CurrencyUnit, MeltBolt11Request, MeltQuoteState, MintBolt11Request, MintQuoteState, + NotificationPayload, PreMintSecrets, SecretKey, State, }; use cdk::wallet::client::{HttpClient, MintConnector}; use cdk::wallet::{Wallet, WalletSubscription}; @@ -376,6 +376,105 @@ async fn test_fake_melt_change_in_quote() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_fake_mint_with_witness() -> Result<()> { + let wallet = Wallet::new( + MINT_URL, + CurrencyUnit::Sat, + Arc::new(WalletMemoryDatabase::default()), + &Mnemonic::generate(12)?.to_seed_normalized(""), + None, + )?; + let mint_quote = wallet.mint_quote(100.into(), None).await?; + + wait_for_mint_to_be_paid(&wallet, &mint_quote.id).await?; + + let mint_amount = wallet + .mint(&mint_quote.id, SplitTarget::default(), None) + .await?; + + assert!(mint_amount == 100.into()); + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_fake_mint_without_witness() -> Result<()> { + let wallet = Wallet::new( + MINT_URL, + CurrencyUnit::Sat, + Arc::new(WalletMemoryDatabase::default()), + &Mnemonic::generate(12)?.to_seed_normalized(""), + None, + )?; + + let mint_quote = wallet.mint_quote(100.into(), None).await?; + + wait_for_mint_to_be_paid(&wallet, &mint_quote.id).await?; + + let http_client = HttpClient::new(MINT_URL.parse()?); + + let active_keyset_id = wallet.get_active_mint_keyset().await?.id; + + let premint_secrets = + PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::default()).unwrap(); + + let request = MintBolt11Request { + quote: mint_quote.id, + outputs: premint_secrets.blinded_messages(), + signature: None, + }; + + let response = http_client.post_mint(request.clone()).await; + + match response { + Err(cdk::error::Error::SignatureMissingOrInvalid) => Ok(()), + Err(err) => bail!("Wrong mint response for minting without witness: {}", err), + Ok(_) => bail!("Minting should not have succeed without a witness"), + } +} + +// TODO: Rewrite this test to include witness wrong +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_fake_mint_with_wrong_witness() -> Result<()> { + let wallet = Wallet::new( + MINT_URL, + CurrencyUnit::Sat, + Arc::new(WalletMemoryDatabase::default()), + &Mnemonic::generate(12)?.to_seed_normalized(""), + None, + )?; + + let mint_quote = wallet.mint_quote(100.into(), None).await?; + + wait_for_mint_to_be_paid(&wallet, &mint_quote.id).await?; + + let http_client = HttpClient::new(MINT_URL.parse()?); + + let active_keyset_id = wallet.get_active_mint_keyset().await?.id; + + let premint_secrets = + PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::default()).unwrap(); + + let mut request = MintBolt11Request { + quote: mint_quote.id, + outputs: premint_secrets.blinded_messages(), + signature: None, + }; + + let secret_key = SecretKey::generate(); + + request.sign(secret_key)?; + + let response = http_client.post_mint(request.clone()).await; + + match response { + Err(cdk::error::Error::SignatureMissingOrInvalid) => Ok(()), + Err(err) => bail!("Wrong mint response for minting without witness: {}", err), + Ok(_) => bail!("Minting should not have succeed without a witness"), + } +} + // Keep polling the state of the mint quote id until it's paid async fn wait_for_mint_to_be_paid(wallet: &Wallet, mint_quote_id: &str) -> Result<()> { let mut subscription = wallet diff --git a/crates/cdk-integration-tests/tests/mint.rs b/crates/cdk-integration-tests/tests/mint.rs index 2bcd281a..af14a7ab 100644 --- a/crates/cdk-integration-tests/tests/mint.rs +++ b/crates/cdk-integration-tests/tests/mint.rs @@ -78,6 +78,7 @@ async fn mint_proofs( amount, unix_time() + 36000, request_lookup.to_string(), + None, ); mint.localstore.add_mint_quote(quote.clone()).await?; @@ -90,6 +91,7 @@ async fn mint_proofs( let mint_request = MintBolt11Request { quote: quote.id, outputs: premint.blinded_messages(), + signature: None, }; let after_mint = mint.process_mint_request(mint_request).await?; diff --git a/crates/cdk-integration-tests/tests/regtest.rs b/crates/cdk-integration-tests/tests/regtest.rs index bbfb51fd..71f3b7fb 100644 --- a/crates/cdk-integration-tests/tests/regtest.rs +++ b/crates/cdk-integration-tests/tests/regtest.rs @@ -381,11 +381,16 @@ async fn test_cached_mint() -> Result<()> { let premint_secrets = PreMintSecrets::random(active_keyset_id, 31.into(), &SplitTarget::default()).unwrap(); - let request = MintBolt11Request { + let mut request = MintBolt11Request { quote: quote.id, outputs: premint_secrets.blinded_messages(), + signature: None, }; + let secret_key = quote.secret_key; + + request.sign(secret_key.expect("Secret key on quote"))?; + let response = http_client.post_mint(request.clone()).await?; let response1 = http_client.post_mint(request).await?; diff --git a/crates/cdk-redb/src/mint/migrations.rs b/crates/cdk-redb/src/mint/migrations.rs index 40e5681e..48b2ae68 100644 --- a/crates/cdk-redb/src/mint/migrations.rs +++ b/crates/cdk-redb/src/mint/migrations.rs @@ -210,6 +210,7 @@ impl From for MintQuote { state: quote.state, expiry: quote.expiry, request_lookup_id: Bolt11Invoice::from_str("e.request).unwrap().to_string(), + pubkey: None, } } } diff --git a/crates/cdk-sqlite/src/mint/migrations/20241108093102_mint_mint_quote_pubkey.sql b/crates/cdk-sqlite/src/mint/migrations/20241108093102_mint_mint_quote_pubkey.sql new file mode 100644 index 00000000..06501e14 --- /dev/null +++ b/crates/cdk-sqlite/src/mint/migrations/20241108093102_mint_mint_quote_pubkey.sql @@ -0,0 +1 @@ +ALTER TABLE mint_quote ADD pubkey TEXT; diff --git a/crates/cdk-sqlite/src/mint/mod.rs b/crates/cdk-sqlite/src/mint/mod.rs index 203b1ab5..009a5295 100644 --- a/crates/cdk-sqlite/src/mint/mod.rs +++ b/crates/cdk-sqlite/src/mint/mod.rs @@ -207,8 +207,8 @@ WHERE active = 1 let res = sqlx::query( r#" INSERT OR REPLACE INTO mint_quote -(id, mint_url, amount, unit, request, state, expiry, request_lookup_id) -VALUES (?, ?, ?, ?, ?, ?, ?, ?); +(id, mint_url, amount, unit, request, state, expiry, request_lookup_id, pubkey) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?); "#, ) .bind(quote.id.to_string()) @@ -219,6 +219,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?); .bind(quote.state.to_string()) .bind(quote.expiry as i64) .bind(quote.request_lookup_id) + .bind(quote.pubkey.map(|p| p.to_string())) .execute(&mut transaction) .await; @@ -1265,6 +1266,7 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result { let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?; let row_request_lookup_id: Option = row.try_get("request_lookup_id").map_err(Error::from)?; + let row_pubkey: Option = row.try_get("pubkey").map_err(Error::from)?; let request_lookup_id = match row_request_lookup_id { Some(id) => id, @@ -1274,6 +1276,10 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result { }, }; + let pubkey = row_pubkey + .map(|key| PublicKey::from_str(&key)) + .transpose()?; + Ok(MintQuote { id: row_id.into_uuid(), mint_url: MintUrl::from_str(&row_mint_url)?, @@ -1283,6 +1289,7 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result { state: MintQuoteState::from_str(&row_state).map_err(Error::from)?, expiry: row_expiry as u64, request_lookup_id, + pubkey, }) } diff --git a/crates/cdk-sqlite/src/wallet/migrations/20241108092756_wallet_mint_quote_secretkey.sql b/crates/cdk-sqlite/src/wallet/migrations/20241108092756_wallet_mint_quote_secretkey.sql new file mode 100644 index 00000000..58b60b82 --- /dev/null +++ b/crates/cdk-sqlite/src/wallet/migrations/20241108092756_wallet_mint_quote_secretkey.sql @@ -0,0 +1 @@ +ALTER TABLE mint_quote ADD secret_key TEXT; diff --git a/crates/cdk-sqlite/src/wallet/mod.rs b/crates/cdk-sqlite/src/wallet/mod.rs index b2480ee1..e85d506f 100644 --- a/crates/cdk-sqlite/src/wallet/mod.rs +++ b/crates/cdk-sqlite/src/wallet/mod.rs @@ -10,7 +10,7 @@ use cdk::cdk_database::{self, WalletDatabase}; use cdk::mint_url::MintUrl; use cdk::nuts::{ CurrencyUnit, Id, KeySetInfo, Keys, MeltQuoteState, MintInfo, MintQuoteState, Proof, PublicKey, - SpendingConditions, State, + SecretKey, SpendingConditions, State, }; use cdk::secret::Secret; use cdk::types::ProofInfo; @@ -347,8 +347,8 @@ WHERE id=? sqlx::query( r#" INSERT OR REPLACE INTO mint_quote -(id, mint_url, amount, unit, request, state, expiry) -VALUES (?, ?, ?, ?, ?, ?, ?); +(id, mint_url, amount, unit, request, state, expiry, secret_key) +VALUES (?, ?, ?, ?, ?, ?, ?, ?); "#, ) .bind(quote.id.to_string()) @@ -358,6 +358,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?); .bind(quote.request) .bind(quote.state.to_string()) .bind(quote.expiry as i64) + .bind(quote.secret_key.map(|p| p.to_string())) .execute(&self.pool) .await .map_err(Error::from)?; @@ -832,9 +833,14 @@ fn sqlite_row_to_mint_quote(row: &SqliteRow) -> Result { let row_request: String = row.try_get("request").map_err(Error::from)?; let row_state: String = row.try_get("state").map_err(Error::from)?; let row_expiry: i64 = row.try_get("expiry").map_err(Error::from)?; + let row_secret: Option = row.try_get("secret_key").map_err(Error::from)?; let state = MintQuoteState::from_str(&row_state)?; + let secret_key = row_secret + .map(|key| SecretKey::from_str(&key)) + .transpose()?; + Ok(MintQuote { id: row_id, mint_url: MintUrl::from_str(&row_mint_url)?, @@ -843,6 +849,7 @@ fn sqlite_row_to_mint_quote(row: &SqliteRow) -> Result { request: row_request, state, expiry: row_expiry as u64, + secret_key, }) } diff --git a/crates/cdk/src/error.rs b/crates/cdk/src/error.rs index dae63c64..b89e30d6 100644 --- a/crates/cdk/src/error.rs +++ b/crates/cdk/src/error.rs @@ -45,6 +45,9 @@ pub enum Error { /// Amount overflow #[error("Amount Overflow")] AmountOverflow, + /// Witness missing or invalid + #[error("Signature missing or invalid")] + SignatureMissingOrInvalid, // Mint Errors /// Minting is disabled @@ -176,7 +179,7 @@ pub enum Error { /// Parse int error #[error(transparent)] ParseInt(#[from] std::num::ParseIntError), - /// Parse Url Error + /// Parse 9rl Error #[error(transparent)] UrlParseError(#[from] url::ParseError), /// Utf8 parse error @@ -239,6 +242,9 @@ pub enum Error { /// NUT18 Error #[error(transparent)] NUT18(#[from] crate::nuts::nut18::Error), + /// NUT20 Error + #[error(transparent)] + NUT20(#[from] crate::nuts::nut20::Error), /// Database Error #[cfg(any(feature = "wallet", feature = "mint"))] #[error(transparent)] @@ -373,6 +379,11 @@ impl From for ErrorResponse { error: Some(err.to_string()), detail: None, }, + Error::NUT20(err) => ErrorResponse { + code: ErrorCode::WitnessMissingOrInvalid, + error: Some(err.to_string()), + detail: None, + }, _ => ErrorResponse { code: ErrorCode::Unknown(9999), error: Some(err.to_string()), @@ -402,6 +413,7 @@ impl From for Error { Self::AmountOutofLimitRange(Amount::default(), Amount::default(), Amount::default()) } ErrorCode::TokenPending => Self::TokenPending, + ErrorCode::WitnessMissingOrInvalid => Self::SignatureMissingOrInvalid, _ => Self::UnknownErrorResponse(err.to_string()), } } @@ -443,6 +455,8 @@ pub enum ErrorCode { TransactionUnbalanced, /// Amount outside of allowed range AmountOutofLimitRange, + /// Witness missing or invalid + WitnessMissingOrInvalid, /// Unknown error code Unknown(u16), } @@ -467,6 +481,7 @@ impl ErrorCode { 20005 => Self::QuotePending, 20006 => Self::InvoiceAlreadyPaid, 20007 => Self::QuoteExpired, + 20008 => Self::WitnessMissingOrInvalid, _ => Self::Unknown(code), } } @@ -490,6 +505,7 @@ impl ErrorCode { Self::QuotePending => 20005, Self::InvoiceAlreadyPaid => 20006, Self::QuoteExpired => 20007, + Self::WitnessMissingOrInvalid => 20008, Self::Unknown(code) => *code, } } diff --git a/crates/cdk/src/mint/builder.rs b/crates/cdk/src/mint/builder.rs index 689d4e91..b61ae8e0 100644 --- a/crates/cdk/src/mint/builder.rs +++ b/crates/cdk/src/mint/builder.rs @@ -46,7 +46,8 @@ impl MintBuilder { .nut10(true) .nut11(true) .nut12(true) - .nut14(true); + .nut14(true) + .nut20(true); builder.mint_info.nuts = nuts; diff --git a/crates/cdk/src/mint/mint_nut04.rs b/crates/cdk/src/mint/mint_nut04.rs index 5b401292..f456864e 100644 --- a/crates/cdk/src/mint/mint_nut04.rs +++ b/crates/cdk/src/mint/mint_nut04.rs @@ -65,6 +65,7 @@ impl Mint { amount, unit, description, + pubkey, } = mint_quote_request; self.check_mint_request_acceptable(amount, &unit)?; @@ -105,6 +106,7 @@ impl Mint { amount, create_invoice_response.expiry.unwrap_or(0), create_invoice_response.request_lookup_id.clone(), + pubkey, ); tracing::debug!( @@ -150,6 +152,7 @@ impl Mint { request: quote.request, state, expiry: Some(quote.expiry), + pubkey: quote.pubkey, }) } @@ -281,6 +284,12 @@ impl Mint { MintQuoteState::Paid => (), } + // If the there is a public key provoided in mint quote request + // verify the signature is provided for the mint request + if let Some(pubkey) = mint_quote.pubkey { + mint_request.verify_signature(pubkey)?; + } + let blinded_messages: Vec = mint_request .outputs .iter() diff --git a/crates/cdk/src/mint/types.rs b/crates/cdk/src/mint/types.rs index ad099c4c..737d23b3 100644 --- a/crates/cdk/src/mint/types.rs +++ b/crates/cdk/src/mint/types.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; -use super::CurrencyUnit; +use super::{CurrencyUnit, PublicKey}; use crate::mint_url::MintUrl; use crate::nuts::{MeltQuoteState, MintQuoteState}; use crate::Amount; @@ -27,6 +27,8 @@ pub struct MintQuote { pub expiry: u64, /// Value used by ln backend to look up state of request pub request_lookup_id: String, + /// Pubkey + pub pubkey: Option, } impl MintQuote { @@ -38,6 +40,7 @@ impl MintQuote { amount: Amount, expiry: u64, request_lookup_id: String, + pubkey: Option, ) -> Self { let id = Uuid::new_v4(); @@ -50,6 +53,7 @@ impl MintQuote { state: MintQuoteState::Unpaid, expiry, request_lookup_id, + pubkey, } } } diff --git a/crates/cdk/src/nuts/mod.rs b/crates/cdk/src/nuts/mod.rs index 0f3bc525..61d88fc9 100644 --- a/crates/cdk/src/nuts/mod.rs +++ b/crates/cdk/src/nuts/mod.rs @@ -21,6 +21,7 @@ pub mod nut15; pub mod nut17; pub mod nut18; pub mod nut19; +pub mod nut20; pub use nut00::{ BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod, PreMint, PreMintSecrets, Proof, diff --git a/crates/cdk/src/nuts/nut04.rs b/crates/cdk/src/nuts/nut04.rs index 9d1c6116..0eda1b7a 100644 --- a/crates/cdk/src/nuts/nut04.rs +++ b/crates/cdk/src/nuts/nut04.rs @@ -12,7 +12,7 @@ use thiserror::Error; use uuid::Uuid; use super::nut00::{BlindSignature, BlindedMessage, CurrencyUnit, PaymentMethod}; -use super::MintQuoteState; +use super::{MintQuoteState, PublicKey}; use crate::Amount; /// NUT04 Error @@ -35,7 +35,11 @@ pub struct MintQuoteBolt11Request { /// Unit wallet would like to pay with pub unit: CurrencyUnit, /// Memo to create the invoice with + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + /// NUT-19 Pubkey + #[serde(skip_serializing_if = "Option::is_none")] + pub pubkey: Option, } /// Possible states of a quote @@ -94,6 +98,9 @@ pub struct MintQuoteBolt11Response { pub state: MintQuoteState, /// Unix timestamp until the quote is valid pub expiry: Option, + /// NUT-19 Pubkey + #[serde(skip_serializing_if = "Option::is_none")] + pub pubkey: Option, } impl MintQuoteBolt11Response { @@ -104,6 +111,7 @@ impl MintQuoteBolt11Response { request: self.request.clone(), state: self.state, expiry: self.expiry, + pubkey: self.pubkey, } } } @@ -116,6 +124,7 @@ impl From> for MintQuoteBolt11Response { request: value.request, state: value.state, expiry: value.expiry, + pubkey: value.pubkey, } } } @@ -128,6 +137,7 @@ impl From for MintQuoteBolt11Response { request: mint_quote.request, state: mint_quote.state, expiry: Some(mint_quote.expiry), + pubkey: mint_quote.pubkey, } } } @@ -143,6 +153,9 @@ pub struct MintBolt11Request { /// Outputs #[cfg_attr(feature = "swagger", schema(max_items = 1_000))] pub outputs: Vec, + /// Signature + #[serde(skip_serializing_if = "Option::is_none")] + pub signature: Option, } #[cfg(feature = "mint")] @@ -153,6 +166,7 @@ impl TryFrom> for MintBolt11Request { Ok(Self { quote: Uuid::from_str(&value.quote)?, outputs: value.outputs, + signature: value.signature, }) } } diff --git a/crates/cdk/src/nuts/nut06.rs b/crates/cdk/src/nuts/nut06.rs index f1667b48..f001716b 100644 --- a/crates/cdk/src/nuts/nut06.rs +++ b/crates/cdk/src/nuts/nut06.rs @@ -247,6 +247,10 @@ pub struct Nuts { #[serde(default)] #[serde(rename = "19")] pub nut19: nut19::Settings, + /// NUT20 Settings + #[serde(default)] + #[serde(rename = "20")] + pub nut20: SupportedSettings, } impl Nuts { @@ -356,6 +360,14 @@ impl Nuts { ..self } } + + /// Nut20 settings + pub fn nut20(self, supported: bool) -> Self { + Self { + nut20: SupportedSettings { supported }, + ..self + } + } } /// Check state Settings diff --git a/crates/cdk/src/nuts/nut20.rs b/crates/cdk/src/nuts/nut20.rs new file mode 100644 index 00000000..d3890e17 --- /dev/null +++ b/crates/cdk/src/nuts/nut20.rs @@ -0,0 +1,151 @@ +//! Mint Quote Signatures + +use std::str::FromStr; + +use bitcoin::secp256k1::schnorr::Signature; +use thiserror::Error; + +use super::{MintBolt11Request, PublicKey, SecretKey}; + +/// Nut19 Error +#[derive(Debug, Error)] +pub enum Error { + /// Signature not provided + #[error("Signature not provided")] + SignatureMissing, + /// Quote signature invalid signature + #[error("Quote signature invalid signature")] + InvalidSignature, + /// Nut01 error + #[error(transparent)] + NUT01(#[from] crate::nuts::nut01::Error), +} + +impl MintBolt11Request +where + Q: ToString, +{ + /// Constructs the message to be signed according to NUT-20 specification. + /// + /// The message is constructed by concatenating (as UTF-8 encoded bytes): + /// 1. The quote ID (as UTF-8) + /// 2. All blinded secrets (B_0 through B_n) converted to hex strings (as UTF-8) + /// + /// Format: `quote_id || B_0 || B_1 || ... || B_n` + /// where each component is encoded as UTF-8 bytes + pub fn msg_to_sign(&self) -> Vec { + // Pre-calculate capacity to avoid reallocations + let quote_id = self.quote.to_string(); + let capacity = quote_id.len() + (self.outputs.len() * 66); + let mut msg = Vec::with_capacity(capacity); + msg.append(&mut quote_id.clone().into_bytes()); // String.into_bytes() produces UTF-8 + for output in &self.outputs { + // to_hex() creates a hex string, into_bytes() converts it to UTF-8 bytes + msg.append(&mut output.blinded_secret.to_hex().into_bytes()); + } + msg + } + + /// Sign [`MintBolt11Request`] + pub fn sign(&mut self, secret_key: SecretKey) -> Result<(), Error> { + let msg = self.msg_to_sign(); + + let signature: Signature = secret_key.sign(&msg)?; + + self.signature = Some(signature.to_string()); + + Ok(()) + } + + /// Verify signature on [`MintBolt11Request`] + pub fn verify_signature(&self, pubkey: PublicKey) -> Result<(), Error> { + let signature = self.signature.as_ref().ok_or(Error::SignatureMissing)?; + + let signature = Signature::from_str(signature).map_err(|_| Error::InvalidSignature)?; + + let msg_to_sign = self.msg_to_sign(); + + pubkey.verify(&msg_to_sign, &signature)?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use uuid::Uuid; + + use super::*; + + #[test] + fn test_msg_to_sign() { + let request: MintBolt11Request = serde_json::from_str(r#"{"quote":"9d745270-1405-46de-b5c5-e2762b4f5e00","outputs":[{"amount":1,"id":"00456a94ab4e1c46","B_":"0342e5bcc77f5b2a3c2afb40bb591a1e27da83cddc968abdc0ec4904201a201834"},{"amount":1,"id":"00456a94ab4e1c46","B_":"032fd3c4dc49a2844a89998d5e9d5b0f0b00dde9310063acb8a92e2fdafa4126d4"},{"amount":1,"id":"00456a94ab4e1c46","B_":"033b6fde50b6a0dfe61ad148fff167ad9cf8308ded5f6f6b2fe000a036c464c311"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02be5a55f03e5c0aaea77595d574bce92c6d57a2a0fb2b5955c0b87e4520e06b53"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02209fc2873f28521cbdde7f7b3bb1521002463f5979686fd156f23fe6a8aa2b79"}],"signature":"cb2b8e7ea69362dfe2a07093f2bbc319226db33db2ef686c940b5ec976bcbfc78df0cd35b3e998adf437b09ee2c950bd66dfe9eb64abd706e43ebc7c669c36c3"}"#).unwrap(); + + // let expected_msg_to_sign = "9d745270-1405-46de-b5c5-e2762b4f5e000342e5bcc77f5b2a3c2afb40bb591a1e27da83cddc968abdc0ec4904201a201834032fd3c4dc49a2844a89998d5e9d5b0f0b00dde9310063acb8a92e2fdafa4126d4033b6fde50b6a0dfe61ad148fff167ad9cf8308ded5f6f6b2fe000a036c464c31102be5a55f03e5c0aaea77595d574bce92c6d57a2a0fb2b5955c0b87e4520e06b5302209fc2873f28521cbdde7f7b3bb1521002463f5979686fd156f23fe6a8aa2b79"; + + let expected_msg_to_sign = [ + 57, 100, 55, 52, 53, 50, 55, 48, 45, 49, 52, 48, 53, 45, 52, 54, 100, 101, 45, 98, 53, + 99, 53, 45, 101, 50, 55, 54, 50, 98, 52, 102, 53, 101, 48, 48, 48, 51, 52, 50, 101, 53, + 98, 99, 99, 55, 55, 102, 53, 98, 50, 97, 51, 99, 50, 97, 102, 98, 52, 48, 98, 98, 53, + 57, 49, 97, 49, 101, 50, 55, 100, 97, 56, 51, 99, 100, 100, 99, 57, 54, 56, 97, 98, + 100, 99, 48, 101, 99, 52, 57, 48, 52, 50, 48, 49, 97, 50, 48, 49, 56, 51, 52, 48, 51, + 50, 102, 100, 51, 99, 52, 100, 99, 52, 57, 97, 50, 56, 52, 52, 97, 56, 57, 57, 57, 56, + 100, 53, 101, 57, 100, 53, 98, 48, 102, 48, 98, 48, 48, 100, 100, 101, 57, 51, 49, 48, + 48, 54, 51, 97, 99, 98, 56, 97, 57, 50, 101, 50, 102, 100, 97, 102, 97, 52, 49, 50, 54, + 100, 52, 48, 51, 51, 98, 54, 102, 100, 101, 53, 48, 98, 54, 97, 48, 100, 102, 101, 54, + 49, 97, 100, 49, 52, 56, 102, 102, 102, 49, 54, 55, 97, 100, 57, 99, 102, 56, 51, 48, + 56, 100, 101, 100, 53, 102, 54, 102, 54, 98, 50, 102, 101, 48, 48, 48, 97, 48, 51, 54, + 99, 52, 54, 52, 99, 51, 49, 49, 48, 50, 98, 101, 53, 97, 53, 53, 102, 48, 51, 101, 53, + 99, 48, 97, 97, 101, 97, 55, 55, 53, 57, 53, 100, 53, 55, 52, 98, 99, 101, 57, 50, 99, + 54, 100, 53, 55, 97, 50, 97, 48, 102, 98, 50, 98, 53, 57, 53, 53, 99, 48, 98, 56, 55, + 101, 52, 53, 50, 48, 101, 48, 54, 98, 53, 51, 48, 50, 50, 48, 57, 102, 99, 50, 56, 55, + 51, 102, 50, 56, 53, 50, 49, 99, 98, 100, 100, 101, 55, 102, 55, 98, 51, 98, 98, 49, + 53, 50, 49, 48, 48, 50, 52, 54, 51, 102, 53, 57, 55, 57, 54, 56, 54, 102, 100, 49, 53, + 54, 102, 50, 51, 102, 101, 54, 97, 56, 97, 97, 50, 98, 55, 57, + ] + .to_vec(); + + let request_msg_to_sign = request.msg_to_sign(); + + assert_eq!(expected_msg_to_sign, request_msg_to_sign); + } + + #[test] + fn test_valid_signature() { + let pubkey = PublicKey::from_hex( + "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac", + ) + .unwrap(); + + let request: MintBolt11Request = serde_json::from_str(r#"{"quote":"9d745270-1405-46de-b5c5-e2762b4f5e00","outputs":[{"amount":1,"id":"00456a94ab4e1c46","B_":"0342e5bcc77f5b2a3c2afb40bb591a1e27da83cddc968abdc0ec4904201a201834"},{"amount":1,"id":"00456a94ab4e1c46","B_":"032fd3c4dc49a2844a89998d5e9d5b0f0b00dde9310063acb8a92e2fdafa4126d4"},{"amount":1,"id":"00456a94ab4e1c46","B_":"033b6fde50b6a0dfe61ad148fff167ad9cf8308ded5f6f6b2fe000a036c464c311"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02be5a55f03e5c0aaea77595d574bce92c6d57a2a0fb2b5955c0b87e4520e06b53"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02209fc2873f28521cbdde7f7b3bb1521002463f5979686fd156f23fe6a8aa2b79"}], "signature": "d4b386f21f7aa7172f0994ee6e4dd966539484247ea71c99b81b8e09b1bb2acbc0026a43c221fd773471dc30d6a32b04692e6837ddaccf0830a63128308e4ee0"}"#).unwrap(); + + assert!(request.verify_signature(pubkey).is_ok()); + } + + #[test] + fn test_mint_request_signature() { + let mut request: MintBolt11Request = serde_json::from_str(r#"{"quote":"9d745270-1405-46de-b5c5-e2762b4f5e00","outputs":[{"amount":1,"id":"00456a94ab4e1c46","B_":"0342e5bcc77f5b2a3c2afb40bb591a1e27da83cddc968abdc0ec4904201a201834"},{"amount":1,"id":"00456a94ab4e1c46","B_":"032fd3c4dc49a2844a89998d5e9d5b0f0b00dde9310063acb8a92e2fdafa4126d4"},{"amount":1,"id":"00456a94ab4e1c46","B_":"033b6fde50b6a0dfe61ad148fff167ad9cf8308ded5f6f6b2fe000a036c464c311"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02be5a55f03e5c0aaea77595d574bce92c6d57a2a0fb2b5955c0b87e4520e06b53"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02209fc2873f28521cbdde7f7b3bb1521002463f5979686fd156f23fe6a8aa2b79"}]}"#).unwrap(); + + let secret = + SecretKey::from_hex("50d7fd7aa2b2fe4607f41f4ce6f8794fc184dd47b8cdfbe4b3d1249aa02d35aa") + .unwrap(); + + request.sign(secret.clone()).unwrap(); + + assert!(request.verify_signature(secret.public_key()).is_ok()); + } + + #[test] + fn test_invalid_signature() { + let pubkey = PublicKey::from_hex( + "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac", + ) + .unwrap(); + + let request: MintBolt11Request = serde_json::from_str(r#"{"quote":"9d745270-1405-46de-b5c5-e2762b4f5e00","outputs":[{"amount":1,"id":"00456a94ab4e1c46","B_":"0342e5bcc77f5b2a3c2afb40bb591a1e27da83cddc968abdc0ec4904201a201834"},{"amount":1,"id":"00456a94ab4e1c46","B_":"032fd3c4dc49a2844a89998d5e9d5b0f0b00dde9310063acb8a92e2fdafa4126d4"},{"amount":1,"id":"00456a94ab4e1c46","B_":"033b6fde50b6a0dfe61ad148fff167ad9cf8308ded5f6f6b2fe000a036c464c311"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02be5a55f03e5c0aaea77595d574bce92c6d57a2a0fb2b5955c0b87e4520e06b53"},{"amount":1,"id":"00456a94ab4e1c46","B_":"02209fc2873f28521cbdde7f7b3bb1521002463f5979686fd156f23fe6a8aa2b79"}],"signature":"cb2b8e7ea69362dfe2a07093f2bbc319226db33db2ef686c940b5ec976bcbfc78df0cd35b3e998adf437b09ee2c950bd66dfe9eb64abd706e43ebc7c669c36c3"}"#).unwrap(); + + // Signature is on a different quote id verification should fail + assert!(request.verify_signature(pubkey).is_err()); + } +} diff --git a/crates/cdk/src/wallet/mint.rs b/crates/cdk/src/wallet/mint.rs index 9ae13498..483c99c2 100644 --- a/crates/cdk/src/wallet/mint.rs +++ b/crates/cdk/src/wallet/mint.rs @@ -6,7 +6,7 @@ use crate::dhke::construct_proofs; use crate::nuts::nut00::ProofsMethods; use crate::nuts::{ nut12, MintBolt11Request, MintQuoteBolt11Request, MintQuoteBolt11Response, PreMintSecrets, - SpendingConditions, State, + SecretKey, SpendingConditions, State, }; use crate::types::ProofInfo; use crate::util::unix_time; @@ -65,10 +65,13 @@ impl Wallet { } } + let secret_key = SecretKey::generate(); + let request = MintQuoteBolt11Request { amount, unit: unit.clone(), description, + pubkey: Some(secret_key.public_key()), }; let quote_res = self.client.post_mint_quote(request).await?; @@ -81,6 +84,7 @@ impl Wallet { request: quote_res.request, state: quote_res.state, expiry: quote_res.expiry.unwrap_or(0), + secret_key: Some(secret_key), }; self.localstore.add_mint_quote(quote.clone()).await?; @@ -121,6 +125,7 @@ impl Wallet { let mint_quote_response = self.mint_quote_state(&mint_quote.id).await?; if mint_quote_response.state == MintQuoteState::Paid { + // TODO: Need to pass in keys here let amount = self .mint(&mint_quote.id, SplitTarget::default(), None) .await?; @@ -216,11 +221,16 @@ impl Wallet { )?, }; - let request = MintBolt11Request { + let mut request = MintBolt11Request { quote: quote_id.to_string(), outputs: premint_secrets.blinded_messages(), + signature: None, }; + if let Some(secret_key) = quote_info.secret_key { + request.sign(secret_key)?; + } + let mint_res = self.client.post_mint(request).await?; let keys = self.get_keyset_keys(active_keyset_id).await?; diff --git a/crates/cdk/src/wallet/types.rs b/crates/cdk/src/wallet/types.rs index 309a4c1c..d1683db3 100644 --- a/crates/cdk/src/wallet/types.rs +++ b/crates/cdk/src/wallet/types.rs @@ -3,11 +3,11 @@ use serde::{Deserialize, Serialize}; use crate::mint_url::MintUrl; -use crate::nuts::{CurrencyUnit, MeltQuoteState, MintQuoteState}; +use crate::nuts::{CurrencyUnit, MeltQuoteState, MintQuoteState, SecretKey}; use crate::Amount; /// Mint Quote Info -#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct MintQuote { /// Quote id pub id: String, @@ -23,6 +23,8 @@ pub struct MintQuote { pub state: MintQuoteState, /// Expiration time of quote pub expiry: u64, + /// Secretkey for signing mint quotes [NUT-20] + pub secret_key: Option, } /// Melt Quote Info diff --git a/flake.lock b/flake.lock index f5581be4..a974c74e 100644 --- a/flake.lock +++ b/flake.lock @@ -57,11 +57,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -177,11 +177,11 @@ ] }, "locked": { - "lastModified": 1731378398, - "narHash": "sha256-a0QWaiX8+AJ9/XBLGMDy6c90GD7HzpxKVdlFwCke5Pw=", + "lastModified": 1731637922, + "narHash": "sha256-6iuzRINXyPX4DfUQZIGafpJnzjFXjVRYMymB10/jFFY=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "0ae9fc2f2fe5361837d59c0bdebbda176427111e", + "rev": "db10c66da18e816030b884388545add8cf096647", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 0b1e343d..e95a95d7 100644 --- a/flake.nix +++ b/flake.nix @@ -65,7 +65,7 @@ targets = [ "wasm32-unknown-unknown" ]; # wasm }; - # Nightly for creating lock files + # Nightly used for formatting nightly_toolchain = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override { extensions = [ "rustfmt" "clippy" "rust-analyzer" ]; }); From 90f9f668e15e34fb5a46e7f33acac9174bea5eef Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Mon, 23 Dec 2024 11:05:56 -0500 Subject: [PATCH 2/2] chore: db msrv --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index e95a95d7..c863a70d 100644 --- a/flake.nix +++ b/flake.nix @@ -274,6 +274,7 @@ cargo update -p allocator-api2 --precise 0.2.18 cargo update -p async-compression --precise 0.4.3 cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5 + cargo update -p redb --precise 2.2.0 ''; buildInputs = buildInputs ++ WASMInputs ++ [ db_msrv_toolchain ]; inherit nativeBuildInputs;