diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecc520bd0..77e111514 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,10 @@ jobs: -p cdk --no-default-features --features "mint swagger", -p cdk-redb, -p cdk-sqlite, + -p cdk-axum --no-default-features, + -p cdk-axum --no-default-features --features swagger, + -p cdk-axum --no-default-features --features redis, + -p cdk-axum --no-default-features --features "redis swagger", -p cdk-axum, -p cdk-cln, -p cdk-lnd, @@ -65,6 +69,9 @@ jobs: -p cdk-fake-wallet, --bin cdk-cli, --bin cdk-mintd, + --bin cdk-mintd --no-default-features --features swagger, + --bin cdk-mintd --no-default-features --features redis, + --bin cdk-mintd --no-default-features --features "redis swagger", ] steps: - name: checkout @@ -152,6 +159,7 @@ jobs: -p cdk --no-default-features --features wallet, -p cdk --no-default-features --features mint, -p cdk-axum, + -p cdk-axum --no-default-features --features redis, -p cdk-strike, -p cdk-lnbits, -p cdk-phoenixd, diff --git a/.helix/languages.toml b/.helix/languages.toml index f86f944a1..c2a98dd65 100644 --- a/.helix/languages.toml +++ b/.helix/languages.toml @@ -1,2 +1,2 @@ [language-server.rust-analyzer.config] -cargo = { features = ["wallet", "mint", "swagger"] } +cargo = { features = ["wallet", "mint", "swagger", "redis"] } diff --git a/Cargo.lock b/Cargo.lock index 9354b7966..1f890ea25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,19 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" 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" @@ -70,11 +76,26 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -148,9 +169,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" dependencies = [ "backtrace", ] @@ -161,6 +182,22 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-compression" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "zstd", + "zstd-safe", +] + [[package]] name = "async-io" version = "1.13.0" @@ -245,9 +282,9 @@ dependencies = [ "futures", "futures-util", "js-sys", - "thiserror 1.0.69", + "thiserror", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tokio-socks", "tokio-tungstenite 0.24.0", "url", @@ -306,7 +343,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", "tokio-tungstenite 0.20.1", "tower", @@ -333,17 +370,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "88fb5a785d6b44fd9d6700935608639af1b8356de1e55d5f7c2740f4faa15d82" dependencies = [ "addr2line", + "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.4.4", "object", "rustc-demangle", - "windows-targets 0.52.6", ] [[package]] @@ -560,6 +597,27 @@ dependencies = [ "generic-array", ] +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bs58" version = "0.5.1" @@ -571,9 +629,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytecount" @@ -664,6 +722,8 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -690,8 +750,8 @@ dependencies = [ "serde", "serde_json", "serde_with", - "sync_wrapper 0.1.2", - "thiserror 1.0.69", + "sync_wrapper", + "thiserror", "tokio", "tokio-tungstenite 0.19.0", "tracing", @@ -711,8 +771,10 @@ dependencies = [ "futures", "moka", "paste", + "redis", "serde", "serde_json", + "sha2", "tokio", "tracing", "utoipa", @@ -750,7 +812,7 @@ dependencies = [ "cdk", "cln-rpc 0.2.0", "futures", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-util", "tracing", @@ -769,7 +831,7 @@ dependencies = [ "rand", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-stream", "tokio-util", @@ -819,7 +881,7 @@ dependencies = [ "cdk", "futures", "lnbits-rs", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-util", "tracing", @@ -834,7 +896,7 @@ dependencies = [ "cdk", "fedimint-tonic-lnd", "futures", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-util", "tracing", @@ -884,7 +946,7 @@ dependencies = [ "cdk", "futures", "phoenixd-rs", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-util", "tracing", @@ -901,7 +963,7 @@ dependencies = [ "redb", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tracing", "uuid", ] @@ -916,7 +978,7 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", "web-sys", ] @@ -931,7 +993,7 @@ dependencies = [ "lightning-invoice", "serde_json", "sqlx", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", "uuid", @@ -948,7 +1010,7 @@ dependencies = [ "cdk", "futures", "strike-rs", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-util", "tracing", @@ -961,12 +1023,6 @@ 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" @@ -1044,9 +1100,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -1054,9 +1110,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -1078,9 +1134,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cln-rpc" @@ -1124,6 +1180,20 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1162,16 +1232,6 @@ 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" @@ -1390,17 +1450,6 @@ 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.90", -] - [[package]] name = "dlv-list" version = "0.3.0" @@ -1498,7 +1547,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1674,9 +1723,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "glob" @@ -1717,11 +1766,10 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ - "cfg-if", "crunchy", ] @@ -1849,9 +1897,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1876,7 +1924,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1887,7 +1935,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1943,7 +1991,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "httparse", "itoa", @@ -1969,21 +2017,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.1.0", + "http 1.2.0", "hyper 1.5.1", "hyper-util", - "rustls 0.23.19", - "rustls-native-certs 0.8.1", + "rustls 0.22.4", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.25.0", "tower-service", - "webpki-roots 0.26.7", ] [[package]] @@ -2007,7 +2053,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "hyper 1.5.1", "pin-project-lite", @@ -2040,124 +2086,6 @@ 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.90", -] - [[package]] name = "idb" version = "0.6.4" @@ -2166,7 +2094,7 @@ checksum = "3afe8830d5802f769dc0be20a87f9f116798c896650cb6266eb5c19a3c109eed" dependencies = [ "js-sys", "num-traits", - "thiserror 1.0.69", + "thiserror", "tokio", "wasm-bindgen", "web-sys", @@ -2180,23 +2108,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2301,6 +2218,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.74" @@ -2408,12 +2334,6 @@ 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" @@ -2526,6 +2446,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2537,9 +2467,9 @@ dependencies = [ [[package]] name = "minreq" -version = "2.12.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" +checksum = "36a8e50e917e18a37d500d27d40b7bc7d127e71c0c94fb2d83f43b4afd308390" dependencies = [ "log", "serde", @@ -2548,20 +2478,20 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] name = "moka" -version = "0.11.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "36506f2f935238463605f3bb13b362f1949daafc3b347d05d60ae08836db2bd2" dependencies = [ "async-io", "async-lock", @@ -2569,6 +2499,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "futures-util", + "num_cpus", "once_cell", "parking_lot 0.12.3", "quanta", @@ -2577,7 +2508,7 @@ dependencies = [ "skeptic", "smallvec", "tagptr", - "thiserror 1.0.69", + "thiserror", "triomphe", "uuid", ] @@ -2645,7 +2576,7 @@ dependencies = [ "async-trait", "lru", "nostr", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", ] @@ -2663,7 +2594,7 @@ dependencies = [ "negentropy 0.4.3", "nostr", "nostr-database", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-stream", "tracing", @@ -2681,7 +2612,7 @@ dependencies = [ "nostr-database", "nostr-relay-pool", "nostr-signer", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", ] @@ -2694,7 +2625,7 @@ checksum = "c1e132975a677a1c97a7695ef1161291dc06517a588b6e17e3aa05d3fb4056a0" dependencies = [ "async-utility", "nostr", - "thiserror 1.0.69", + "thiserror", "tokio", ] @@ -2754,14 +2685,21 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.5" +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "memchr", + "hermit-abi 0.3.9", + "libc", ] +[[package]] +name = "object" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + [[package]] name = "once_cell" version = "1.20.2" @@ -2908,7 +2846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", - "thiserror 1.0.69", + "thiserror", "ucd-trie", ] @@ -2969,7 +2907,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", ] @@ -3204,58 +3142,6 @@ 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.19", - "socket2 0.5.8", - "thiserror 2.0.3", - "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.19", - "rustls-pki-types", - "slab", - "thiserror 2.0.3", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.8", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "quote" version = "1.0.37" @@ -3333,6 +3219,30 @@ dependencies = [ "libc", ] +[[package]] +name = "redis" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba" +dependencies = [ + "async-trait", + "bytes", + "combine", + "futures-util", + "itoa", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "ryu", + "sha1_smol", + "socket2 0.4.10", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "url", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -3359,19 +3269,19 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "regex-automata 0.3.9", + "regex-syntax 0.7.5", ] [[package]] @@ -3385,13 +3295,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax 0.7.5", ] [[package]] @@ -3402,25 +3312,26 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ + "async-compression", "base64 0.22.1", "bytes", "futures-core", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "hyper 1.5.1", - "hyper-rustls 0.27.3", + "hyper-rustls 0.26.0", "hyper-util", "ipnet", "js-sys", @@ -3429,25 +3340,25 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "quinn", - "rustls 0.23.19", - "rustls-native-certs 0.8.1", + "rustls 0.22.4", + "rustls-native-certs 0.7.3", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.25.0", "tokio-socks", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", "webpki-roots 0.26.7", - "windows-registry", + "winreg", ] [[package]] @@ -3457,7 +3368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "887466cfa8a12c08ee4b174998135cea8ff0fd84858627cd793e56535a045bc9" dependencies = [ "idb", - "thiserror 1.0.69", + "thiserror", "wasm-bindgen", ] @@ -3553,12 +3464,6 @@ 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" @@ -3619,6 +3524,20 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +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" @@ -3642,19 +3561,20 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework 2.11.1", + "security-framework", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", + "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework 3.0.1", + "security-framework", ] [[package]] @@ -3680,9 +3600,6 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" -dependencies = [ - "web-time", -] [[package]] name = "rustls-webpki" @@ -3829,20 +3746,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -3941,17 +3845,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.11.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" dependencies = [ - "base64 0.22.1", + "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.0", "serde", - "serde_derive", "serde_json", "serde_with_macros", "time", @@ -3959,9 +3861,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.11.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +checksum = "ea3cee93715c2e266b9338b7544da68a9f24e227722ba482bd1c024367c77c65" dependencies = [ "darling", "proc-macro2", @@ -3980,6 +3882,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + [[package]] name = "sha2" version = "0.10.8" @@ -4149,7 +4057,7 @@ dependencies = [ "sqlformat", "sqlx-rt", "stringprep", - "thiserror 1.0.69", + "thiserror", "tokio-stream", "url", "uuid", @@ -4186,12 +4094,6 @@ 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" @@ -4209,7 +4111,7 @@ dependencies = [ "ring 0.17.8", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", "tower", "tower-http", @@ -4266,26 +4168,6 @@ 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.90", -] - [[package]] name = "tagptr" version = "0.2.0" @@ -4311,16 +4193,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" -dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl", ] [[package]] @@ -4334,17 +4207,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "thiserror-impl" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "thread_local" version = "1.1.8" @@ -4357,9 +4219,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -4378,24 +4240,14 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "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" @@ -4423,20 +4275,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" 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.52.0", + "windows-sys 0.48.0", ] [[package]] @@ -4451,9 +4304,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -4483,15 +4336,25 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.23.19", + "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", + "tokio", +] + [[package]] name = "tokio-socks" version = "0.5.2" @@ -4500,15 +4363,15 @@ checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", - "thiserror 1.0.69", + "thiserror", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4553,16 +4416,16 @@ dependencies = [ "rustls 0.23.19", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tungstenite 0.24.0", "webpki-roots 0.26.7", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -4649,6 +4512,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ + "async-compression", "bitflags 2.6.0", "bytes", "futures-core", @@ -4657,6 +4521,8 @@ dependencies = [ "http-body 0.4.6", "http-range-header", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", @@ -4738,9 +4604,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.14" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" @@ -4763,7 +4629,7 @@ dependencies = [ "rand", "rustls 0.21.12", "sha1", - "thiserror 1.0.69", + "thiserror", "url", "utf-8", "webpki", @@ -4783,7 +4649,7 @@ dependencies = [ "log", "rand", "sha1", - "thiserror 1.0.69", + "thiserror", "url", "utf-8", ] @@ -4797,14 +4663,14 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand", "rustls 0.23.19", "rustls-pki-types", "sha1", - "thiserror 1.0.69", + "thiserror", "utf-8", ] @@ -4889,9 +4755,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -4905,18 +4771,6 @@ 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" @@ -5100,16 +4954,6 @@ dependencies = [ "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", -] - [[package]] name = "webpki" version = "0.22.4" @@ -5178,36 +5022,6 @@ 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" @@ -5357,16 +5171,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" +name = "winreg" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] [[package]] name = "yaml-rust" @@ -5377,30 +5189,6 @@ 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.90", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -5423,62 +5211,47 @@ dependencies = [ ] [[package]] -name = "zerofrom" -version = "0.1.5" +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" -dependencies = [ - "zerofrom-derive", -] +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerofrom-derive" -version = "0.1.5" +name = "zip" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", - "synstructure", + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", ] [[package]] -name = "zeroize" -version = "1.8.1" +name = "zstd" +version = "0.13.2" 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" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", + "zstd-safe", ] [[package]] -name = "zerovec-derive" -version = "0.10.3" +name = "zstd-safe" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "zstd-sys", ] [[package]] -name = "zip" -version = "0.6.6" +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", - "flate2", + "cc", + "pkg-config", ] diff --git a/Dockerfile b/Dockerfile index f56e51b91..711d172da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ COPY Cargo.toml ./Cargo.toml COPY crates ./crates # Start the Nix daemon and develop the environment -RUN nix develop --extra-experimental-features nix-command --extra-experimental-features flakes --command cargo build --release --bin cdk-mintd +RUN nix develop --extra-experimental-features nix-command --extra-experimental-features flakes --command cargo build --release --bin cdk-mintd --features redis # Create a runtime stage FROM debian:bookworm-slim diff --git a/crates/cdk-axum/Cargo.toml b/crates/cdk-axum/Cargo.toml index 861a028cd..90ba75964 100644 --- a/crates/cdk-axum/Cargo.toml +++ b/crates/cdk-axum/Cargo.toml @@ -30,6 +30,11 @@ serde_json = "1" paste = "1.0.15" serde = { version = "1.0.210", features = ["derive"] } uuid = { version = "1", features = ["v4", "serde"] } +sha2 = "0.10.8" +redis = { version = "0.23.3", features = [ + "tokio-rustls-comp", +], optional = true } [features] +redis = ["dep:redis"] swagger = ["cdk/swagger", "dep:utoipa"] diff --git a/crates/cdk-axum/src/cache/backend/memory.rs b/crates/cdk-axum/src/cache/backend/memory.rs new file mode 100644 index 000000000..ec21772e3 --- /dev/null +++ b/crates/cdk-axum/src/cache/backend/memory.rs @@ -0,0 +1,45 @@ +use std::time::Duration; + +use moka::future::Cache; + +use crate::cache::{HttpCacheKey, HttpCacheStorage, DEFAULT_TTI_SECS, DEFAULT_TTL_SECS}; + +/// In memory cache storage for the HTTP cache. +/// +/// This is the default cache storage backend, which is used if no other storage +/// backend is provided, or if the provided storage backend is `None`. +/// +/// The cache is limited to 10,000 entries and it is not shared between +/// instances nor persisted. +pub struct InMemoryHttpCache(pub Cache>); + +impl Default for InMemoryHttpCache { + fn default() -> Self { + InMemoryHttpCache( + Cache::builder() + .max_capacity(10_000) + .time_to_live(Duration::from_secs(DEFAULT_TTL_SECS)) + .time_to_idle(Duration::from_secs(DEFAULT_TTI_SECS)) + .build(), + ) + } +} + +#[async_trait::async_trait] +impl HttpCacheStorage for InMemoryHttpCache { + fn set_expiration_times(&mut self, cache_ttl: Duration, cache_tti: Duration) { + self.0 = Cache::builder() + .max_capacity(10_000) + .time_to_live(cache_ttl) + .time_to_idle(cache_tti) + .build(); + } + + async fn get(&self, key: &HttpCacheKey) -> Option> { + self.0.get(key) + } + + async fn set(&self, key: HttpCacheKey, value: Vec) { + self.0.insert(key, value).await; + } +} diff --git a/crates/cdk-axum/src/cache/backend/mod.rs b/crates/cdk-axum/src/cache/backend/mod.rs new file mode 100644 index 000000000..511d156f9 --- /dev/null +++ b/crates/cdk-axum/src/cache/backend/mod.rs @@ -0,0 +1,7 @@ +mod memory; +#[cfg(feature = "redis")] +mod redis; + +pub use self::memory::InMemoryHttpCache; +#[cfg(feature = "redis")] +pub use self::redis::{Config as RedisConfig, HttpCacheRedis}; diff --git a/crates/cdk-axum/src/cache/backend/redis.rs b/crates/cdk-axum/src/cache/backend/redis.rs new file mode 100644 index 000000000..3e2af2447 --- /dev/null +++ b/crates/cdk-axum/src/cache/backend/redis.rs @@ -0,0 +1,96 @@ +use std::time::Duration; + +use redis::AsyncCommands; +use serde::{Deserialize, Serialize}; + +use crate::cache::{HttpCacheKey, HttpCacheStorage}; + +/// Redis cache storage for the HTTP cache. +/// +/// This cache storage backend uses Redis to store the cache. +pub struct HttpCacheRedis { + cache_ttl: Duration, + prefix: Option>, + client: redis::Client, +} + +/// Configuration for the Redis cache storage. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct Config { + /// Commong key prefix + pub key_prefix: Option, + + /// Connection string to the Redis server. + pub connection_string: String, +} + +impl HttpCacheRedis { + /// Create a new Redis cache. + pub fn new(client: redis::Client) -> Self { + Self { + client, + prefix: None, + cache_ttl: Duration::from_secs(60), + } + } + + /// Set a prefix for the cache keys. + /// + /// This is useful to have all the HTTP cache keys under a common prefix, + /// some sort of namespace, to make management of the database easier. + pub fn set_prefix(mut self, prefix: Vec) -> Self { + self.prefix = Some(prefix); + self + } +} + +#[async_trait::async_trait] +impl HttpCacheStorage for HttpCacheRedis { + fn set_expiration_times(&mut self, cache_ttl: Duration, _cache_tti: Duration) { + self.cache_ttl = cache_ttl; + } + + async fn get(&self, key: &HttpCacheKey) -> Option> { + let mut conn = self + .client + .get_multiplexed_tokio_connection() + .await + .map_err(|err| { + tracing::error!("Failed to get redis connection: {:?}", err); + err + }) + .ok()?; + + let mut db_key = self.prefix.clone().unwrap_or_default(); + db_key.extend(&**key); + + conn.get(db_key) + .await + .map_err(|err| { + tracing::error!("Failed to get value from redis: {:?}", err); + err + }) + .ok()? + } + + async fn set(&self, key: HttpCacheKey, value: Vec) { + let mut db_key = self.prefix.clone().unwrap_or_default(); + db_key.extend(&*key); + + let mut conn = match self.client.get_multiplexed_tokio_connection().await { + Ok(conn) => conn, + Err(err) => { + tracing::error!("Failed to get redis connection: {:?}", err); + return; + } + }; + + let _: Result<(), _> = conn + .set_ex(db_key, value, self.cache_ttl.as_secs() as usize) + .await + .map_err(|err| { + tracing::error!("Failed to set value in redis: {:?}", err); + err + }); + } +} diff --git a/crates/cdk-axum/src/cache/config.rs b/crates/cdk-axum/src/cache/config.rs new file mode 100644 index 000000000..f50551221 --- /dev/null +++ b/crates/cdk-axum/src/cache/config.rs @@ -0,0 +1,102 @@ +use serde::{Deserialize, Serialize}; + +pub const ENV_CDK_MINTD_CACHE_BACKEND: &str = "CDK_MINTD_CACHE_BACKEND"; + +#[cfg(feature = "redis")] +pub const ENV_CDK_MINTD_CACHE_REDIS_URL: &str = "CDK_MINTD_CACHE_REDIS_URL"; +#[cfg(feature = "redis")] +pub const ENV_CDK_MINTD_CACHE_REDIS_KEY_PREFIX: &str = "CDK_MINTD_CACHE_REDIS_KEY_PREFIX"; + +pub const ENV_CDK_MINTD_CACHE_TTI: &str = "CDK_MINTD_CACHE_TTI"; +pub const ENV_CDK_MINTD_CACHE_TTL: &str = "CDK_MINTD_CACHE_TTL"; + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(tag = "backend")] +#[serde(rename_all = "lowercase")] +pub enum Backend { + #[default] + Memory, + #[cfg(feature = "redis")] + Redis(super::backend::RedisConfig), +} + +impl Backend { + pub fn from_env_str(backend_str: &str) -> Option { + match backend_str.to_lowercase().as_str() { + "memory" => Some(Self::Memory), + #[cfg(feature = "redis")] + "redis" => { + // Get Redis configuration from environment + let connection_string = std::env::var(ENV_CDK_MINTD_CACHE_REDIS_URL) + .unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); + + let key_prefix = std::env::var(ENV_CDK_MINTD_CACHE_REDIS_KEY_PREFIX).ok(); + + Some(Self::Redis(super::backend::RedisConfig { + connection_string, + key_prefix, + })) + } + _ => None, + } + } +} + +/// Cache configuration. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct Config { + /// Cache backend. + #[serde(default)] + #[serde(flatten)] + pub backend: Backend, + + /// Time to live for the cache entries. + pub ttl: Option, + + /// Time for the cache entries to be idle. + pub tti: Option, +} + +impl Config { + /// Config from env + pub fn from_env(mut self) -> Self { + use std::env; + + // Parse backend + if let Ok(backend_str) = env::var(ENV_CDK_MINTD_CACHE_BACKEND) { + if let Some(backend) = Backend::from_env_str(&backend_str) { + self.backend = backend; + + // If Redis backend is selected, parse Redis configuration + #[cfg(feature = "redis")] + if matches!(self.backend, Backend::Redis(_)) { + let connection_string = env::var(ENV_CDK_MINTD_CACHE_REDIS_URL) + .unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); + + let key_prefix = env::var(ENV_CDK_MINTD_CACHE_REDIS_KEY_PREFIX).ok(); + + self.backend = Backend::Redis(super::backend::RedisConfig { + connection_string, + key_prefix, + }); + } + } + } + + // Parse TTL + if let Ok(ttl_str) = env::var(ENV_CDK_MINTD_CACHE_TTL) { + if let Ok(ttl) = ttl_str.parse() { + self.ttl = Some(ttl); + } + } + + // Parse TTI + if let Ok(tti_str) = env::var(ENV_CDK_MINTD_CACHE_TTI) { + if let Ok(tti) = tti_str.parse() { + self.tti = Some(tti); + } + } + + self + } +} diff --git a/crates/cdk-axum/src/cache/mod.rs b/crates/cdk-axum/src/cache/mod.rs new file mode 100644 index 000000000..d4ed27d22 --- /dev/null +++ b/crates/cdk-axum/src/cache/mod.rs @@ -0,0 +1,188 @@ +//! HTTP cache. +//! +//! This is mod defines a common trait to define custom backends for the HTTP cache. +//! +//! The HTTP cache is a layer to cache responses from HTTP requests, to avoid hitting +//! the same endpoint multiple times, which can be expensive and slow, or to provide +//! idempotent operations. +//! +//! This mod also provides common backend implementations as well, such as In +//! Memory (default) and Redis. +use std::ops::Deref; +use std::sync::Arc; +use std::time::Duration; + +use serde::de::DeserializeOwned; +use serde::Serialize; +use sha2::{Digest, Sha256}; + +mod backend; +mod config; + +pub use self::backend::*; +pub use self::config::Config; + +#[async_trait::async_trait] +/// Cache storage for the HTTP cache. +pub trait HttpCacheStorage { + /// Sets the expiration times for the cache. + fn set_expiration_times(&mut self, cache_ttl: Duration, cache_tti: Duration); + + /// Get a value from the cache. + async fn get(&self, key: &HttpCacheKey) -> Option>; + + /// Set a value in the cache. + async fn set(&self, key: HttpCacheKey, value: Vec); +} + +/// Http cache with a pluggable storage backend. +pub struct HttpCache { + /// Time to live for the cache. + pub ttl: Duration, + /// Time to idle for the cache. + pub tti: Duration, + /// Storage backend for the cache. + storage: Arc>, +} + +impl Default for HttpCache { + fn default() -> Self { + Self::new( + Duration::from_secs(DEFAULT_TTL_SECS), + Duration::from_secs(DEFAULT_TTI_SECS), + None, + ) + } +} + +/// Max payload size for the cache key. +/// +/// This is a trade-off between security and performance. A large payload can be used to +/// perform a CPU attack. +const MAX_PAYLOAD_SIZE: usize = 10 * 1024 * 1024; + +/// Default TTL for the cache. +const DEFAULT_TTL_SECS: u64 = 60; + +/// Default TTI for the cache. +const DEFAULT_TTI_SECS: u64 = 60; + +/// Http cache key. +/// +/// This type ensures no Vec is used as a key, which is error-prone. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct HttpCacheKey([u8; 32]); + +impl Deref for HttpCacheKey { + type Target = [u8; 32]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for HttpCache { + fn from(config: config::Config) -> Self { + match config.backend { + config::Backend::Memory => Self::new( + Duration::from_secs(config.ttl.unwrap_or(DEFAULT_TTL_SECS)), + Duration::from_secs(config.tti.unwrap_or(DEFAULT_TTI_SECS)), + None, + ), + #[cfg(feature = "redis")] + config::Backend::Redis(redis_config) => { + let client = redis::Client::open(redis_config.connection_string) + .expect("Failed to create Redis client"); + let storage = HttpCacheRedis::new(client).set_prefix( + redis_config + .key_prefix + .unwrap_or_default() + .as_bytes() + .to_vec(), + ); + Self::new( + Duration::from_secs(config.ttl.unwrap_or(DEFAULT_TTL_SECS)), + Duration::from_secs(config.tti.unwrap_or(DEFAULT_TTI_SECS)), + Some(Box::new(storage)), + ) + } + } + } +} + +impl HttpCache { + /// Create a new HTTP cache. + pub fn new( + ttl: Duration, + tti: Duration, + storage: Option>, + ) -> Self { + let mut storage = storage.unwrap_or_else(|| Box::new(InMemoryHttpCache::default())); + storage.set_expiration_times(ttl, tti); + + Self { + ttl, + tti, + storage: Arc::new(storage), + } + } + + /// Calculate a cache key from a serializable value. + /// + /// Usually the input is the request body or query parameters. + /// + /// The result is an optional cache key. If the key cannot be calculated, it + /// will be None, meaning the value cannot be cached, therefore the entire + /// caching mechanism should be skipped. + /// + /// Instead of using the entire serialized input as the key, the key is a + /// double hash to have a predictable key size, although it may open the + /// window for CPU attacks with large payloads, but it is a trade-off. + /// Perhaps upper layer have a protection against large payloads. + pub fn calculate_key(&self, key: &K) -> Option + where + K: Serialize, + { + let json_value = match serde_json::to_vec(key) { + Ok(value) => value, + Err(err) => { + tracing::warn!("Failed to serialize key: {:?}", err); + return None; + } + }; + + if json_value.len() > MAX_PAYLOAD_SIZE { + tracing::warn!("Key size is too large: {}", json_value.len()); + return None; + } + + let first_hash = Sha256::digest(json_value); + let second_hash = Sha256::digest(first_hash); + Some(HttpCacheKey(second_hash.into())) + } + + /// Get a value from the cache. + pub async fn get(self: &Arc, key: &HttpCacheKey) -> Option + where + V: DeserializeOwned, + { + self.storage.get(key).await.and_then(|value| { + serde_json::from_slice(&value) + .map_err(|e| { + tracing::warn!("Failed to deserialize value: {:?}", e); + e + }) + .ok() + }) + } + + /// Set a value in the cache. + pub async fn set(self: &Arc, key: HttpCacheKey, value: &V) { + if let Ok(bytes) = serde_json::to_vec(value).map_err(|e| { + tracing::warn!("Failed to serialize value: {:?}", e); + e + }) { + self.storage.set(key, bytes).await; + } + } +} diff --git a/crates/cdk-axum/src/lib.rs b/crates/cdk-axum/src/lib.rs index 1acc9370c..b5b2ed24a 100644 --- a/crates/cdk-axum/src/lib.rs +++ b/crates/cdk-axum/src/lib.rs @@ -4,15 +4,15 @@ #![warn(rustdoc::bare_urls)] use std::sync::Arc; -use std::time::Duration; use anyhow::Result; use axum::routing::{get, post}; use axum::Router; +use cache::HttpCache; use cdk::mint::Mint; -use moka::future::Cache; use router_handlers::*; +pub mod cache; mod router_handlers; mod ws; @@ -52,7 +52,7 @@ use uuid::Uuid; #[derive(Clone)] pub struct MintState { mint: Arc, - cache: Cache, + cache: Arc, } #[cfg(feature = "swagger")] @@ -131,15 +131,20 @@ pub struct MintState { /// OpenAPI spec for the mint's v1 APIs pub struct ApiDocV1; -/// Create mint [`Router`] with required endpoints for cashu mint -pub async fn create_mint_router(mint: Arc, cache_ttl: u64, cache_tti: u64) -> Result { +/// Create mint [`Router`] with required endpoints for cashu mint with the default cache +pub async fn create_mint_router(mint: Arc) -> Result { + create_mint_router_with_custom_cache(mint, Default::default()).await +} + +/// Create mint [`Router`] with required endpoints for cashu mint with a custom +/// backend for cache +pub async fn create_mint_router_with_custom_cache( + mint: Arc, + cache: HttpCache, +) -> Result { let state = MintState { mint, - cache: Cache::builder() - .max_capacity(10_000) - .time_to_live(Duration::from_secs(cache_ttl)) - .time_to_idle(Duration::from_secs(cache_tti)) - .build(), + cache: Arc::new(cache), }; let v1_router = Router::new() diff --git a/crates/cdk-axum/src/router_handlers.rs b/crates/cdk-axum/src/router_handlers.rs index 0d2bfac44..5c5710598 100644 --- a/crates/cdk-axum/src/router_handlers.rs +++ b/crates/cdk-axum/src/router_handlers.rs @@ -11,7 +11,6 @@ use cdk::nuts::{ SwapRequest, SwapResponse, }; use cdk::util::unix_time; -use cdk::Error; use paste::paste; use uuid::Uuid; @@ -31,19 +30,20 @@ macro_rules! post_cache_wrapper { let json_extracted_payload = payload.deref(); let State(mint_state) = state.clone(); - let cache_key = serde_json::to_string(&json_extracted_payload).map_err(|err| { - into_response(Error::from(err)) - })?; - - if let Some(cached_response) = mint_state.cache.get(&cache_key) { - return Ok(Json(serde_json::from_str(&cached_response) - .expect("Shouldn't panic: response is json-deserializable."))); + let cache_key = match mint_state.cache.calculate_key(&json_extracted_payload) { + Some(key) => key, + None => { + // Could not calculate key, just return the handler result + return $handler(state, payload).await; + } + }; + + if let Some(cached_response) = mint_state.cache.get::<$response_type>(&cache_key).await { + return Ok(Json(cached_response)); } let response = $handler(state, payload).await?; - mint_state.cache.insert(cache_key, serde_json::to_string(response.deref()) - .expect("Shouldn't panic: response is json-serializable.") - ).await; + mint_state.cache.set(cache_key, &response.deref()).await; Ok(response) } } diff --git a/crates/cdk-integration-tests/src/init_fake_wallet.rs b/crates/cdk-integration-tests/src/init_fake_wallet.rs index d3216b820..b24f5b522 100644 --- a/crates/cdk-integration-tests/src/init_fake_wallet.rs +++ b/crates/cdk-integration-tests/src/init_fake_wallet.rs @@ -50,11 +50,9 @@ where ); let mint = create_mint(database, ln_backends.clone()).await?; - let cache_ttl = 3600; - let cache_tti = 3600; let mint_arc = Arc::new(mint); - let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint_arc), cache_ttl, cache_tti) + let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint_arc)) .await .unwrap(); diff --git a/crates/cdk-integration-tests/src/init_regtest.rs b/crates/cdk-integration-tests/src/init_regtest.rs index b7ac843bc..2ddeca81e 100644 --- a/crates/cdk-integration-tests/src/init_regtest.rs +++ b/crates/cdk-integration-tests/src/init_regtest.rs @@ -221,17 +221,11 @@ where ); let mint = create_mint(database, ln_backends.clone()).await?; - let cache_time_to_live = 3600; - let cache_time_to_idle = 3600; let mint_arc = Arc::new(mint); - let v1_service = cdk_axum::create_mint_router( - Arc::clone(&mint_arc), - cache_time_to_live, - cache_time_to_idle, - ) - .await - .unwrap(); + let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint_arc)) + .await + .unwrap(); let mint_service = Router::new() .merge(v1_service) diff --git a/crates/cdk-integration-tests/src/lib.rs b/crates/cdk-integration-tests/src/lib.rs index 7211c64c4..abca88bbf 100644 --- a/crates/cdk-integration-tests/src/lib.rs +++ b/crates/cdk-integration-tests/src/lib.rs @@ -86,17 +86,10 @@ pub async fn start_mint( HashMap::new(), ) .await?; - let cache_time_to_live = 3600; - let cache_time_to_idle = 3600; let mint_arc = Arc::new(mint); - let v1_service = cdk_axum::create_mint_router( - Arc::clone(&mint_arc), - cache_time_to_live, - cache_time_to_idle, - ) - .await?; + let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint_arc)).await?; let mint_service = Router::new() .merge(v1_service) diff --git a/crates/cdk-mintd/Cargo.toml b/crates/cdk-mintd/Cargo.toml index abe9c8d79..d6d84ff12 100644 --- a/crates/cdk-mintd/Cargo.toml +++ b/crates/cdk-mintd/Cargo.toml @@ -6,15 +6,21 @@ authors = ["CDK Developers"] license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.63.0" # MSRV description = "CDK mint binary" [dependencies] anyhow = "1" axum = "0.6.20" -cdk = { path = "../cdk", version = "0.5.0", default-features = false, features = ["mint"] } -cdk-redb = { path = "../cdk-redb", version = "0.5.0", default-features = false, features = ["mint"] } -cdk-sqlite = { path = "../cdk-sqlite", version = "0.5.0", default-features = false, features = ["mint"] } +cdk = { path = "../cdk", version = "0.5.0", default-features = false, features = [ + "mint", +] } +cdk-redb = { path = "../cdk-redb", version = "0.5.0", default-features = false, features = [ + "mint", +] } +cdk-sqlite = { path = "../cdk-sqlite", version = "0.5.0", default-features = false, features = [ + "mint", +] } cdk-cln = { path = "../cdk-cln", version = "0.5.0", default-features = false } cdk-lnbits = { path = "../cdk-lnbits", version = "0.5.0", default-features = false } cdk-phoenixd = { path = "../cdk-phoenixd", version = "0.5.0", default-features = false } @@ -25,7 +31,10 @@ cdk-axum = { path = "../cdk-axum", version = "0.5.0", default-features = false } config = { version = "0.13.3", features = ["toml"] } clap = { version = "4.4.8", features = ["derive", "env", "default"] } tokio = { version = "1", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } +tracing = { version = "0.1", default-features = false, features = [ + "attributes", + "log", +] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } futures = { version = "0.3.28", default-features = false } serde = { version = "1", default-features = false, features = ["derive"] } @@ -40,3 +49,4 @@ rand = "0.8.5" [features] swagger = ["cdk-axum/swagger", "dep:utoipa", "dep:utoipa-swagger-ui"] +redis = ["cdk-axum/redis"] diff --git a/crates/cdk-mintd/example.config.toml b/crates/cdk-mintd/example.config.toml index 7946fd5ba..af11f7905 100644 --- a/crates/cdk-mintd/example.config.toml +++ b/crates/cdk-mintd/example.config.toml @@ -6,6 +6,14 @@ mnemonic = "" # input_fee_ppk = 0 # enable_swagger_ui = false +[info.http_cache] +# memory or redis +backend = "memory" +ttl = 60 +tti = 60 +# `key_prefix` and `connection_string` required for redis +# key_prefix = "mintd" +# connection_string = "redis://localhost" [mint_info] @@ -32,9 +40,12 @@ ln_backend = "cln" # fee_percent=0.04 # reserve_fee_min=4 -# [cln] -# Required if using cln backend path to rpc -# cln_path = "" +[cln] +#Required if using cln backend path to rpc +cln_path = "" +rpc_path = "" +fee_percent = 0.02 +reserve_fee_min = 1 # [strike] # For the Webhook subscription, the url under [info] must be a valid, absolute, non-local, https url diff --git a/crates/cdk-mintd/src/config.rs b/crates/cdk-mintd/src/config.rs index fc579b17a..df46c279b 100644 --- a/crates/cdk-mintd/src/config.rs +++ b/crates/cdk-mintd/src/config.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use cdk::nuts::{CurrencyUnit, PublicKey}; use cdk::Amount; +use cdk_axum::cache; use config::{Config, ConfigError, File}; use serde::{Deserialize, Serialize}; @@ -11,11 +12,10 @@ pub struct Info { pub listen_host: String, pub listen_port: u16, pub mnemonic: String, - pub seconds_quote_is_valid_for: Option, - pub seconds_to_cache_requests_for: Option, - pub seconds_to_extend_cache_by: Option, pub input_fee_ppk: Option, + pub http_cache: cache::Config, + /// When this is set to true, the mint exposes a Swagger UI for it's API at /// `[listen_host]:[listen_port]/swagger-ui` /// @@ -93,6 +93,7 @@ pub struct LNbits { #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Cln { pub rpc_path: PathBuf, + #[serde(default)] pub bolt12: bool, pub fee_percent: f32, pub reserve_fee_min: Amount, @@ -210,7 +211,10 @@ pub struct MintInfo { impl Settings { #[must_use] - pub fn new(config_file_name: &Option) -> Self { + pub fn new

(config_file_name: Option

) -> Self + where + P: Into, + { let default_settings = Self::default(); // attempt to construct settings with file let from_file = Self::new_from_default(&default_settings, config_file_name); @@ -223,17 +227,20 @@ impl Settings { } } - fn new_from_default( + fn new_from_default

( default: &Settings, - config_file_name: &Option, - ) -> Result { + config_file_name: Option

, + ) -> Result + where + P: Into, + { let mut default_config_file_name = home::home_dir() .ok_or(ConfigError::NotFound("Config Path".to_string()))? .join("cashu-rs-mint"); default_config_file_name.push("config.toml"); let config: String = match config_file_name { - Some(value) => value.clone().to_string_lossy().to_string(), + Some(value) => value.into().to_string_lossy().to_string(), None => default_config_file_name.to_string_lossy().to_string(), }; let builder = Config::builder(); diff --git a/crates/cdk-mintd/src/env_vars.rs b/crates/cdk-mintd/src/env_vars.rs index eae4de4d2..3147e069c 100644 --- a/crates/cdk-mintd/src/env_vars.rs +++ b/crates/cdk-mintd/src/env_vars.rs @@ -127,22 +127,15 @@ impl Info { self.mnemonic = mnemonic; } - // Optional fields - if let Ok(seconds_str) = env::var(ENV_SECONDS_QUOTE_VALID) { - if let Ok(seconds) = seconds_str.parse() { - self.seconds_quote_is_valid_for = Some(seconds); - } - } - if let Ok(cache_seconds_str) = env::var(ENV_CACHE_SECONDS) { if let Ok(seconds) = cache_seconds_str.parse() { - self.seconds_to_cache_requests_for = Some(seconds); + self.http_cache.ttl = Some(seconds); } } if let Ok(extend_cache_str) = env::var(ENV_EXTEND_CACHE_SECONDS) { if let Ok(seconds) = extend_cache_str.parse() { - self.seconds_to_extend_cache_by = Some(seconds); + self.http_cache.tti = Some(seconds); } } @@ -158,6 +151,8 @@ impl Info { } } + self.http_cache = self.http_cache.from_env(); + self } } diff --git a/crates/cdk-mintd/src/lib.rs b/crates/cdk-mintd/src/lib.rs index f088ba3b5..1919dcf22 100644 --- a/crates/cdk-mintd/src/lib.rs +++ b/crates/cdk-mintd/src/lib.rs @@ -21,3 +21,22 @@ fn expand_path(path: &str) -> Option { Some(PathBuf::from(path)) } } + +#[cfg(test)] +mod test { + use std::env::current_dir; + + use super::*; + + #[test] + fn example_is_parsed() { + let config = config::Settings::new(Some(format!( + "{}/example.config.toml", + current_dir().expect("cwd").to_string_lossy() + ))); + let cache = config.info.http_cache; + + assert_eq!(cache.ttl, Some(60)); + assert_eq!(cache.tti, Some(60)); + } +} diff --git a/crates/cdk-mintd/src/main.rs b/crates/cdk-mintd/src/main.rs index 455d4119f..8c17377f6 100644 --- a/crates/cdk-mintd/src/main.rs +++ b/crates/cdk-mintd/src/main.rs @@ -22,6 +22,7 @@ use cdk::nuts::nut17::SupportedMethods; use cdk::nuts::nut19::{CachedEndpoint, Method as NUT19Method, Path as NUT19Path}; use cdk::nuts::{ContactInfo, CurrencyUnit, MintVersion, PaymentMethod}; use cdk::types::LnKey; +use cdk_axum::cache::HttpCache; use cdk_mintd::cli::CLIArgs; use cdk_mintd::config::{self, DatabaseEngine, LnBackend}; use cdk_mintd::setup::LnBackendSetup; @@ -36,9 +37,6 @@ use tracing_subscriber::EnvFilter; use utoipa::OpenApi; const CARGO_PKG_VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION"); -const DEFAULT_QUOTE_TTL_SECS: u64 = 1800; -const DEFAULT_CACHE_TTL_SECS: u64 = 1800; -const DEFAULT_CACHE_TTI_SECS: u64 = 1800; #[tokio::main] async fn main() -> anyhow::Result<()> { @@ -72,7 +70,7 @@ async fn main() -> anyhow::Result<()> { let mut mint_builder = MintBuilder::new(); let mut settings = if config_file_arg.exists() { - config::Settings::new(&Some(config_file_arg)) + config::Settings::new(Some(config_file_arg)) } else { tracing::info!("Config file does not exist. Attempting to read env vars"); config::Settings::default() @@ -302,18 +300,15 @@ async fn main() -> anyhow::Result<()> { .with_quote_ttl(10000, 10000) .with_seed(mnemonic.to_seed_normalized("").to_vec()); - let cache_ttl = settings - .info - .seconds_to_cache_requests_for - .unwrap_or(DEFAULT_CACHE_TTL_SECS); - let cached_endpoints = vec![ CachedEndpoint::new(NUT19Method::Post, NUT19Path::MintBolt11), CachedEndpoint::new(NUT19Method::Post, NUT19Path::MeltBolt11), CachedEndpoint::new(NUT19Method::Post, NUT19Path::Swap), ]; - mint_builder = mint_builder.add_cache(Some(cache_ttl), cached_endpoints); + let cache: HttpCache = settings.info.http_cache.into(); + + mint_builder = mint_builder.add_cache(Some(cache.ttl.as_secs()), cached_endpoints); let mint = mint_builder.build().await?; @@ -332,16 +327,9 @@ async fn main() -> anyhow::Result<()> { let listen_addr = settings.info.listen_host; let listen_port = settings.info.listen_port; - let _quote_ttl = settings - .info - .seconds_quote_is_valid_for - .unwrap_or(DEFAULT_QUOTE_TTL_SECS); - let cache_tti = settings - .info - .seconds_to_extend_cache_by - .unwrap_or(DEFAULT_CACHE_TTI_SECS); - - let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint), cache_ttl, cache_tti).await?; + + let v1_service = + cdk_axum::create_mint_router_with_custom_cache(Arc::clone(&mint), cache).await?; let mut mint_service = Router::new() .merge(v1_service) diff --git a/docker-compose.yaml b/docker-compose.yaml index b0c6efb96..c30a6970f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -13,4 +13,21 @@ services: - CDK_MINTD_LISTEN_PORT=8085 - CDK_MINTD_MNEMONIC= - CDK_MINTD_DATABASE=redb + - CDK_MINTD_CACHE_BACKEND=memory + # - CDK_MINTD_CACHE_REDIS_URL=redis://redis:6379 + # - CDK_MINTD_CACHE_REDIS_KEY_PREFIX=cdk-mintd command: ["cdk-mintd"] + # depends_on: + # - redis + +# redis: +# image: redis:7-alpine +# container_name: mint_redis +# ports: +# - "6379:6379" +# volumes: +# - redis_data:/data +# command: redis-server --save 60 1 --loglevel warning + +# volumes: +# redis_data: