diff --git a/Cargo.lock b/Cargo.lock index 145d293..388937d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,18 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.4.4", + "cpufeatures", + "zeroize", +] + [[package]] name = "age" version = "0.7.1" @@ -37,7 +49,7 @@ dependencies = [ "bech32 0.8.1", "chacha20poly1305", "cookie-factory", - "hkdf", + "hkdf 0.11.0", "hmac 0.11.0", "i18n-embed", "i18n-embed-fl", @@ -63,13 +75,25 @@ dependencies = [ "base64 0.13.1", "chacha20poly1305", "cookie-factory", - "hkdf", + "hkdf 0.11.0", "nom", "rand 0.8.5", "secrecy 0.8.0", "sha2 0.9.9", ] +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -79,6 +103,65 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a21b9440a626c7fc8573a9e3d3a06b75c7c97754c2949bc7857b90353ca655" +dependencies = [ + "as-slice", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "amplify" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e711289a6cb28171b4f0e6c8019c69ff9476050508dc082167575d458ff74d0" +dependencies = [ + "amplify_derive", + "amplify_num", + "ascii", + "wasm-bindgen", +] + +[[package]] +name = "amplify_derive" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759dcbfaf94d838367a86d493ec34ccc8aa6fe365cb7880d6bf89006de24d9c1" +dependencies = [ + "amplify_syn", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "amplify_num" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c009c5c4de814911b177e2ea59e4930bb918978ed3cce4900d846a6ceb0838" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "amplify_syn" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7736fb8d473c0d83098b5bac44df6a561e20470375cd8bcae30516dc889fd62a" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -103,6 +186,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + [[package]] name = "arc-swap" version = "0.4.8" @@ -115,16 +204,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" -[[package]] -name = "arrayvec" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" -dependencies = [ - "nodrop", - "odds", -] - [[package]] name = "arrayvec" version = "0.4.12" @@ -134,6 +213,359 @@ dependencies = [ "nodrop", ] +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "arti-client" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38167a7335592fa9ae726f4de0f8cb37c62f53e8547f2564844e047bf9b8c103" +dependencies = [ + "cfg-if 1.0.0", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more", + "educe", + "fs-mistrust", + "futures 0.3.29", + "hostname-validator", + "humantime-serde", + "libc", + "postage", + "safelog", + "serde", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-chanmgr", + "tor-circmgr", + "tor-config", + "tor-dirmgr", + "tor-error", + "tor-guardmgr", + "tor-hsclient", + "tor-hscrypto", + "tor-hsservice", + "tor-keymgr", + "tor-linkspec", + "tor-llcrypto", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-rtcompat", + "tracing", + "void", +] + +[[package]] +name = "arti-hyper" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990270b0c568f8e06386643962057a34204ae6ba5f68cba0a85650ace7b46b1e" +dependencies = [ + "anyhow", + "arti-client", + "educe", + "hyper 0.14.28", + "pin-project", + "thiserror", + "tls-api", + "tls-api-native-tls", + "tokio 1.37.0", + "tor-error", + "tor-rtcompat", +] + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +dependencies = [ + "concurrent-queue", + "event-listener 4.0.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "async-compression" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" +dependencies = [ + "flate2", + "futures-core", + "futures-io", + "memchr", + "pin-project-lite 0.2.13", + "xz2", + "zstd", + "zstd-safe", +] + +[[package]] +name = "async-executor" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +dependencies = [ + "async-lock 3.2.0", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite 2.1.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.1.1", + "async-executor", + "async-io 2.2.2", + "async-lock 3.2.0", + "blocking", + "futures-lite 2.1.0", + "once_cell", + "tokio 1.37.0", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg 1.1.0", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" +dependencies = [ + "async-lock 3.2.0", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-io", + "futures-lite 2.1.0", + "parking", + "polling 3.3.1", + "rustix 0.38.25", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +dependencies = [ + "event-listener 4.0.0", + "event-listener-strategy", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "async-native-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9343dc5acf07e79ff82d0c37899f079db3534d99f189a1837c8e549c99405bec" +dependencies = [ + "futures-util", + "native-tls", + "thiserror", + "url", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if 1.0.0", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +dependencies = [ + "async-io 2.2.2", + "async-lock 2.8.0", + "atomic-waker", + "cfg-if 1.0.0", + "futures-core", + "futures-io", + "rustix 0.38.25", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite 0.2.13", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46" + +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "async_executors" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a982d2f86de6137cc05c9db9a915a19886c97911f9790d04f174cede74be01a5" +dependencies = [ + "async-std", + "blanket", + "futures-core", + "futures-task", + "futures-util", + "pin-project", + "rustc_version", + "tokio 1.37.0", +] + +[[package]] +name = "asynchronous-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" +dependencies = [ + "bytes 1.5.0", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -175,6 +607,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.9.3" @@ -227,25 +665,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" -[[package]] -name = "bindgen" -version = "0.59.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2 1.0.69", - "quote 1.0.33", - "regex", - "rustc-hash", - "shlex", -] - [[package]] name = "bit-vec" version = "0.6.3" @@ -270,6 +689,18 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -280,6 +711,17 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blanket" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b121a9fe0df916e362fb3271088d071159cdf11db0e4182d02152850756eff" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -319,6 +761,28 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "blocking" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +dependencies = [ + "async-channel 2.1.1", + "async-lock 3.2.0", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite 2.1.0", + "piper", + "tracing", +] + +[[package]] +name = "bounded-vec-deque" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd" + [[package]] name = "bs58" version = "0.3.1" @@ -327,9 +791,9 @@ checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -341,12 +805,24 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" + [[package]] name = "byteorder" version = "1.5.0" @@ -375,24 +851,22 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "caret" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d55bb9904b8ef817fd66664cba4ecacac936781105c1016b0d2e13b900218db" + [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "0.1.10" @@ -412,11 +886,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ "cfg-if 1.0.0", - "cipher", + "cipher 0.3.0", "cpufeatures", "zeroize", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.4.4", + "cpufeatures", +] + [[package]] name = "chacha20poly1305" version = "0.9.1" @@ -424,8 +909,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" dependencies = [ "aead", - "chacha20", - "cipher", + "chacha20 0.8.2", + "cipher 0.3.0", "poly1305", "zeroize", ] @@ -442,7 +927,7 @@ dependencies = [ "num-traits 0.2.17", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -455,14 +940,14 @@ dependencies = [ ] [[package]] -name = "clang-sys" -version = "1.6.1" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "glob", - "libc", - "libloading", + "crypto-common", + "inout", + "zeroize", ] [[package]] @@ -490,12 +975,44 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "coarsetime" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b3839cf01bb7960114be3ccf2340f541b6d0c81f8690b007b2b39f750f7e5d" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] + +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie-factory" version = "0.3.2" @@ -514,11 +1031,11 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys 0.8.6", "libc", ] @@ -530,15 +1047,15 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -554,24 +1071,21 @@ dependencies = [ [[package]] name = "croaring" -version = "0.5.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aff1eea8a79ffa2a743c1322d5c3853d45699b7842197160c7c32a18c32c1866" +checksum = "7266f0a7275b00ce4c4f4753e8c31afdefe93828101ece83a06e2ddab1dd1010" dependencies = [ "byteorder", "croaring-sys", - "libc", ] [[package]] name = "croaring-sys" -version = "0.5.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d77e33a1d5e04573f79846692e72f2e02e0fdd942b90f023c45f146d3447db" +checksum = "e47112498c394a7067949ebc07ef429b7384a413cf0efcf675846a47bcd307fb" dependencies = [ - "bindgen", "cc", - "libc", ] [[package]] @@ -598,6 +1112,16 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -607,6 +1131,18 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -619,14 +1155,35 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array 0.14.7", "subtle", ] +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa 1.0.9", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "ct-logs" version = "0.6.0" @@ -636,6 +1193,25 @@ dependencies = [ "sct", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher 0.4.4", +] + +[[package]] +name = "ctrlc" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +dependencies = [ + "nix 0.27.1", + "windows-sys 0.48.0", +] + [[package]] name = "curve25519-dalek" version = "2.1.3" @@ -662,6 +1238,113 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "cvt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core 0.20.8", + "darling_macro 0.20.8", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.70", + "quote 1.0.33", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.70", + "quote 1.0.33", + "strsim 0.10.0", + "syn 2.0.39", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core 0.20.8", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -669,7 +1352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "lock_api 0.4.11", "once_cell", "parking_lot_core 0.9.9", @@ -677,9 +1360,129 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive-adhoc" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5283ac2881753c76c0892406705553f0d9ab30649f81e18964d3408f4501edb8" +dependencies = [ + "derive-adhoc-macros", + "heck 0.4.1", +] + +[[package]] +name = "derive-adhoc-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c21b673a9b8c78c34908e6fcb42b922e11c4df2de5237f1c3f58d3285904a84b" +dependencies = [ + "heck 0.4.1", + "itertools 0.10.5", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.70", + "quote 1.0.33", + "sha3 0.10.8", + "strum 0.25.0", + "syn 1.0.109", + "void", +] + +[[package]] +name = "derive-deftly" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c173dfcd5b92893ab05a8efb18b9522db4db6e0b93db5740f397573c027ce1e" +dependencies = [ + "derive-deftly-macros", + "heck 0.4.1", +] + +[[package]] +name = "derive-deftly-macros" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216fa20211bcd18cc359b75413bfb6cf89f62568fa27bc5fed3778a7a16e17af" +dependencies = [ + "heck 0.4.1", + "indexmap 2.1.0", + "itertools 0.12.0", + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.70", + "quote 1.0.33", + "sha3 0.10.8", + "strum 0.26.2", + "syn 2.0.39", + "void", +] + +[[package]] +name = "derive_builder_core_fork_arti" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c1b715c79be6328caa9a5e1a387a196ea503740f0722ec3dd8f67a9e72314d" +dependencies = [ + "darling 0.14.4", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_fork_arti" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3eae24d595f4d0ecc90a9a5a6d11c2bd8dafe2375ec4a1ec63250e5ade7d228" +dependencies = [ + "derive_builder_macro_fork_arti", +] + +[[package]] +name = "derive_builder_macro_fork_arti" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69887769a2489cd946bf782eb2b1bb2cb7bc88551440c94a765d4f040c08ebf3" +dependencies = [ + "derive_builder_core_fork_arti", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2 1.0.70", + "quote 1.0.33", + "rustc_version", + "syn 1.0.109", +] [[package]] name = "digest" @@ -706,10 +1509,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys 0.4.1", +] + [[package]] name = "dirs" version = "2.0.2" @@ -717,7 +1530,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ "cfg-if 0.1.10", - "dirs-sys", + "dirs-sys 0.3.7", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", ] [[package]] @@ -731,17 +1563,52 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "displaydoc" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "easy-jsonrpc-mw" version = "0.5.4" @@ -761,19 +1628,43 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6368dbd2c6685fb84fc6e6a4749917ddc98905793fd06341c7e11a2504f2724" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2 0.4.30", "quote 0.6.13", "syn 0.15.44", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature 2.2.0", + "spki", +] + [[package]] name = "ed25519" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ - "signature", + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature 2.2.0", ] [[package]] @@ -783,19 +1674,72 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ "curve25519-dalek 3.2.0", - "ed25519", + "ed25519 1.5.3", "rand 0.7.3", "serde", "sha2 0.9.9", "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.2", + "ed25519 2.2.3", + "merlin", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "educe" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" +dependencies = [ + "enum-ordinalize", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array 0.14.7", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -805,6 +1749,19 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "enum-ordinalize" +version = "3.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" +dependencies = [ + "num-bigint 0.4.4", + "num-traits 0.2.17", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "enum_primitive" version = "0.1.1" @@ -814,6 +1771,19 @@ dependencies = [ "num-traits 0.1.43", ] +[[package]] +name = "env_logger" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +dependencies = [ + "atty", + "humantime 1.3.0", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -822,12 +1792,61 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "event-listener" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "event-listener" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.0", + "pin-project-lite 0.2.13", ] [[package]] @@ -836,12 +1855,74 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" + +[[package]] +name = "figment" +version = "0.10.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" +dependencies = [ + "atomic 0.6.0", + "serde", + "toml 0.8.8", + "uncased", + "version_check", +] + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "find-crate" version = "0.6.3" @@ -882,7 +1963,7 @@ dependencies = [ "intl-memoizer", "intl_pluralrules", "rustc-hash", - "self_cell", + "self_cell 0.10.3", "smallvec", "unic-langid", ] @@ -905,6 +1986,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "fluid-let" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749cff877dc1af878a0b31a41dd221a753634401ea0ef2f87b62d3171522485a" + [[package]] name = "fnv" version = "1.0.7" @@ -928,13 +2015,30 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-mistrust" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5764b75624acb3ec878488145198a8fed761ca18fe26759d4ac4c7543fd2373a" +dependencies = [ + "derive_builder_fork_arti", + "dirs 5.0.1", + "educe", + "libc", + "once_cell", + "pwd-grp", + "serde", + "thiserror", + "walkdir", +] + [[package]] name = "fs2" version = "0.4.3" @@ -945,6 +2049,51 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "fs_at" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982f82cc75107eef84f417ad6c53ae89bf65b561937ca4a3b3b0fd04d0aa2425" +dependencies = [ + "aligned", + "cfg-if 1.0.0", + "cvt", + "libc", + "nix 0.26.4", + "windows-sys 0.48.0", +] + +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "fslock-arti-fork" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21bd626aaab7b904b20bef6d9e06298914a0c8d9fb8b010483766b2e532791" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "fslock-guard" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9267d03223dd8877b0a3f8341661d21b7ba6a18e90f60e92e550addd30bc32c7" +dependencies = [ + "fslock-arti-fork", + "thiserror", + "winapi 0.3.9", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -982,6 +2131,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673464e1e314dd67a0fd9544abc99e8eb28d0c7e3b69b033bcff9b2d00b87333" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.1.31" @@ -990,9 +2145,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1005,9 +2160,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1015,15 +2170,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1032,38 +2187,77 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.13", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +dependencies = [ + "fastrand 2.0.1", + "futures-core", + "futures-io", + "parking", + "pin-project-lite 0.2.13", +] [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", +] + +[[package]] +name = "futures-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" +dependencies = [ + "futures-io", + "rustls 0.23.5", + "rustls-pki-types", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1100,6 +2294,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1115,94 +2310,77 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] -name = "glob" -version = "0.3.1" +name = "glob-match" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "9985c9503b412198aa4197559e9a318524ebc4519c229bfa05a535828c950b9d" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", ] [[package]] name = "grin_api" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "371de4435e3681a028a0741e4c4c9fa0be7ec95b86a89fef82e534c7de6e79ca" dependencies = [ "bytes 0.5.6", "easy-jsonrpc-mw", - "futures 0.3.28", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_p2p 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_pool 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "http", + "futures 0.3.29", + "grin_chain", + "grin_core", + "grin_p2p", + "grin_pool", + "grin_store", + "grin_util", + "http 0.2.11", "hyper 0.13.10", "hyper-rustls 0.20.0", "hyper-timeout", "lazy_static", "log", "regex", - "ring", - "rustls 0.17.0", - "serde", - "serde_derive", - "serde_json", - "thiserror", - "tokio 0.2.25", - "tokio-rustls 0.13.1", - "url", -] - -[[package]] -name = "grin_api" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "bytes 0.5.6", - "easy-jsonrpc-mw", - "futures 0.3.28", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_p2p 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_pool 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "http", - "hyper 0.13.10", - "hyper-rustls 0.20.0", - "hyper-timeout", - "lazy_static", - "log", - "regex", - "ring", + "ring 0.16.20", "rustls 0.17.0", "serde", "serde_derive", @@ -1215,8 +2393,9 @@ dependencies = [ [[package]] name = "grin_chain" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1987d095cb41dffb7f67f4ae97acd0141fc77df28e1af376f8b4ab784d5ab54" dependencies = [ "bit-vec", "bitflags 1.3.2", @@ -1224,33 +2403,10 @@ dependencies = [ "chrono", "croaring", "enum_primitive", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "lazy_static", - "log", - "lru-cache", - "serde", - "serde_derive", - "thiserror", -] - -[[package]] -name = "grin_chain" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "bit-vec", - "bitflags 1.3.2", - "byteorder", - "chrono", - "croaring", - "enum_primitive", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_core", + "grin_keychain", + "grin_store", + "grin_util", "lazy_static", "log", "lru-cache", @@ -1261,8 +2417,9 @@ dependencies = [ [[package]] name = "grin_core" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d3887c1090b18862424ed4ad1929f6c9b81709cfcca8bf8b88c928d4af2167" dependencies = [ "blake2-rfc", "byteorder", @@ -1270,39 +2427,13 @@ dependencies = [ "chrono", "croaring", "enum_primitive", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "grin_keychain", + "grin_util", "lazy_static", "log", "lru-cache", "num", - "num-bigint", - "rand 0.6.5", - "serde", - "serde_derive", - "siphasher", - "thiserror", - "zeroize", -] - -[[package]] -name = "grin_core" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "blake2-rfc", - "byteorder", - "bytes 0.5.6", - "chrono", - "croaring", - "enum_primitive", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "lazy_static", - "log", - "lru-cache", - "num", - "num-bigint", + "num-bigint 0.2.6", "rand 0.6.5", "serde", "serde_derive", @@ -1313,35 +2444,14 @@ dependencies = [ [[package]] name = "grin_keychain" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2864c09ee9ac184a2a580a6f34debd642011a34fd40af6ab26c084b1aea951ac" dependencies = [ "blake2-rfc", "byteorder", "digest 0.9.0", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "hmac 0.11.0", - "lazy_static", - "log", - "pbkdf2 0.8.0", - "rand 0.6.5", - "ripemd160", - "serde", - "serde_derive", - "serde_json", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "grin_keychain" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "blake2-rfc", - "byteorder", - "digest 0.9.0", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_util", "hmac 0.11.0", "lazy_static", "log", @@ -1362,23 +2472,23 @@ dependencies = [ "blake2-rfc", "byteorder", "bytes 0.5.6", - "chacha20", + "chacha20 0.8.2", "curve25519-dalek 2.1.3", - "ed25519-dalek", - "grin_api 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "ed25519-dalek 1.0.1", + "grin_api", + "grin_chain", + "grin_core", + "grin_keychain", "grin_secp256k1zkp", "grin_servers", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_store", + "grin_util", "grin_wallet_api", "grin_wallet_impls", "grin_wallet_libwallet", "grin_wallet_util", "hmac 0.12.1", - "itertools", + "itertools 0.10.5", "lazy_static", "rand 0.7.3", "rpassword", @@ -1393,39 +2503,18 @@ dependencies = [ [[package]] name = "grin_p2p" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8968c6b250cc928eb8467c0ed283d53676ae5896f8396d6136b0d2dc5fa77f" dependencies = [ "bitflags 1.3.2", "bytes 0.5.6", "chrono", "enum_primitive", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "log", - "lru-cache", - "num", - "rand 0.6.5", - "serde", - "serde_derive", - "tempfile", -] - -[[package]] -name = "grin_p2p" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "bitflags 1.3.2", - "bytes 0.5.6", - "chrono", - "enum_primitive", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_chain", + "grin_core", + "grin_store", + "grin_util", "log", "lru-cache", "num", @@ -1437,31 +2526,15 @@ dependencies = [ [[package]] name = "grin_pool" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1828edf8e05010fbd3a19ff6e73740a696fbb681859617805c25eb66480ce0d8" dependencies = [ "blake2-rfc", "chrono", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "log", - "rand 0.6.5", - "serde", - "serde_derive", - "thiserror", -] - -[[package]] -name = "grin_pool" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "blake2-rfc", - "chrono", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_core", + "grin_keychain", + "grin_util", "log", "rand 0.6.5", "serde", @@ -1471,15 +2544,14 @@ dependencies = [ [[package]] name = "grin_secp256k1zkp" -version = "0.7.12" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04798e32404c0af082b6a209ad4df1ab1d9ec3a5a5056f284cfa32f74e59ce6" +checksum = "06832645c3d28079245827908045946db48e5d62b4c54b40701c7e21327e2571" dependencies = [ - "arrayvec 0.3.25", + "arrayvec 0.7.4", "cc", "libc", "rand 0.5.6", - "rustc-serialize", "serde", "serde_json", "zeroize", @@ -1487,21 +2559,22 @@ dependencies = [ [[package]] name = "grin_servers" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde13741fc12858b6eb10936bcbe4b7c3b9f79fa7a75a7e083445b76e0bb6547" dependencies = [ "chrono", "fs2", - "futures 0.3.28", - "grin_api 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_p2p 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_pool 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "http", + "futures 0.3.29", + "grin_api", + "grin_chain", + "grin_core", + "grin_keychain", + "grin_p2p", + "grin_pool", + "grin_store", + "grin_util", + "http 0.2.11", "hyper 0.13.10", "hyper-rustls 0.20.0", "lmdb-zero", @@ -1517,32 +2590,14 @@ dependencies = [ [[package]] name = "grin_store" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a81f65738f02e2af799e3b596996a7be3087df8ae478241b41a62c00623840" dependencies = [ "byteorder", "croaring", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "libc", - "lmdb-zero", - "log", - "memmap", - "serde", - "serde_derive", - "tempfile", - "thiserror", -] - -[[package]] -name = "grin_store" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" -dependencies = [ - "byteorder", - "croaring", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_core", + "grin_util", "libc", "lmdb-zero", "log", @@ -1555,29 +2610,9 @@ dependencies = [ [[package]] name = "grin_util" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" -dependencies = [ - "backtrace", - "base64 0.12.3", - "byteorder", - "grin_secp256k1zkp", - "lazy_static", - "log", - "log4rs", - "parking_lot 0.10.2", - "rand 0.6.5", - "serde", - "serde_derive", - "walkdir", - "zeroize", - "zip", -] - -[[package]] -name = "grin_util" -version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?branch=master#05ec6fda38015a08918f27aa6e380e3c7283405f" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e644f4a7e648c7038226417de9e2101743ce337ad60539a1ec6580571a04ad3" dependencies = [ "backtrace", "base64 0.12.3", @@ -1597,23 +2632,24 @@ dependencies = [ [[package]] name = "grin_wallet_api" -version = "5.2.0-beta.1" -source = "git+https://github.com/mimblewimble/grin-wallet?tag=v5.2.0-beta.1#12a25f82f1a799caa738f3d7cf42e8ee2b13f005" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d99b560f3c1257833b5abea1db06ac4736a2501421074768b3dcb775a1a8508e" dependencies = [ "base64 0.12.3", "chrono", "easy-jsonrpc-mw", - "ed25519-dalek", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "ed25519-dalek 1.0.1", + "grin_core", + "grin_keychain", + "grin_util", "grin_wallet_config", "grin_wallet_impls", "grin_wallet_libwallet", "grin_wallet_util", "log", "rand 0.6.5", - "ring", + "ring 0.16.20", "serde", "serde_derive", "serde_json", @@ -1622,12 +2658,13 @@ dependencies = [ [[package]] name = "grin_wallet_config" -version = "5.2.0-beta.1" -source = "git+https://github.com/mimblewimble/grin-wallet?tag=v5.2.0-beta.1#12a25f82f1a799caa738f3d7cf42e8ee2b13f005" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa93a3be58950ac13dd6d4aa51737e1bbc0befb9f44dfde12e233eb169071b0" dependencies = [ - "dirs", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "dirs 2.0.2", + "grin_core", + "grin_util", "grin_wallet_util", "rand 0.6.5", "serde", @@ -1635,24 +2672,60 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "grin_wallet_controller" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321061a9ba48b0241d07dd4c2dcf69acd0923d7f7b040265d1d8a224fb9c0ac9" +dependencies = [ + "chrono", + "easy-jsonrpc-mw", + "futures 0.3.29", + "grin_api", + "grin_core", + "grin_keychain", + "grin_util", + "grin_wallet_api", + "grin_wallet_config", + "grin_wallet_impls", + "grin_wallet_libwallet", + "grin_wallet_util", + "hyper 0.13.10", + "lazy_static", + "log", + "prettytable-rs", + "qr_code", + "rand 0.7.3", + "ring 0.16.20", + "serde", + "serde_derive", + "serde_json", + "term 0.6.1", + "thiserror", + "tokio 0.2.25", + "url", + "uuid", +] + [[package]] name = "grin_wallet_impls" -version = "5.2.0-beta.1" -source = "git+https://github.com/mimblewimble/grin-wallet?tag=v5.2.0-beta.1#12a25f82f1a799caa738f3d7cf42e8ee2b13f005" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5630eca4cf5dca99d89753571a112fd13f2b29d8c05faabbaeebec065deb2bf2" dependencies = [ "base64 0.12.3", "blake2-rfc", "byteorder", "chrono", "data-encoding", - "ed25519-dalek", - "futures 0.3.28", - "grin_api 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "ed25519-dalek 1.0.1", + "futures 0.3.29", + "grin_api", + "grin_chain", + "grin_core", + "grin_keychain", + "grin_store", + "grin_util", "grin_wallet_config", "grin_wallet_libwallet", "grin_wallet_util", @@ -1661,7 +2734,7 @@ dependencies = [ "rand 0.6.5", "regex", "reqwest", - "ring", + "ring 0.16.20", "serde", "serde_derive", "serde_json", @@ -1676,8 +2749,9 @@ dependencies = [ [[package]] name = "grin_wallet_libwallet" -version = "5.2.0-beta.1" -source = "git+https://github.com/mimblewimble/grin-wallet?tag=v5.2.0-beta.1#12a25f82f1a799caa738f3d7cf42e8ee2b13f005" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27b3a75037f69e51bd1b52bb6a4a13d8dd8a764d2477ab944c9e67410d913df" dependencies = [ "age", "base64 0.9.3", @@ -1687,16 +2761,16 @@ dependencies = [ "byteorder", "chrono", "curve25519-dalek 2.1.3", - "ed25519-dalek", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "ed25519-dalek 1.0.1", + "grin_core", + "grin_keychain", + "grin_store", + "grin_util", "grin_wallet_config", "grin_wallet_util", "lazy_static", "log", - "num-bigint", + "num-bigint 0.2.6", "rand 0.6.5", "regex", "secrecy 0.6.0", @@ -1704,8 +2778,8 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.8.2", - "strum", - "strum_macros", + "strum 0.18.0", + "strum_macros 0.18.0", "thiserror", "uuid", "x25519-dalek 0.6.0", @@ -1713,19 +2787,43 @@ dependencies = [ [[package]] name = "grin_wallet_util" -version = "5.2.0-beta.1" -source = "git+https://github.com/mimblewimble/grin-wallet?tag=v5.2.0-beta.1#12a25f82f1a799caa738f3d7cf42e8ee2b13f005" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ffdc9f591de5ba9194e2add286a4c37d04ad5c3f502dada10de8c282b2990c" dependencies = [ "data-encoding", - "ed25519-dalek", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3)", + "ed25519-dalek 1.0.1", + "grin_util", "rand 0.6.5", "serde", "serde_derive", - "sha3", + "sha3 0.8.2", "thiserror", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "growable-bloom-filter" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c669fa03050eb3445343f215d62fc1ab831e8098bc9a55f26e9724faff11075c" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "xxhash-rust", +] + [[package]] name = "h2" version = "0.2.7" @@ -1737,7 +2835,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.11", "indexmap 1.9.3", "slab", "tokio 0.2.25", @@ -1746,25 +2844,6 @@ dependencies = [ "tracing-futures", ] -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes 1.5.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 1.9.3", - "slab", - "tokio 1.33.0", - "tokio-util 0.7.9", - "tracing", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1773,32 +2852,21 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" - -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "base64 0.21.5", - "bytes 1.5.0", - "headers-core", - "http", - "httpdate 1.0.3", - "mime", - "sha1", + "ahash", + "allocator-api2", ] [[package]] -name = "headers-core" -version = "0.2.0" +name = "hashlink" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee" dependencies = [ - "http", + "hashbrown 0.14.3", ] [[package]] @@ -1810,6 +2878,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1825,6 +2899,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hkdf" version = "0.11.0" @@ -1835,6 +2915,15 @@ dependencies = [ "hmac 0.11.0", ] +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + [[package]] name = "hmac" version = "0.11.0" @@ -1855,10 +2944,27 @@ dependencies = [ ] [[package]] -name = "http" -version = "0.2.9" +name = "hostname-validator" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes 1.5.0", + "fnv", + "itoa 1.0.9", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes 1.5.0", "fnv", @@ -1872,7 +2978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ "bytes 0.5.6", - "http", + "http 0.2.11", ] [[package]] @@ -1882,7 +2988,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes 1.5.0", - "http", + "http 0.2.11", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes 1.5.0", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes 1.5.0", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite 0.2.13", ] @@ -1913,6 +3042,22 @@ dependencies = [ "quick-error", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" +dependencies = [ + "humantime 2.1.0", + "serde", +] + [[package]] name = "hyper" version = "0.13.10" @@ -1923,8 +3068,8 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.2.7", - "http", + "h2", + "http 0.2.11", "http-body 0.3.1", "httparse", "httpdate 0.3.2", @@ -1939,44 +3084,40 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes 1.5.0", "futures-channel", "futures-core", "futures-util", - "h2 0.3.21", - "http", + "http 0.2.11", "http-body 0.4.5", "httparse", "httpdate 1.0.3", "itoa 1.0.9", "pin-project-lite 0.2.13", - "socket2 0.4.10", - "tokio 1.33.0", + "socket2 0.5.5", + "tokio 1.37.0", "tower-service", "tracing", "want", ] [[package]] -name = "hyper-proxy" -version = "0.9.1" +name = "hyper" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes 1.5.0", - "futures 0.3.28", - "headers", - "http", - "hyper 0.14.27", - "hyper-tls 0.5.0", - "native-tls", - "tokio 1.33.0", - "tokio-native-tls", - "tower-service", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite 0.2.13", + "smallvec", + "tokio 1.37.0", + "want", ] [[package]] @@ -1994,7 +3135,7 @@ dependencies = [ "rustls-native-certs", "tokio 0.2.25", "tokio-rustls 0.13.1", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -2010,7 +3151,7 @@ dependencies = [ "rustls 0.18.1", "tokio 0.2.25", "tokio-rustls 0.14.1", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -2040,15 +3181,38 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes 1.5.0", - "hyper 0.14.27", + "http-body-util", + "hyper 1.2.0", + "hyper-util", "native-tls", - "tokio 1.33.0", + "tokio 1.37.0", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes 1.5.0", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite 0.2.13", + "socket2 0.5.5", + "tokio 1.37.0", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -2061,7 +3225,7 @@ dependencies = [ "serde", "serde_derive", "thiserror", - "toml 0.8.4", + "toml 0.8.8", "unic-langid", ] @@ -2100,24 +3264,24 @@ dependencies = [ "i18n-embed", "lazy_static", "proc-macro-error", - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "strsim 0.10.0", - "syn 2.0.38", + "syn 2.0.39", "unic-langid", ] [[package]] name = "i18n-embed-impl" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a4d5bff745c9a6e1459c490059281b353a4ab0a4e1e58b3eeeaef71f97d07b" +checksum = "81093c4701672f59416582fe3145676126fd23ba5db910acad0793c1108aaa58" dependencies = [ "find-crate", "i18n-config", - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2127,7 +3291,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", - "core-foundation-sys 0.8.4", + "core-foundation-sys 0.8.6", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", @@ -2144,10 +3308,16 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2161,16 +3331,27 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", + "serde", ] [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.7", ] [[package]] @@ -2201,6 +3382,23 @@ dependencies = [ "unic-langid", ] +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.3", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -2216,6 +3414,17 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.3", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2225,6 +3434,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2238,10 +3456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] -name = "js-sys" -version = "0.3.64" +name = "jobserver" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "f08474e32172238f2827bd160c67871cdb2801430f65c3979184dc362e3ca118" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -2265,7 +3492,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.28", + "futures 0.3.29", "futures-executor", "futures-util", "log", @@ -2280,8 +3507,8 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.69", + "proc-macro-crate 0.1.5", + "proc-macro2 1.0.70", "quote 1.0.33", "syn 1.0.109", ] @@ -2292,8 +3519,8 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.28", - "hyper 0.14.27", + "futures 0.3.29", + "hyper 0.14.28", "jsonrpc-core 18.0.0", "jsonrpc-server-utils", "log", @@ -2309,17 +3536,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.5.0", - "futures 0.3.28", + "futures 0.3.29", "globset", "jsonrpc-core 18.0.0", "lazy_static", "log", - "tokio 1.33.0", + "tokio 1.37.0", "tokio-stream", "tokio-util 0.6.10", "unicase", ] +[[package]] +name = "k12" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4dc5fdb62af2f520116927304f15d25b3c2667b4817b90efdc045194c912c54" +dependencies = [ + "digest 0.10.7", + "sha3 0.10.8", +] + [[package]] name = "keccak" version = "0.1.4" @@ -2339,23 +3576,29 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "liblmdb-sys" @@ -2368,13 +3611,31 @@ dependencies = [ ] [[package]] -name = "libloading" -version = "0.7.4" +name = "libm" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", ] [[package]] @@ -2385,9 +3646,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lmdb-zero" @@ -2427,6 +3694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" dependencies = [ "serde", + "value-bag", ] [[package]] @@ -2445,13 +3713,13 @@ dependencies = [ "chrono", "flate2", "fnv", - "humantime", + "humantime 1.3.0", "libc", "log", "log-mdc", "parking_lot 0.10.2", "serde", - "serde-value", + "serde-value 0.6.0", "serde_derive", "serde_json", "serde_yaml", @@ -2469,6 +3737,26 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.6.4" @@ -2485,6 +3773,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "memmap2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -2494,6 +3791,18 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -2552,7 +3861,7 @@ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2603,48 +3912,69 @@ dependencies = [ name = "mwixnet" version = "0.1.0" dependencies = [ + "arti-client", + "arti-hyper", + "async-std", + "async-trait", "blake2-rfc", "byteorder", - "bytes 0.5.6", - "chacha20", + "bytes 1.5.0", + "chacha20 0.9.1", + "chrono", "clap", - "curve25519-dalek 2.1.3", - "dirs", - "ed25519-dalek", + "ctrlc", + "curve25519-dalek 4.1.2", + "dirs 2.0.2", + "ed25519-dalek 2.1.1", + "fs-mistrust", "function_name", - "futures 0.3.28", - "grin_api 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_chain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_core 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_keychain 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "futures 0.3.29", + "grin_api", + "grin_chain", + "grin_core", + "grin_keychain", "grin_onion", + "grin_p2p", "grin_secp256k1zkp", "grin_servers", - "grin_store 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", - "grin_util 5.2.0-beta.3 (git+https://github.com/mimblewimble/grin?branch=master)", + "grin_store", + "grin_util", "grin_wallet_api", + "grin_wallet_config", + "grin_wallet_controller", "grin_wallet_impls", "grin_wallet_libwallet", "grin_wallet_util", "hmac 0.12.1", - "hyper 0.14.27", - "hyper-proxy", - "itertools", + "hyper 0.14.28", + "hyper-tls 0.6.0", + "itertools 0.12.0", "jsonrpc-core 18.0.0", "jsonrpc-derive", "jsonrpc-http-server", "lazy_static", + "log", "pbkdf2 0.8.0", "rand 0.7.3", - "ring", + "remove_dir_all", + "ring 0.16.20", "rpassword", + "rusqlite", "serde", "serde_derive", "serde_json", "sha2 0.10.8", "thiserror", - "tokio 1.33.0", - "toml 0.5.11", + "tls-api", + "tls-api-native-tls", + "tokio 1.37.0", + "toml 0.8.8", + "tor-hscrypto", + "tor-hsrproxy", + "tor-hsservice", + "tor-keymgr", + "tor-llcrypto", + "tor-rtcompat", "x25519-dalek 0.6.0", ] @@ -2677,6 +4007,28 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "libc", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2693,6 +4045,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normpath" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -2702,13 +4063,23 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi 0.3.9", +] + [[package]] name = "num" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" dependencies = [ - "num-bigint", + "num-bigint 0.2.6", "num-complex", "num-integer", "num-iter", @@ -2727,6 +4098,34 @@ dependencies = [ "num-traits 0.2.17", ] +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits 0.2.17", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits 0.2.17", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-complex" version = "0.2.4" @@ -2737,6 +4136,12 @@ dependencies = [ "num-traits 0.2.17", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.45" @@ -2765,7 +4170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg 1.1.0", - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits 0.2.17", ] @@ -2786,6 +4191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg 1.1.0", + "libm", ] [[package]] @@ -2798,6 +4204,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "object" version = "0.32.1" @@ -2807,12 +4234,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "odds" -version = "0.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" - [[package]] name = "once_cell" version = "1.18.0" @@ -2833,9 +4254,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ "bitflags 2.4.1", "cfg-if 1.0.0", @@ -2852,9 +4273,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2865,9 +4286,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", @@ -2875,6 +4296,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "1.1.1" @@ -2884,6 +4311,65 @@ dependencies = [ "num-traits 0.2.17", ] +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits 0.2.17", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.8", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.8", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core 0.6.4", + "sha2 0.10.8", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.10.2" @@ -2953,20 +4439,26 @@ dependencies = [ "libc", "redox_syscall 0.4.1", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] name = "password-hash" -version = "0.2.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e0b28ace46c5a396546bcf443bf422b57049617433d8854227352a4a9b24e7" +checksum = "c1a5d4e9c205d2c1ae73b84aab6240e98218c0e72e63b50422cfb2d1ca952282" dependencies = [ "base64ct", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "pbkdf2" version = "0.8.0" @@ -2990,16 +4482,72 @@ dependencies = [ ] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "pem" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64 0.13.1", + "once_cell", + "regex", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] [[package]] name = "pin-project" @@ -3016,9 +4564,9 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3039,12 +4587,80 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg 1.1.0", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "concurrent-queue", + "libc", + "log", + "pin-project-lite 0.2.13", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +dependencies = [ + "cfg-if 1.0.0", + "concurrent-queue", + "pin-project-lite 0.2.13", + "rustix 0.38.25", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "poly1305" version = "0.7.2" @@ -3056,12 +4672,66 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "postage" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1" +dependencies = [ + "atomic 0.5.3", + "crossbeam-queue", + "futures 0.3.29", + "parking_lot 0.12.1", + "pin-project", + "static_assertions", + "thiserror", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term 0.7.0", + "unicode-width", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "priority-queue" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" +dependencies = [ + "autocfg 1.1.0", + "indexmap 1.9.3", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -3071,6 +4741,25 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.0", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3078,7 +4767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "syn 1.0.109", "version_check", @@ -3090,7 +4779,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "version_check", ] @@ -3106,13 +4795,31 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "pwd-grp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6955c41fd7e4283bdf6ff3e7218b7e3f8ef24c4236b31d22be050f4cfd5e2a2c" +dependencies = [ + "derive-adhoc", + "libc", + "paste", + "thiserror", +] + +[[package]] +name = "qr_code" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5520fbcd7da152a449261c5a533a1c7fad044e9e8aa9528cfec3f464786c7926" + [[package]] name = "quick-error" version = "1.2.3" @@ -3134,9 +4841,15 @@ version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.5.6" @@ -3253,7 +4966,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -3327,6 +5040,12 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rangemap" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" + [[package]] name = "rayon" version = "1.8.0" @@ -3371,15 +5090,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3391,12 +5101,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -3408,8 +5118,17 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -3420,15 +5139,37 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.2", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "remove_dir_all" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23895cfadc1917fed9c6ed76a8c2903615fa3704f7493ff82b364c6540acc02b" +dependencies = [ + "aligned", + "cfg-if 1.0.0", + "cvt", + "fs_at", + "lazy_static", + "libc", + "normpath", + "windows-sys 0.45.0", +] + [[package]] name = "reqwest" version = "0.10.10" @@ -3440,7 +5181,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "http", + "http 0.2.11", "http-body 0.3.1", "hyper 0.13.10", "hyper-rustls 0.21.0", @@ -3469,6 +5210,22 @@ dependencies = [ "winreg", ] +[[package]] +name = "retry-error" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dea0c97723329951a3ed41ce0de8b8e389de3de4b815fb86ff57f6ab868f04" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + [[package]] name = "ring" version = "0.16.20" @@ -3478,12 +5235,27 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi 0.3.9", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom 0.2.11", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -3505,6 +5277,42 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits 0.2.17", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "sha2 0.10.8", + "signature 2.2.0", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rusqlite" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" +dependencies = [ + "bitflags 2.4.1", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", + "time", +] + [[package]] name = "rust-embed" version = "6.8.1" @@ -3522,10 +5330,10 @@ version = "6.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "rust-embed-utils", - "syn 2.0.38", + "syn 2.0.39", "walkdir", ] @@ -3552,22 +5360,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] [[package]] name = "rustix" -version = "0.38.20" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.4.12", + "windows-sys 0.48.0", ] [[package]] @@ -3578,9 +5403,9 @@ checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" dependencies = [ "base64 0.11.0", "log", - "ring", + "ring 0.16.20", "sct", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -3591,9 +5416,24 @@ checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ "base64 0.12.3", "log", - "ring", + "ring 0.16.20", "sct", - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.23.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" +dependencies = [ + "log", + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] @@ -3608,12 +5448,48 @@ dependencies = [ "security-framework 0.4.4", ] +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "safelog" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea892f8598a3682b6ed10ed9d8522b50366a792953eda37e1d9ddf01e183e3f" +dependencies = [ + "derive_more", + "educe", + "either", + "fluid-let", + "thiserror", +] + [[package]] name = "safemem" version = "0.3.3" @@ -3626,7 +5502,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -3638,13 +5514,23 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sanitize-filename" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ed72fbaf78e6f2d41744923916966c4fbe3d7c74e3037a8ee482f1115572603" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "schannel" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3671,8 +5557,22 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.7", + "pkcs8", + "subtle", + "zeroize", ] [[package]] @@ -3713,8 +5613,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.3", - "core-foundation-sys 0.8.4", + "core-foundation 0.9.4", + "core-foundation-sys 0.8.6", "libc", "security-framework-sys 2.9.1", ] @@ -3735,21 +5635,36 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys 0.8.6", "libc", ] [[package]] name = "self_cell" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.2", +] + +[[package]] +name = "self_cell" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -3760,26 +5675,54 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" dependencies = [ - "ordered-float", + "ordered-float 1.1.1", + "serde", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float 2.10.1", + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", +] + +[[package]] +name = "serde_ignored" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80c31d5c53fd39f208e770f5a20a0bb214dee2a8d0d8adba18e19ad95a482ca5" +dependencies = [ + "serde", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa 1.0.9", "ryu", @@ -3807,6 +5750,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.5", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling 0.20.8", + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "serde_yaml" version = "0.8.26" @@ -3880,10 +5853,32 @@ dependencies = [ ] [[package]] -name = "shlex" -version = "1.2.0" +name = "sha3" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs 5.0.1", +] [[package]] name = "signal-hook-registry" @@ -3900,6 +5895,28 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint 0.4.4", + "num-traits 0.2.17", + "thiserror", + "time", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -3916,10 +5933,19 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.1" +name = "slotmap" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -3949,7 +5975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3958,6 +5984,75 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher 0.4.4", + "ssh-encoding", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "pem-rfc7468", + "sha2 0.10.8", +] + +[[package]] +name = "ssh-key" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b71299a724c8d84956caaf8fc3b3ea57c3587fe2d0b800cd0dc1f3599905d7e" +dependencies = [ + "p256", + "p384", + "p521", + "rand_core 0.6.4", + "rsa", + "sec1", + "sha2 0.10.8", + "signature 2.2.0", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" @@ -3976,23 +6071,67 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros 0.26.2", +] + [[package]] name = "strum_macros" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ - "heck", - "proc-macro2 1.0.69", + "heck 0.3.3", + "proc-macro2 1.0.70", "quote 1.0.33", "syn 1.0.109", ] [[package]] -name = "subtle" -version = "2.4.1" +name = "strum_macros" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2 1.0.70", + "quote 1.0.33", + "rustversion", + "syn 2.0.39", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2 1.0.70", + "quote 1.0.33", + "rustversion", + "syn 2.0.39", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "supercow" @@ -4017,30 +6156,30 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "unicode-ident", ] [[package]] name = "sysinfo" -version = "0.29.10" +version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" +checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ "cfg-if 1.0.0", - "core-foundation-sys 0.8.4", + "core-foundation-sys 0.8.6", "libc", "ntapi", "once_cell", @@ -4049,16 +6188,63 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.8.0" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if 1.0.0", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys", + "fastrand 2.0.1", + "redox_syscall 0.4.1", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + +[[package]] +name = "term" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" +dependencies = [ + "dirs 2.0.2", + "winapi 0.3.9", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi 0.3.9", +] + +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-cert-gen" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345f92b7cac59507cdaba298c5493f7c40e2063d31f6fc621105183344d5d50a" +dependencies = [ + "once_cell", + "pem", + "tempfile", ] [[package]] @@ -4072,20 +6258,20 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "syn 1.0.109", ] @@ -4101,6 +6287,47 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef89ece63debf11bc32d1ed8d078ac870cbeb44da02afb02a9ff135ae7ca0582" +dependencies = [ + "deranged", + "itoa 1.0.9", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "timer" version = "0.2.0" @@ -4112,9 +6339,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0e245e80bdc9b4e5356fc45a72184abbc3861992603f515270e9340f5a219" +checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece" dependencies = [ "displaydoc", ] @@ -4134,6 +6361,53 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tls-api" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d1b3dfb0a60da3e8a130c9f2432063d9979928a05c2b2cdcfc9fd05e4f53a3" +dependencies = [ + "anyhow", + "log", + "pem", + "tempfile", + "thiserror", + "tokio 1.37.0", + "void", + "webpki 0.22.4", +] + +[[package]] +name = "tls-api-native-tls" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b935bda2458120a5d2cea542013796fcf13937566580027f6a08f42a52206f7" +dependencies = [ + "anyhow", + "native-tls", + "thiserror", + "tls-api", + "tls-api-test", + "tokio 1.37.0", +] + +[[package]] +name = "tls-api-test" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df107843d725428d76bb159040fbae6d1524dcf25d5b24c56daa6b37ce9dbb5" +dependencies = [ + "anyhow", + "env_logger", + "log", + "pem", + "test-cert-gen", + "tls-api", + "tokio 1.37.0", + "untrusted 0.6.2", + "webpki 0.22.4", +] + [[package]] name = "tokio" version = "0.2.25" @@ -4160,9 +6434,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.33.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes 1.5.0", @@ -4173,8 +6447,8 @@ dependencies = [ "pin-project-lite 0.2.13", "signal-hook-registry", "socket2 0.5.5", - "tokio-macros 2.1.0", - "windows-sys", + "tokio-macros 2.2.0", + "windows-sys 0.48.0", ] [[package]] @@ -4193,20 +6467,20 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", "syn 1.0.109", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4216,7 +6490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.33.0", + "tokio 1.37.0", ] [[package]] @@ -4228,7 +6502,7 @@ dependencies = [ "futures-core", "rustls 0.17.0", "tokio 0.2.25", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -4240,7 +6514,7 @@ dependencies = [ "futures-core", "rustls 0.18.1", "tokio 0.2.25", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -4251,20 +6525,20 @@ checksum = "d611fd5d241872372d52a0a3d309c52d0b95a6a67671a6c8f7ab2c4a37fb2539" dependencies = [ "bytes 0.4.12", "either", - "futures 0.3.28", + "futures 0.3.29", "thiserror", "tokio 0.2.25", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite 0.2.13", - "tokio 1.33.0", + "tokio 1.37.0", ] [[package]] @@ -4316,21 +6590,21 @@ dependencies = [ "futures-sink", "log", "pin-project-lite 0.2.13", - "tokio 1.33.0", + "tokio 1.37.0", ] [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes 1.5.0", "futures-core", + "futures-io", "futures-sink", "pin-project-lite 0.2.13", - "tokio 1.33.0", - "tracing", + "tokio 1.37.0", ] [[package]] @@ -4344,14 +6618,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef75d881185fd2df4a040793927c153d863651108a93c7e17a9e591baa95cc6" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.21.0", ] [[package]] @@ -4365,17 +6639,903 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.4" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380f9e8120405471f7c9ad1860a713ef5ece6a670c7eae39225e477340f32fc4" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "tor-async-utils" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b48a1a2254a32b504478be8fbcac5ca9d747b6e10bd34f9559f0a92864690d6" +dependencies = [ + "futures 0.3.29", + "pin-project", + "postage", + "void", +] + +[[package]] +name = "tor-basic-utils" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b38dac0caaa5913fb93276fc564f8e9fd082121d2a23176fe2e3108d182b85" +dependencies = [ + "hex", + "libc", + "paste", + "rand 0.8.5", + "rand_chacha 0.3.1", + "slab", + "thiserror", +] + +[[package]] +name = "tor-bytes" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f830b62e4df202e6783d5d7baa73eb5ef47cadf4aea40921512b95a6f8a1da89" +dependencies = [ + "bytes 1.5.0", + "digest 0.10.7", + "educe", + "getrandom 0.2.11", + "thiserror", + "tor-error", + "tor-llcrypto", + "zeroize", +] + +[[package]] +name = "tor-cell" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e3549cd797a8cb9c54a50287328157f652f341ccc64089088c7689ea9f759c" +dependencies = [ + "bitflags 2.4.1", + "bytes 1.5.0", + "caret", + "derive_more", + "educe", + "paste", + "rand 0.8.5", + "smallvec", + "thiserror", + "tor-basic-utils", + "tor-bytes", + "tor-cert", + "tor-error", + "tor-hscrypto", + "tor-linkspec", + "tor-llcrypto", + "tor-units", +] + +[[package]] +name = "tor-cert" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d049223a0f4d5965f8e947f1b1b559b72a6cacdc904dcf296e49ce503f6821e5" +dependencies = [ + "caret", + "derive_builder_fork_arti", + "derive_more", + "digest 0.10.7", + "thiserror", + "tor-bytes", + "tor-checkable", + "tor-llcrypto", +] + +[[package]] +name = "tor-chanmgr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464dbcf8ea3c2333ecdc4f6526dc0015a16052af5b256bc9449c384bb61fe962" +dependencies = [ + "async-trait", + "derive_builder_fork_arti", + "derive_more", + "educe", + "futures 0.3.29", + "postage", + "rand 0.8.5", + "safelog", + "serde", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-cell", + "tor-config", + "tor-error", + "tor-linkspec", + "tor-llcrypto", + "tor-netdir", + "tor-proto", + "tor-rtcompat", + "tor-socksproto", + "tor-units", + "tracing", + "void", +] + +[[package]] +name = "tor-checkable" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb8047d82b3754e8662d29c02680db453059b68956f1b0d44f965f0536f239d" +dependencies = [ + "humantime 2.1.0", + "signature 2.2.0", + "thiserror", + "tor-llcrypto", +] + +[[package]] +name = "tor-circmgr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "607a1d725f67db7722854b685bbbb440002b339cf610a0647a90b6540b4f25ec" +dependencies = [ + "amplify", + "async-trait", + "bounded-vec-deque", + "cfg-if 1.0.0", + "derive_builder_fork_arti", + "derive_more", + "downcast-rs", + "dyn-clone", + "educe", + "futures 0.3.29", + "humantime-serde", + "itertools 0.12.0", + "once_cell", + "pin-project", + "rand 0.8.5", + "retry-error", + "safelog", + "serde", + "static_assertions", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-chanmgr", + "tor-config", + "tor-error", + "tor-guardmgr", + "tor-linkspec", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-protover", + "tor-relay-selection", + "tor-rtcompat", + "tracing", + "void", + "weak-table", +] + +[[package]] +name = "tor-config" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eacc03d70e00cedf31de3f393255d1ee4ec1f1d393ec79223c4a4e69fffd80dd" +dependencies = [ + "derive-deftly", + "derive_builder_fork_arti", + "directories", + "educe", + "either", + "figment", + "fs-mistrust", + "itertools 0.12.0", + "once_cell", + "paste", + "regex", + "serde", + "serde-value 0.7.0", + "serde_ignored", + "shellexpand", + "strum 0.26.2", + "thiserror", + "toml 0.8.8", + "tor-basic-utils", + "tor-error", + "tracing", + "void", +] + +[[package]] +name = "tor-consdiff" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60ccfee1404d281437a659932592f3c7592305668d93addf01384adb16531e5" +dependencies = [ + "digest 0.10.7", + "hex", + "thiserror", + "tor-llcrypto", +] + +[[package]] +name = "tor-dirclient" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f604e7450609aaae0d892572bee4d894ba00cd8061cafcbd8c8fa7c1561c2e0" +dependencies = [ + "async-compression", + "base64ct", + "derive_more", + "futures 0.3.29", + "hex", + "http 1.1.0", + "httparse", + "httpdate 1.0.3", + "itertools 0.12.0", + "memchr", + "thiserror", + "tor-circmgr", + "tor-error", + "tor-hscrypto", + "tor-linkspec", + "tor-llcrypto", + "tor-netdoc", + "tor-proto", + "tor-rtcompat", + "tracing", +] + +[[package]] +name = "tor-dirmgr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c676354fa69cb358b460ef698d354fb224da626b7d8dbe70a30230f30a7367" +dependencies = [ + "async-trait", + "base64ct", + "derive_builder_fork_arti", + "derive_more", + "digest 0.10.7", + "educe", + "event-listener 5.3.0", + "fs-mistrust", + "fslock", + "futures 0.3.29", + "hex", + "humantime 2.1.0", + "humantime-serde", + "itertools 0.12.0", + "memmap2", + "once_cell", + "paste", + "postage", + "rand 0.8.5", + "rusqlite", + "safelog", + "scopeguard", + "serde", + "signature 2.2.0", + "strum 0.26.2", + "thiserror", + "time", + "tor-async-utils", + "tor-basic-utils", + "tor-checkable", + "tor-circmgr", + "tor-config", + "tor-consdiff", + "tor-dirclient", + "tor-error", + "tor-guardmgr", + "tor-llcrypto", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-rtcompat", + "tracing", +] + +[[package]] +name = "tor-error" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321b27a08c18364e6e30374bfb13817c8acec8a274d461db166ebe1280969eef" +dependencies = [ + "backtrace", + "derive_more", + "futures 0.3.29", + "once_cell", + "paste", + "retry-error", + "static_assertions", + "strum 0.26.2", + "thiserror", + "tracing", +] + +[[package]] +name = "tor-guardmgr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbbb44d3f571397a849faaf7bbb25a30f098095b94eb4234b970d8024514879" +dependencies = [ + "amplify", + "base64ct", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more", + "dyn-clone", + "educe", + "futures 0.3.29", + "humantime 2.1.0", + "humantime-serde", + "itertools 0.12.0", + "num_enum", + "pin-project", + "postage", + "rand 0.8.5", + "safelog", + "serde", + "strum 0.26.2", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-config", + "tor-error", + "tor-linkspec", + "tor-llcrypto", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-relay-selection", + "tor-rtcompat", + "tor-units", + "tracing", +] + +[[package]] +name = "tor-hsclient" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210dc08c53929e0c800198779a9595ff0cad1051c52320533a8421b4eb0f2deb" +dependencies = [ + "async-trait", + "derive-deftly", + "derive_more", + "educe", + "either", + "futures 0.3.29", + "itertools 0.12.0", + "postage", + "rand 0.8.5", + "retry-error", + "safelog", + "slotmap", + "strum 0.26.2", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-checkable", + "tor-circmgr", + "tor-config", + "tor-dirclient", + "tor-error", + "tor-hscrypto", + "tor-keymgr", + "tor-linkspec", + "tor-llcrypto", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-rtcompat", + "tracing", +] + +[[package]] +name = "tor-hscrypto" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c76aa63e02c854b1a845b2a35ed811a52848f37cff413d2b8357e3d47aaefbb" +dependencies = [ + "cipher 0.4.4", + "data-encoding", + "derive_more", + "digest 0.10.7", + "itertools 0.12.0", + "paste", + "rand 0.8.5", + "safelog", + "signature 2.2.0", + "subtle", + "thiserror", + "tor-basic-utils", + "tor-bytes", + "tor-error", + "tor-llcrypto", + "tor-units", + "zeroize", +] + +[[package]] +name = "tor-hsrproxy" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ce1ae094d32314bf4fa1142bc5ffaaf041927df0a2a5654f9860c6b79578fe" +dependencies = [ + "derive-deftly", + "derive_builder_fork_arti", + "futures 0.3.29", + "rangemap", + "safelog", + "serde", + "serde_with", + "thiserror", + "tor-async-utils", + "tor-cell", + "tor-config", + "tor-error", + "tor-hsservice", + "tor-log-ratelim", + "tor-proto", + "tor-rtcompat", + "tracing", + "void", +] + +[[package]] +name = "tor-hsservice" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d73024a7936cc0439f1b10db876070476ff8bbec0dccb31e5773e654d20dd87" +dependencies = [ + "async-trait", + "base64ct", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more", + "digest 0.10.7", + "educe", + "fs-mistrust", + "futures 0.3.29", + "growable-bloom-filter", + "hex", + "humantime 2.1.0", + "itertools 0.12.0", + "k12", + "once_cell", + "postage", + "rand 0.8.5", + "rand_core 0.6.4", + "retry-error", + "safelog", + "serde", + "serde_with", + "strum 0.26.2", + "thiserror", + "tor-async-utils", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-circmgr", + "tor-config", + "tor-dirclient", + "tor-error", + "tor-hscrypto", + "tor-keymgr", + "tor-linkspec", + "tor-llcrypto", + "tor-log-ratelim", + "tor-netdir", + "tor-netdoc", + "tor-persist", + "tor-proto", + "tor-protover", + "tor-relay-selection", + "tor-rtcompat", + "tracing", + "void", +] + +[[package]] +name = "tor-keymgr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c6dbc1247aaf53417ffd38958fa262fb6fb3b891987babfa0d0e51028bc9ad" +dependencies = [ + "amplify", + "arrayvec 0.7.4", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more", + "downcast-rs", + "dyn-clone", + "fs-mistrust", + "glob-match", + "humantime 2.1.0", + "inventory", + "itertools 0.12.0", + "rand 0.8.5", + "serde", + "ssh-key", + "thiserror", + "tor-basic-utils", + "tor-config", + "tor-error", + "tor-hscrypto", + "tor-llcrypto", + "tor-persist", + "walkdir", + "zeroize", +] + +[[package]] +name = "tor-linkspec" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3017bfdc155832fbaf21b99d24d2ab251b1463c5a1ed4432dc02c6d7c145cac9" +dependencies = [ + "base64ct", + "by_address", + "caret", + "derive-deftly", + "derive_builder_fork_arti", + "derive_more", + "hex", + "itertools 0.12.0", + "safelog", + "serde", + "serde_with", + "strum 0.26.2", + "thiserror", + "tor-basic-utils", + "tor-bytes", + "tor-config", + "tor-llcrypto", + "tor-protover", +] + +[[package]] +name = "tor-llcrypto" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47163b1ad910d8365693efbe508f1fbb7215fb91b4ee579fd2e64c2adcbf853" +dependencies = [ + "aes", + "base64ct", + "ctr", + "curve25519-dalek 4.1.2", + "derive_more", + "digest 0.10.7", + "ed25519-dalek 2.1.1", + "educe", + "getrandom 0.2.11", + "hex", + "rand_core 0.6.4", + "rsa", + "safelog", + "serde", + "sha1", + "sha2 0.10.8", + "sha3 0.10.8", + "signature 2.2.0", + "simple_asn1", + "subtle", + "thiserror", + "x25519-dalek 2.0.1", + "zeroize", +] + +[[package]] +name = "tor-log-ratelim" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8e31f18898b65ebe928a4959d41b8e81b6322213070fbeb60f116eaa2d472b" +dependencies = [ + "futures 0.3.29", + "humantime 2.1.0", + "once_cell", + "thiserror", + "tor-error", + "tor-rtcompat", + "tracing", + "weak-table", +] + +[[package]] +name = "tor-netdir" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67662012b77d73ccb08380975d676914879438dcc3a56bcebb49ffed92f72b3e" +dependencies = [ + "bitflags 2.4.1", + "derive_more", + "digest 0.10.7", + "futures 0.3.29", + "hex", + "humantime 2.1.0", + "itertools 0.12.0", + "num_enum", + "rand 0.8.5", + "serde", + "static_assertions", + "strum 0.26.2", + "thiserror", + "time", + "tor-basic-utils", + "tor-error", + "tor-hscrypto", + "tor-linkspec", + "tor-llcrypto", + "tor-netdoc", + "tor-protover", + "tor-units", + "tracing", + "typed-index-collections", +] + +[[package]] +name = "tor-netdoc" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9cc90b2d501aeb6b82106615545a15baea23337215f2daebab4faf140b2c6c" +dependencies = [ + "amplify", + "base64ct", + "bitflags 2.4.1", + "cipher 0.4.4", + "derive_builder_fork_arti", + "derive_more", + "digest 0.10.7", + "educe", + "hex", + "humantime 2.1.0", + "itertools 0.12.0", + "once_cell", + "phf", + "rand 0.8.5", + "serde", + "serde_with", + "signature 2.2.0", + "smallvec", + "subtle", + "thiserror", + "time", + "tinystr", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-cert", + "tor-checkable", + "tor-error", + "tor-hscrypto", + "tor-linkspec", + "tor-llcrypto", + "tor-protover", + "tor-units", + "weak-table", + "zeroize", +] + +[[package]] +name = "tor-persist" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d57c0676b6eecad9242b42c72b0e501ea78a900aee2663fb0e237cdfa2f0bd31" +dependencies = [ + "amplify", + "derive-deftly", + "derive_more", + "filetime", + "fs-mistrust", + "fslock", + "fslock-guard", + "itertools 0.12.0", + "paste", + "sanitize-filename", + "serde", + "serde_json", + "thiserror", + "tor-basic-utils", + "tor-error", + "tracing", +] + +[[package]] +name = "tor-proto" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a090687ac4b1145bae9b8f4d45d9a45fbac8e508e1e0358951e2608ff451d02" +dependencies = [ + "asynchronous-codec", + "bitvec", + "bytes 1.5.0", + "cipher 0.4.4", + "coarsetime", + "derive_builder_fork_arti", + "derive_more", + "digest 0.10.7", + "educe", + "futures 0.3.29", + "hkdf 0.12.4", + "hmac 0.12.1", + "pin-project", + "rand 0.8.5", + "rand_core 0.6.4", + "safelog", + "subtle", + "thiserror", + "tokio 1.37.0", + "tokio-util 0.7.10", + "tor-async-utils", + "tor-basic-utils", + "tor-bytes", + "tor-cell", + "tor-cert", + "tor-checkable", + "tor-config", + "tor-error", + "tor-hscrypto", + "tor-linkspec", + "tor-llcrypto", + "tor-log-ratelim", + "tor-rtcompat", + "tor-rtmock", + "tor-units", + "tracing", + "typenum", + "visibility", + "void", + "zeroize", +] + +[[package]] +name = "tor-protover" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5af1a305ca533613b676f13d5a276d648cb1f974361c830a3113703aad3b34" +dependencies = [ + "caret", + "thiserror", +] + +[[package]] +name = "tor-relay-selection" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003bc22bbfc01fefc9c6fdb9d72ee1b8d979b2fae3d6885522f4ba9da327ef47" +dependencies = [ + "rand 0.8.5", + "serde", + "tor-basic-utils", + "tor-linkspec", + "tor-netdir", + "tor-netdoc", +] + +[[package]] +name = "tor-rtcompat" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d97b2264cfea9e8ed9b7aa50d220d1003a5775f5065ec3ef576eb9e61a1885" +dependencies = [ + "async-io 2.2.2", + "async-native-tls", + "async-std", + "async-trait", + "async_executors", + "coarsetime", + "derive_more", + "educe", + "futures 0.3.29", + "futures-rustls", + "native-tls", + "paste", + "pin-project", + "rustls-pki-types", + "thiserror", + "tokio 1.37.0", + "tokio-util 0.7.10", + "tracing", + "x509-signature", +] + +[[package]] +name = "tor-rtmock" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c547161e0854858ca7ad1fa31c4da8d97bfd983c2acaaf91488551d7f2ce5e88" +dependencies = [ + "amplify", + "async-trait", + "backtrace", + "derive-deftly", + "derive_more", + "educe", + "futures 0.3.29", + "humantime 2.1.0", + "itertools 0.12.0", + "pin-project", + "priority-queue", + "slotmap", + "strum 0.26.2", + "thiserror", + "tor-async-utils", + "tor-error", + "tor-rtcompat", + "tracing", + "tracing-test", + "void", +] + +[[package]] +name = "tor-socksproto" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc64bbb385974631c800d1951bb48f08775c407281d4ce9a36aaa1c6512ced33" +dependencies = [ + "caret", + "subtle", + "thiserror", + "tor-bytes", + "tor-error", +] + +[[package]] +name = "tor-units" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0710451c303d01d6503157a90f831ed4f62574ec265116e1aebb4b67f0657972" +dependencies = [ + "derive_more", + "thiserror", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite 0.2.13", + "tokio 1.37.0", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4390,9 +7550,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite 0.2.13", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -4400,6 +7572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] @@ -4412,6 +7585,58 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-test" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a2c0ff408fe918a94c428a3f2ad04e4afd5c95bbc08fcf868eff750c15728a4" +dependencies = [ + "lazy_static", + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bc1c4f8e2e73a977812ab339d503e6feeb92700f6d07a6de4d321522d5c08" +dependencies = [ + "lazy_static", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "traitobject" version = "0.1.0" @@ -4433,6 +7658,12 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "typed-index-collections" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183496e014253d15abbe6235677b1392dba2d40524c88938991226baa38ac7c4" + [[package]] name = "typemap" version = "0.3.3" @@ -4448,6 +7679,15 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + [[package]] name = "unic-langid" version = "0.9.1" @@ -4517,9 +7757,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "universal-hash" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ "generic-array 0.14.7", "subtle", @@ -4534,6 +7774,12 @@ dependencies = [ "traitobject", ] +[[package]] +name = "untrusted" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" + [[package]] name = "untrusted" version = "0.7.1" @@ -4541,10 +7787,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] -name = "url" -version = "2.4.1" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -4557,10 +7809,22 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4579,6 +7843,29 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "visibility" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3fd98999db9227cf28e59d83e1f120f42bc233d4b152e8fab9bc87d5bb1e0f8" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + [[package]] name = "walkdir" version = "2.4.0" @@ -4611,10 +7898,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.87" +name = "wasix" +version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4624,24 +7920,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4651,9 +7947,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote 1.0.33", "wasm-bindgen-macro-support", @@ -4661,28 +7957,34 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + +[[package]] +name = "weak-table" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4694,8 +7996,18 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -4704,7 +8016,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" dependencies = [ - "webpki", + "webpki 0.21.4", ] [[package]] @@ -4756,7 +8068,16 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -4765,7 +8086,31 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -4774,51 +8119,144 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4826,10 +8264,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "winnow" -version = "0.5.17" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -4853,6 +8297,15 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x25519-dalek" version = "0.6.0" @@ -4875,6 +8328,43 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek 4.1.2", + "rand_core 0.6.4", + "serde", + "zeroize", +] + +[[package]] +name = "x509-signature" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb2bc2a902d992cd5f471ee3ab0ffd6603047a4207384562755b9d6de977518" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + [[package]] name = "yaml-rust" version = "0.3.5" @@ -4891,10 +8381,30 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.6.0" +name = "zerocopy" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2 1.0.70", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -4905,9 +8415,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.69", + "proc-macro2 1.0.70", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4920,3 +8430,31 @@ dependencies = [ "crc32fast", "thiserror", ] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 3e8a20a..1aee15a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,46 +9,67 @@ edition = "2021" members = ["onion"] [dependencies] -blake2 = { package = "blake2-rfc", version = "0.2"} +arti-client = { version = "0.18.0", default-features = false, features = ["async-std", "rustls", "onion-service-client", "onion-service-service"] } +arti-hyper = "0.18.0" +async-std = { version = "1", features = ["tokio1"] } +async-trait = "0.1.74" +blake2 = { package = "blake2-rfc", version = "0.2" } byteorder = "1" -bytes = "0.5.6" -chacha20 = "0.8.1" +bytes = "1.5.0" +chacha20 = "0.9.1" +chrono = "0.4.31" clap = { version = "2.33", features = ["yaml"] } -curve25519-dalek = "2.1" +ctrlc = { version = "3.1", features = ["termination"] } +curve25519-dalek = "4.1.2" dirs = "2.0" -ed25519-dalek = "1.0.1" +ed25519-dalek = "2.1.1" function_name = "0.3.0" futures = "0.3" -hmac = { version = "0.12.0", features = ["std"]} -hyper = { version = "0.14", features = ["full"] } -hyper-proxy = "0.9.1" -itertools = { version = "0.10.3"} -jsonrpc-core = "18.0" -jsonrpc-derive = "18.0" -jsonrpc-http-server = "18.0" +fs-mistrust = "0.7.9" +hmac = { version = "0.12.0", features = ["std"] } +hyper = "0.14.28" +hyper-tls = "0.6.0" +itertools = { version = "0.12.0" } +jsonrpc-core = "18.0.0" +jsonrpc-derive = "18.0.0" +jsonrpc-http-server = "18.0.0" lazy_static = "1" pbkdf2 = "0.8.0" rand = "0.7.3" +remove_dir_all = "0.8.2" ring = "0.16" rpassword = "4.0" -serde = { version = "1", features= ["derive"]} +rusqlite = { version = "0.31.0", features = ["bundled"] } +serde = { version = "1", features = ["derive"] } serde_derive = "1" serde_json = "1" sha2 = "0.10.0" -thiserror = "1.0.31" -tokio = { version = "1", features = ["full"] } -toml = "0.5" +thiserror = "1.0.30" +tls-api = "0.9.0" +tls-api-native-tls = "0.9.0" +tokio = { version = "1.37.0", features = ["full"] } +toml = "0.8.8" +tor-hscrypto = "0.18.0" +tor-hsrproxy = "0.18.0" +tor-hsservice = "0.18.0" +tor-llcrypto = "0.18.0" +tor-keymgr = "0.18.0" +tor-rtcompat = "0.18.0" x25519-dalek = "0.6.0" grin_onion = { path = "./onion" } -grin_secp256k1zkp = { version = "0.7.12", features = ["bullet-proof-sizing"]} -grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_servers = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_wallet_api = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_impls = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_libwallet = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_util = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } \ No newline at end of file +grin_secp256k1zkp = { version = "0.7.14", features = ["bullet-proof-sizing"] } +grin_api = "5.3.1" +grin_core = "5.3.1" +grin_chain = "5.3.1" +grin_keychain = "5.3.1" +grin_p2p = "5.3.1" +grin_servers = "5.3.1" +grin_store = "5.3.1" +grin_util = "5.3.1" +grin_wallet_api = "5.3.1" +grin_wallet_config = "5.3.1" +grin_wallet_controller = "5.3.1" +grin_wallet_impls = "5.3.1" +grin_wallet_libwallet = "5.3.1" +grin_wallet_util = "5.3.1" +log = "0.4.20" \ No newline at end of file diff --git a/doc/swap_api.md b/doc/swap_api.md index a779d63..fa84f86 100644 --- a/doc/swap_api.md +++ b/doc/swap_api.md @@ -47,6 +47,7 @@ In case of errors, the API will return a `SwapError` type with one of the follow - `FeeTooLow`: The provided fee is too low. - `StoreError`: An error occurred when saving swap to the data store. - `ClientError`: An error occurred during client communication. +- `SwapTxNotFound`: The previous swap transaction was not found in data store. - `UnknownError`: An unknown error occurred. ### Example diff --git a/onion/Cargo.toml b/onion/Cargo.toml index c0e36f9..a7eab60 100644 --- a/onion/Cargo.toml +++ b/onion/Cargo.toml @@ -6,33 +6,33 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -blake2 = { package = "blake2-rfc", version = "0.2"} +blake2 = { package = "blake2-rfc", version = "0.2" } byteorder = "1" bytes = "0.5.6" chacha20 = "0.8.1" curve25519-dalek = "2.1" ed25519-dalek = "1.0.1" -hmac = { version = "0.12.0", features = ["std"]} -itertools = { version = "0.10.3"} +hmac = { version = "0.12.0", features = ["std"] } +itertools = { version = "0.10.3" } lazy_static = "1" rand = "0.7.3" rpassword = "4.0" -serde = { version = "1", features= ["derive"]} +serde = { version = "1", features = ["derive"] } serde_derive = "1" serde_json = "1" sha2 = "0.10.0" -thiserror = "1.0.31" +thiserror = "1" toml = "0.5" x25519-dalek = "0.6.0" -grin_secp256k1zkp = { version = "0.7.11", features = ["bullet-proof-sizing"]} -grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_servers = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } -grin_wallet_api = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_impls = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_libwallet = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } -grin_wallet_util = { git = "https://github.com/mimblewimble/grin-wallet", tag = "v5.2.0-beta.1" } \ No newline at end of file +grin_secp256k1zkp = { version = "0.7.14", features = ["bullet-proof-sizing"] } +grin_api = "5.3.1" +grin_core = "5.3.1" +grin_chain = "5.3.1" +grin_keychain = "5.3.1" +grin_servers = "5.3.1" +grin_store = "5.3.1" +grin_util = "5.3.1" +grin_wallet_api = "5.3.1" +grin_wallet_impls = "5.3.1" +grin_wallet_libwallet = "5.3.1" +grin_wallet_util = "5.3.1" \ No newline at end of file diff --git a/onion/src/crypto/dalek.rs b/onion/src/crypto/dalek.rs index 70c7654..ab107bc 100644 --- a/onion/src/crypto/dalek.rs +++ b/onion/src/crypto/dalek.rs @@ -162,7 +162,7 @@ pub fn sign(sk: &SecretKey, message: &[u8]) -> Result) -> Result) -> Result Onion { let commit = rand_commit(); @@ -116,20 +117,20 @@ pub mod test_util { } pub fn rand_commit() -> Commitment { - secp::commit(rand::thread_rng().next_u64(), &secp::random_secret()).unwrap() + secp::commit(thread_rng().next_u64(), &random_secret()).unwrap() } pub fn rand_hash() -> Hash { - Hash::from_hex(secp::random_secret().to_hex().as_str()).unwrap() + Hash::from_hex(random_secret().to_hex().as_str()).unwrap() } pub fn rand_proof() -> RangeProof { let secp = Secp256k1::new(); secp.bullet_proof( - rand::thread_rng().next_u64(), - secp::random_secret(), - secp::random_secret(), - secp::random_secret(), + thread_rng().next_u64(), + random_secret(), + random_secret(), + random_secret(), None, None, ) @@ -153,8 +154,8 @@ pub mod test_util { let rp = secp.bullet_proof( out_value, blind.clone(), - secp::random_secret(), - secp::random_secret(), + random_secret(), + random_secret(), None, None, ); diff --git a/onion/src/onion.rs b/onion/src/onion.rs index 974b743..2533aaf 100644 --- a/onion/src/onion.rs +++ b/onion/src/onion.rs @@ -1,22 +1,23 @@ -use crate::crypto::secp::{self, Commitment, RangeProof, SecretKey}; -use crate::util::{read_optional, vec_to_array, write_optional}; - -use chacha20::cipher::{NewCipher, StreamCipher}; -use chacha20::{ChaCha20, Key, Nonce}; -use grin_core::core::FeeFields; -use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; -use grin_util::{self, ToHex}; -use hmac::digest::InvalidLength; -use hmac::{Hmac, Mac}; -use serde::ser::SerializeStruct; -use serde::Deserialize; -use sha2::Sha256; use std::fmt; use std::hash::{Hash, Hasher}; use std::result::Result; + +use chacha20::{ChaCha20, Key, Nonce}; +use chacha20::cipher::{NewCipher, StreamCipher}; +use grin_core::core::FeeFields; +use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; +use grin_util::{self, ToHex}; +use hmac::{Hmac, Mac}; +use hmac::digest::InvalidLength; +use serde::Deserialize; +use serde::ser::SerializeStruct; +use sha2::Sha256; use thiserror::Error; use x25519_dalek::{PublicKey as xPublicKey, SharedSecret, StaticSecret}; +use crate::crypto::secp::{self, Commitment, RangeProof, SecretKey}; +use crate::util::{read_optional, vec_to_array, write_optional}; + type HmacSha256 = Hmac; pub type RawBytes = Vec; @@ -328,12 +329,13 @@ impl From for OnionError { #[cfg(test)] pub mod tests { - use super::*; - use crate::crypto::secp::random_secret; - use crate::{new_hop, Hop}; - use grin_core::core::FeeFields; + use crate::{create_onion, Hop, new_hop}; + use crate::crypto::secp::random_secret; + + use super::*; + /// Test end-to-end Onion creation and unwrapping logic. #[test] fn onion() { @@ -376,12 +378,12 @@ pub mod tests { hops.push(hop); } - let mut onion_packet = test_util::create_onion(&commitment, &hops).unwrap(); + let mut onion_packet = create_onion(&commitment, &hops).unwrap(); let mut payload = Payload { next_ephemeral_pk: onion_packet.ephemeral_pubkey.clone(), excess: random_secret(), - fee: FeeFields::from(fee_per_hop as u32), + fee: FeeFields::from(fee_per_hop), rangeproof: None, }; for i in 0..5 { @@ -393,6 +395,6 @@ pub mod tests { assert!(payload.rangeproof.is_some()); assert_eq!(payload.rangeproof.unwrap(), hops[4].rangeproof.unwrap()); assert_eq!(secp::commit(out_value, &final_blind).unwrap(), final_commit); - assert_eq!(payload.fee, FeeFields::from(fee_per_hop as u32)); + assert_eq!(payload.fee, FeeFields::from(fee_per_hop)); } } diff --git a/onion/src/util.rs b/onion/src/util.rs index 99ae709..2b2f134 100644 --- a/onion/src/util.rs +++ b/onion/src/util.rs @@ -19,10 +19,10 @@ use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; /// # Example /// /// ``` -/// let mut writer = vec![]; +/// let mut buf = vec![]; /// let optional_value: Option = Some(10); -/// write_optional(&mut writer, &optional_value); -/// assert_eq!(buf, &[1, 0, 0, 0, 10]); +/// grin_onion::util::write_optional(&mut grin_core::ser::BinWriter::default(&mut buf), &optional_value).unwrap(); +/// assert_eq!(&buf, &[1, 0, 0, 0, 10]); /// ``` pub fn write_optional( writer: &mut W, @@ -58,8 +58,8 @@ pub fn write_optional( /// /// ``` /// let mut buf: &[u8] = &[1, 0, 0, 0, 10]; -/// let mut reader = BinReader::new(&mut buf, ProtocolVersion::local(), DeserializationMode::default()); -/// let optional_value: Option = read_optional(&mut reader).unwrap(); +/// let mut reader = grin_core::ser::BinReader::new(&mut buf, grin_core::ser::ProtocolVersion::local(), grin_core::ser::DeserializationMode::default()); +/// let optional_value: Option = grin_onion::util::read_optional(&mut reader).unwrap(); /// assert_eq!(optional_value, Some(10)); /// ``` pub fn read_optional(reader: &mut R) -> Result, ser::Error> { @@ -87,7 +87,7 @@ pub fn read_optional(reader: &mut R) -> Result /// /// ``` /// let v = vec![0, 1, 2, 3, 4, 5]; -/// let a = vec_to_array::<4>(&v).unwrap(); +/// let a = grin_onion::util::vec_to_array::<4>(&v).unwrap(); /// assert_eq!(a, [0, 1, 2, 3]); /// ``` pub fn vec_to_array(vec: &Vec) -> Result<[u8; S], ser::Error> { diff --git a/src/main.rs b/src/bin/mwixnet.rs similarity index 68% rename from src/main.rs rename to src/bin/mwixnet.rs index fdf84bb..66092d6 100644 --- a/src/main.rs +++ b/src/bin/mwixnet.rs @@ -1,33 +1,30 @@ -use config::ServerConfig; -use node::HttpGrinNode; -use store::SwapStore; -use wallet::HttpWallet; - -use crate::client::{MixClient, MixClientImpl}; -use crate::node::GrinNode; -use crate::store::StoreError; -use clap::App; -use grin_core::global; -use grin_core::global::ChainTypes; -use grin_onion::crypto; -use grin_onion::crypto::dalek::DalekPublicKey; -use grin_util::{StopState, ZeroingString}; -use rpassword; -use std::path::PathBuf; -use std::sync::Arc; -use tokio::runtime::Runtime; - #[macro_use] extern crate clap; -mod client; -mod config; -mod node; -mod servers; -mod store; -mod tor; -mod tx; -mod wallet; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use std::thread::{sleep, spawn}; +use std::time::Duration; + +use clap::App; +use grin_core::global; +use grin_core::global::ChainTypes; +use grin_util::{StopState, ZeroingString}; +use rand::{Rng, thread_rng}; +use rpassword; +use tor_rtcompat::PreferredRuntime; + +use grin_onion::crypto; +use grin_onion::crypto::dalek::DalekPublicKey; +use mwixnet::config::{self, ServerConfig}; +use mwixnet::mix_client::{MixClient, MixClientImpl}; +use mwixnet::node::GrinNode; +use mwixnet::node::HttpGrinNode; +use mwixnet::servers; +use mwixnet::store::StoreError; +use mwixnet::store::SwapStore; +use mwixnet::tor; +use mwixnet::wallet::HttpWallet; const DEFAULT_INTERVAL: u32 = 12 * 60 * 60; @@ -37,7 +34,7 @@ fn main() -> Result<(), Box> { } fn real_main() -> Result<(), Box> { - let yml = load_yaml!("../mwixnet.yml"); + let yml = load_yaml!("mwixnet.yml"); let args = App::from_yaml(yml).get_matches(); let chain_type = if args.is_present("testnet") { ChainTypes::Testnet @@ -59,7 +56,6 @@ fn real_main() -> Result<(), Box> { .value_of("round_time") .map(|t| t.parse::().unwrap()); let bind_addr = args.value_of("bind_addr"); - let socks_addr = args.value_of("socks_addr"); let grin_node_url = args.value_of("grin_node_url"); let grin_node_secret_path = args.value_of("grin_node_secret_path"); let wallet_owner_url = args.value_of("wallet_owner_url"); @@ -84,7 +80,6 @@ fn real_main() -> Result<(), Box> { key: crypto::secp::random_secret(), interval_s: round_time.unwrap_or(DEFAULT_INTERVAL), addr: bind_addr.unwrap_or("127.0.0.1:3000").parse()?, - socks_proxy_addr: socks_addr.unwrap_or("127.0.0.1:3001").parse()?, grin_node_url: match grin_node_url { Some(u) => u.parse()?, None => config::grin_node_url(&chain_type), @@ -146,11 +141,6 @@ fn real_main() -> Result<(), Box> { server_config.addr = bind_addr.parse()?; } - // Override socks_addr, if supplied - if let Some(socks_addr) = socks_addr { - server_config.socks_proxy_addr = socks_addr.parse()?; - } - // Override prev_server, if supplied if let Some(prev_server) = prev_server { server_config.prev_server = Some(prev_server); @@ -168,18 +158,21 @@ fn real_main() -> Result<(), Box> { ); // Node API health check - if let Err(e) = node.get_chain_height() { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; + if let Err(e) = rt.block_on(node.async_get_chain_tip()) { eprintln!("Node communication failure. Is node listening?"); return Err(e.into()); }; // Open wallet let wallet_pass = prompt_wallet_password(&args.value_of("wallet_pass")); - let wallet = HttpWallet::open_wallet( + let wallet = rt.block_on(HttpWallet::async_open_wallet( &server_config.wallet_owner_url, &server_config.wallet_owner_api_secret(), &wallet_pass, - ); + )); let wallet = match wallet { Ok(w) => w, Err(e) => { @@ -188,21 +181,29 @@ fn real_main() -> Result<(), Box> { } }; - let mut tor_process = tor::init_tor_listener(&server_config)?; + let tor_instance = rt.block_on(tor::async_init_tor( + PreferredRuntime::current().unwrap(), + &config::get_grin_path(&chain_type).to_str().unwrap(), + &server_config, + ))?; + let tor_instance = Arc::new(grin_util::Mutex::new(tor_instance)); + let tor_clone = tor_instance.clone(); let stop_state = Arc::new(StopState::new()); let stop_state_clone = stop_state.clone(); - let rt = Runtime::new()?; rt.spawn(async move { futures::executor::block_on(build_signals_fut()); - let _ = tor_process.kill(); + tor_clone.lock().stop(); stop_state_clone.stop(); }); let next_mixer: Option> = server_config.next_server.clone().map(|pk| { - let client: Arc = - Arc::new(MixClientImpl::new(server_config.clone(), pk.clone())); + let client: Arc = Arc::new(MixClientImpl::new( + server_config.clone(), + tor_instance.clone(), + pk.clone(), + )); client }); @@ -213,13 +214,26 @@ fn real_main() -> Result<(), Box> { server_config.server_pubkey().to_hex() ); - servers::mix_rpc::listen( + let (_, http_server) = servers::mix_rpc::listen( + rt.handle(), server_config, next_mixer, Arc::new(wallet), Arc::new(node), - stop_state, - ) + )?; + + let close_handle = http_server.close_handle(); + let round_handle = spawn(move || loop { + if stop_state.is_stopped() { + close_handle.close(); + break; + } + + sleep(Duration::from_millis(100)); + }); + + http_server.wait(); + round_handle.join().unwrap(); } else { println!( "Starting SWAP server with public key {:?}", @@ -237,15 +251,75 @@ fn real_main() -> Result<(), Box> { )?; // Start the mwixnet JSON-RPC HTTP 'swap' server - servers::swap_rpc::listen( - server_config, + let (swap_server, http_server) = servers::swap_rpc::listen( + rt.handle(), + &server_config, next_mixer, Arc::new(wallet), Arc::new(node), store, - stop_state, - ) + )?; + + let close_handle = http_server.close_handle(); + let round_handle = spawn(move || { + let mut rng = thread_rng(); + let mut secs = 0u32; + let mut reorg_secs = 0u32; + let mut reorg_window = rng.gen_range(900u32, 3600u32); + let prev_tx = Arc::new(Mutex::new(None)); + let server = swap_server.clone(); + + loop { + if stop_state.is_stopped() { + close_handle.close(); + break; + } + + sleep(Duration::from_secs(1)); + secs = (secs + 1) % server_config.interval_s; + reorg_secs = (reorg_secs + 1) % reorg_window; + + if secs == 0 { + let prev_tx_clone = prev_tx.clone(); + let server_clone = server.clone(); + rt.spawn(async move { + let result = server_clone.lock().await.execute_round().await; + let mut prev_tx_lock = prev_tx_clone.lock().unwrap(); + *prev_tx_lock = match result { + Ok(Some(tx)) => Some(tx), + _ => None, + }; + }); + reorg_secs = 0; + reorg_window = rng.gen_range(900u32, 3600u32); + } else if reorg_secs == 0 { + let prev_tx_clone = prev_tx.clone(); + let server_clone = server.clone(); + rt.spawn(async move { + let tx_option = { + let prev_tx_lock = prev_tx_clone.lock().unwrap(); + prev_tx_lock.clone() + }; // Lock is dropped here + + if let Some(tx) = tx_option { + let result = server_clone.lock().await.check_reorg(&tx).await; + let mut prev_tx_lock = prev_tx_clone.lock().unwrap(); + *prev_tx_lock = match result { + Ok(Some(tx)) => Some(tx), + _ => None, + }; + } + }); + reorg_window = rng.gen_range(900u32, 3600u32); + } + } + }); + + http_server.wait(); + round_handle.join().unwrap(); } + + Ok(()) } #[cfg(unix)] diff --git a/mwixnet.yml b/src/bin/mwixnet.yml similarity index 91% rename from mwixnet.yml rename to src/bin/mwixnet.yml index b3b3091..10326af 100644 --- a/mwixnet.yml +++ b/src/bin/mwixnet.yml @@ -38,10 +38,6 @@ args: help: Address to bind the rpc server to (e.g. 127.0.0.1:3000) long: bind_addr takes_value: true - - socks_addr: - help: Address to bind the SOCKS5 tor proxy to (e.g. 127.0.0.1:3001) - long: socks_addr - takes_value: true - prev_server: help: Hex public key of the previous swap/mix server long: prev_server diff --git a/src/client.rs b/src/client.rs deleted file mode 100644 index 987e343..0000000 --- a/src/client.rs +++ /dev/null @@ -1,172 +0,0 @@ -use crate::config::ServerConfig; -use crate::crypto::dalek; -use crate::servers::mix_rpc::MixReq; -use crate::tx::TxComponents; -use crate::{tor, DalekPublicKey}; -use grin_onion::onion::Onion; - -use grin_api::client; -use grin_api::client::TimeOut; -use grin_api::json_rpc::build_request; -use grin_core::ser; -use grin_core::ser::ProtocolVersion; -use grin_wallet_util::OnionV3Address; -use hyper::client::HttpConnector; -use hyper_proxy::{Intercept, Proxy, ProxyConnector}; -use serde_json; -use thiserror::Error; - -/// Error types for interacting with nodes -#[derive(Error, Debug)] -pub enum ClientError { - #[error("Tor Error: {0:?}")] - Tor(tor::TorError), - #[error("API Error: {0:?}")] - API(grin_api::Error), - #[error("Dalek Error: {0:?}")] - Dalek(dalek::DalekError), - #[error("Error parsing response: {0:?}")] - ResponseParse(serde_json::Error), - #[error("Custom client error: {0:?}")] - Custom(String), -} - -/// A client for consuming a mix API -pub trait MixClient: Send + Sync { - /// Swaps the outputs provided and returns the final swapped outputs and kernels. - fn mix_outputs(&self, onions: &Vec) -> Result<(Vec, TxComponents), ClientError>; -} - -pub struct MixClientImpl { - config: ServerConfig, - addr: OnionV3Address, -} - -impl MixClientImpl { - pub fn new(config: ServerConfig, next_pubkey: DalekPublicKey) -> Self { - let addr = OnionV3Address::from_bytes(next_pubkey.as_ref().to_bytes()); - MixClientImpl { config, addr } - } - - fn send_json_request( - &self, - addr: &OnionV3Address, - method: &str, - params: &serde_json::Value, - ) -> Result { - let _tor = tor::init_tor_sender(&self.config).map_err(ClientError::Tor)?; - - let proxy = { - let proxy_uri = format!("http://{:?}", self.config.socks_proxy_addr) - .parse() - .unwrap(); - let proxy = Proxy::new(Intercept::All, proxy_uri); - //proxy.set_authorization(Authorization::basic("John Doe", "Agent1234")); - let connector = HttpConnector::new(); - let proxy_connector = ProxyConnector::from_proxy(connector, proxy).unwrap(); - proxy_connector - }; - - let url = format!("{}/v1", addr.to_http_str()); - let mut req = client::create_post_request(&url, None, &build_request(method, params)) - .map_err(ClientError::API)?; - - let uri = url.parse().unwrap(); - if let Some(headers) = proxy.http_headers(&uri) { - req.headers_mut().extend(headers.clone().into_iter()); - } - - let res = client::send_request(req, TimeOut::default()).map_err(ClientError::API)?; - - serde_json::from_str(&res).map_err(ClientError::ResponseParse) - } -} - -impl MixClient for MixClientImpl { - fn mix_outputs(&self, onions: &Vec) -> Result<(Vec, TxComponents), ClientError> { - let serialized = ser::ser_vec(&onions, ProtocolVersion::local()).unwrap(); - let sig = - dalek::sign(&self.config.key, serialized.as_slice()).map_err(ClientError::Dalek)?; - let mix = MixReq::new(onions.clone(), sig); - - let params = serde_json::json!(mix); - - self.send_json_request::<(Vec, TxComponents)>(&self.addr, "mix", ¶ms) - } -} - -#[cfg(test)] -pub mod mock { - use super::{ClientError, MixClient}; - use crate::tx::TxComponents; - use grin_onion::onion::Onion; - - use std::collections::HashMap; - - pub struct MockMixClient { - results: HashMap, (Vec, TxComponents)>, - } - - impl MockMixClient { - pub fn new() -> MockMixClient { - MockMixClient { - results: HashMap::new(), - } - } - - pub fn set_response(&mut self, onions: &Vec, r: (Vec, TxComponents)) { - self.results.insert(onions.clone(), r); - } - } - - impl MixClient for MockMixClient { - fn mix_outputs( - &self, - onions: &Vec, - ) -> Result<(Vec, TxComponents), ClientError> { - self.results - .get(onions) - .map(|r| Ok(r.clone())) - .unwrap_or(Err(ClientError::Custom("No response set for input".into()))) - } - } -} - -#[cfg(test)] -pub mod test_util { - use super::{ClientError, MixClient}; - use crate::crypto::dalek; - use crate::crypto::secp::SecretKey; - use crate::servers::mix::MixServer; - use crate::tx::TxComponents; - use crate::DalekPublicKey; - use grin_core::ser; - use grin_core::ser::ProtocolVersion; - use grin_onion::onion::Onion; - use std::sync::Arc; - - /// Implementation of the 'MixClient' trait that calls a mix server implementation directly. - /// No JSON-RPC serialization or socket communication occurs. - #[derive(Clone)] - pub struct DirectMixClient { - pub key: SecretKey, - pub mix_server: Arc, - } - - impl MixClient for DirectMixClient { - fn mix_outputs( - &self, - onions: &Vec, - ) -> Result<(Vec, TxComponents), ClientError> { - let serialized = ser::ser_vec(&onions, ProtocolVersion::local()).unwrap(); - let sig = dalek::sign(&self.key, serialized.as_slice()).map_err(ClientError::Dalek)?; - - sig.verify( - &DalekPublicKey::from_secret(&self.key), - serialized.as_slice(), - ) - .unwrap(); - Ok(self.mix_server.mix_outputs(&onions, &sig).unwrap()) - } - } -} diff --git a/src/config.rs b/src/config.rs index 1fab7dc..b5466cd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,20 +1,21 @@ -use crate::crypto::dalek::DalekPublicKey; -use crate::crypto::secp::SecretKey; - use core::num::NonZeroU32; -use grin_core::global::ChainTypes; -use grin_util::{file, ToHex, ZeroingString}; -use grin_wallet_util::OnionV3Address; -use rand::{thread_rng, Rng}; -use ring::{aead, pbkdf2}; -use serde_derive::{Deserialize, Serialize}; use std::fs::File; use std::io::prelude::*; use std::net::SocketAddr; use std::path::PathBuf; use std::result::Result; + +use grin_core::global::ChainTypes; +use grin_util::{file, ToHex, ZeroingString}; +use grin_wallet_util::OnionV3Address; +use rand::{Rng, thread_rng}; +use ring::{aead, pbkdf2}; +use serde_derive::{Deserialize, Serialize}; use thiserror::Error; +use grin_onion::crypto::dalek::DalekPublicKey; +use grin_onion::crypto::secp::SecretKey; + const GRIN_HOME: &str = ".grin"; const NODE_API_SECRET_FILE_NAME: &str = ".api_secret"; const WALLET_OWNER_API_SECRET_FILE_NAME: &str = ".owner_api_secret"; @@ -28,8 +29,6 @@ pub struct ServerConfig { pub interval_s: u32, /// socket address the server listener should bind to pub addr: SocketAddr, - /// socket address the tor sender should bind to - pub socks_proxy_addr: SocketAddr, /// foreign api address of the grin node pub grin_node_url: SocketAddr, /// path to file containing api secret for the grin node @@ -39,10 +38,10 @@ pub struct ServerConfig { /// path to file containing secret for the grin wallet's owner api pub wallet_owner_secret_path: Option, /// public key of the previous mix/swap server (e.g. N_1 if this is N_2) - #[serde(with = "crate::crypto::dalek::option_dalek_pubkey_serde", default)] + #[serde(with = "grin_onion::crypto::dalek::option_dalek_pubkey_serde", default)] pub prev_server: Option, /// public key of the next mix server - #[serde(with = "crate::crypto::dalek::option_dalek_pubkey_serde", default)] + #[serde(with = "grin_onion::crypto::dalek::option_dalek_pubkey_serde", default)] pub next_server: Option, } @@ -181,14 +180,13 @@ struct RawConfig { nonce: String, interval_s: u32, addr: SocketAddr, - socks_proxy_addr: SocketAddr, grin_node_url: SocketAddr, grin_node_secret_path: Option, wallet_owner_url: SocketAddr, wallet_owner_secret_path: Option, - #[serde(with = "crate::crypto::dalek::option_dalek_pubkey_serde", default)] + #[serde(with = "grin_onion::crypto::dalek::option_dalek_pubkey_serde", default)] prev_server: Option, - #[serde(with = "crate::crypto::dalek::option_dalek_pubkey_serde", default)] + #[serde(with = "grin_onion::crypto::dalek::option_dalek_pubkey_serde", default)] next_server: Option, } @@ -206,7 +204,6 @@ pub fn write_config( nonce: encrypted.nonce, interval_s: server_config.interval_s, addr: server_config.addr, - socks_proxy_addr: server_config.socks_proxy_addr, grin_node_url: server_config.grin_node_url, grin_node_secret_path: server_config.grin_node_secret_path.clone(), wallet_owner_url: server_config.wallet_owner_url, @@ -243,7 +240,6 @@ pub fn load_config( key: secret_key, interval_s: raw_config.interval_s, addr: raw_config.addr, - socks_proxy_addr: raw_config.socks_proxy_addr, grin_node_url: raw_config.grin_node_url, grin_node_secret_path: raw_config.grin_node_secret_path, wallet_owner_url: raw_config.wallet_owner_url, @@ -254,10 +250,7 @@ pub fn load_config( } pub fn get_grin_path(chain_type: &ChainTypes) -> PathBuf { - let mut grin_path = match dirs::home_dir() { - Some(p) => p, - None => PathBuf::new(), - }; + let mut grin_path = dirs::home_dir().unwrap_or_else(|| PathBuf::new()); grin_path.push(GRIN_HOME); grin_path.push(chain_type.shortname()); grin_path @@ -289,10 +282,13 @@ pub fn wallet_owner_url(_chain_type: &ChainTypes) -> SocketAddr { #[cfg(test)] pub mod test_util { - use crate::{DalekPublicKey, ServerConfig}; - use secp256k1zkp::SecretKey; use std::net::TcpListener; + use grin_onion::crypto::dalek::DalekPublicKey; + use secp256k1zkp::SecretKey; + + use crate::config::ServerConfig; + pub fn local_config( server_key: &SecretKey, prev_server: &Option, @@ -302,7 +298,6 @@ pub mod test_util { key: server_key.clone(), interval_s: 1, addr: TcpListener::bind("127.0.0.1:0")?.local_addr()?, - socks_proxy_addr: TcpListener::bind("127.0.0.1:0")?.local_addr()?, grin_node_url: "127.0.0.1:3413".parse()?, grin_node_secret_path: None, wallet_owner_url: "127.0.0.1:3420".parse()?, @@ -316,8 +311,9 @@ pub mod test_util { #[cfg(test)] mod tests { + use grin_onion::crypto::secp; + use super::*; - use crate::crypto::secp; #[test] fn server_key_encrypt() { diff --git a/src/http.rs b/src/http.rs new file mode 100644 index 0000000..d121aba --- /dev/null +++ b/src/http.rs @@ -0,0 +1,127 @@ +use std::time::Duration; + +use grin_api::json_rpc; +use grin_util::to_base64; +use grin_wallet_api::{EncryptedRequest, EncryptedResponse, JsonId}; +use hyper::body::Body as HyperBody; +use hyper::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT}; +use hyper::Request; +use serde_json::json; +use thiserror::Error; + +use secp256k1zkp::SecretKey; + +/// Error types for HTTP client connections +#[derive(Error, Debug)] +pub enum HttpError { + #[error("Error decrypting response")] + DecryptResponseError(), + #[error("Hyper HTTP error: {0:?}")] + HyperHttpError(hyper::http::Error), + #[error("Hyper request failed with error: {0:?}")] + RequestFailed(hyper::Error), + #[error("Error with response body: {0:?}")] + ResponseBodyError(hyper::Error), + #[error("Error deserializing JSON response: {0:?}")] + ResponseJsonError(serde_json::Error), + #[error("Error decoding JSON-RPC response: {0:?}")] + ResponseParseError(json_rpc::Error), + #[error("Wrong response code: {0}")] + ResponseStatusError(hyper::StatusCode), +} + +pub async fn async_send_enc_request( + url: &String, + api_secret: &Option, + method: &str, + params: &serde_json::Value, + shared_key: &SecretKey, +) -> Result { + let req = json!({ + "method": method, + "params": params, + "id": JsonId::IntId(1), + "jsonrpc": "2.0", + }); + let enc_req = EncryptedRequest::from_json(&JsonId::IntId(1), &req, &shared_key).unwrap(); + let req = build_request(&url, &api_secret, serde_json::to_string(&enc_req).unwrap())?; + let response_str = send_request_async(req).await?; + let enc_res: EncryptedResponse = + serde_json::from_str(&response_str).map_err(HttpError::ResponseJsonError)?; + + let decrypted = enc_res + .decrypt(&shared_key) + .map_err(|_| HttpError::DecryptResponseError())?; + + let response: json_rpc::Response = + serde_json::from_value(decrypted).map_err(HttpError::ResponseJsonError)?; + let parsed = response + .clone() + .into_result() + .map_err(HttpError::ResponseParseError)?; + Ok(parsed) +} + +pub async fn async_send_json_request( + url: &String, + api_secret: &Option, + method: &str, + params: &serde_json::Value, +) -> Result { + let req_body = json!({ + "method": method, + "params": params, + "id": 1, + "jsonrpc": "2.0", + }); + let req = build_request(&url, &api_secret, serde_json::to_string(&req_body).unwrap())?; + let data = send_request_async(req).await?; + let ser: json_rpc::Response = + serde_json::from_str(&data).map_err(HttpError::ResponseJsonError)?; + let parsed = ser + .clone() + .into_result() + .map_err(HttpError::ResponseParseError)?; + Ok(parsed) +} + +pub fn build_request( + url: &String, + api_secret: &Option, + req_body: String, +) -> Result, HttpError> { + let mut req_builder = hyper::Request::builder(); + if let Some(api_secret) = api_secret { + let basic_auth = format!("Basic {}", to_base64(&format!("grin:{}", api_secret))); + req_builder = req_builder.header(AUTHORIZATION, basic_auth); + } + + req_builder + .method(hyper::Method::POST) + .uri(url) + .header(USER_AGENT, "grin-client") + .header(ACCEPT, "application/json") + .header(CONTENT_TYPE, "application/json") + .body(HyperBody::from(req_body)) + .map_err(HttpError::HyperHttpError) +} + +async fn send_request_async(req: Request) -> Result { + let client = hyper::Client::builder() + .pool_idle_timeout(Duration::from_secs(30)) + .build_http(); + + let resp = client + .request(req) + .await + .map_err(HttpError::RequestFailed)?; + if !resp.status().is_success() { + return Err(HttpError::ResponseStatusError(resp.status())); + } + + let raw = hyper::body::to_bytes(resp) + .await + .map_err(HttpError::ResponseBodyError)?; + + Ok(String::from_utf8_lossy(&raw).to_string()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..20846bd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,22 @@ +#[macro_use] +extern crate log; + +pub mod config; +pub mod http; +pub mod mix_client; +pub mod node; +pub mod servers; +pub mod store; +pub mod tor; +pub mod tx; +pub mod wallet; + +pub use config::ServerConfig; +pub use mix_client::MixClient; +pub use node::{GrinNode, HttpGrinNode, NodeError}; +pub use servers::mix::{MixError, MixServer}; +pub use servers::mix_rpc::listen as mix_listen; +pub use servers::swap::{SwapError, SwapServer}; +pub use servers::swap_rpc::listen as swap_listen; +pub use store::{StoreError, SwapStore}; +pub use wallet::{HttpWallet, Wallet, WalletError}; diff --git a/src/mix_client.rs b/src/mix_client.rs new file mode 100644 index 0000000..7f39f4f --- /dev/null +++ b/src/mix_client.rs @@ -0,0 +1,189 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use grin_api::json_rpc::{build_request, Response}; +use grin_core::ser; +use grin_core::ser::ProtocolVersion; +use grin_wallet_util::OnionV3Address; +use serde_json; +use serde_json::json; +use thiserror::Error; +use tor_rtcompat::Runtime; + +use grin_onion::crypto::dalek::{self, DalekPublicKey}; +use grin_onion::onion::Onion; + +use crate::config::ServerConfig; +use crate::servers::mix_rpc::{MixReq, MixResp}; +use crate::tor::TorService; +use crate::{http, tor}; + +/// Error types for interacting with nodes +#[derive(Error, Debug)] +pub enum MixClientError { + #[error("Tor Error: {0:?}")] + Tor(tor::TorError), + #[error("Communication Error: {0:?}")] + CommError(http::HttpError), + #[error("Dalek Error: {0:?}")] + Dalek(dalek::DalekError), + #[error("Error decoding JSON response: {0:?}")] + DecodeResponseError(serde_json::Error), + #[error("Error in JSON-RPC response: {0:?}")] + ResponseError(grin_api::json_rpc::RpcError), + #[error("Custom client error: {0:?}")] + Custom(String), +} + +/// A client for consuming a mix API +#[async_trait] +pub trait MixClient: Send + Sync { + /// Swaps the outputs provided and returns the final swapped outputs and kernels. + async fn mix_outputs(&self, onions: &Vec) -> Result; +} + +pub struct MixClientImpl { + config: ServerConfig, + tor: Arc>>, + addr: OnionV3Address, +} + +impl MixClientImpl { + pub fn new( + config: ServerConfig, + tor: Arc>>, + next_pubkey: DalekPublicKey, + ) -> Self { + let addr = OnionV3Address::from_bytes(next_pubkey.as_ref().to_bytes()); + MixClientImpl { config, tor, addr } + } + + async fn async_send_json_request( + &self, + addr: &OnionV3Address, + method: &str, + params: &serde_json::Value, + ) -> Result { + let url = format!("{}/v1", addr.to_http_str()); + let request_str = serde_json::to_string(&build_request(method, params)).unwrap(); + let hyper_request = + http::build_request(&url, &None, request_str).map_err(MixClientError::CommError)?; + + let hyper_client = self.tor.lock().new_hyper_client(); + let res = hyper_client.request(hyper_request).await.unwrap(); + + let body_bytes = hyper::body::to_bytes(res.into_body()).await.unwrap(); + let res = String::from_utf8(body_bytes.to_vec()).unwrap(); + + let response: Response = + serde_json::from_str(&res).map_err(MixClientError::DecodeResponseError)?; + + if let Some(ref e) = response.error { + return Err(MixClientError::ResponseError(e.clone())); + } + + let result = match response.result.clone() { + Some(r) => serde_json::from_value(r).map_err(MixClientError::DecodeResponseError), + None => serde_json::from_value(serde_json::Value::Null) + .map_err(MixClientError::DecodeResponseError), + }?; + + Ok(result) + } +} + +#[async_trait] +impl MixClient for MixClientImpl { + async fn mix_outputs(&self, onions: &Vec) -> Result { + let serialized = ser::ser_vec(&onions, ProtocolVersion::local()).unwrap(); + let sig = + dalek::sign(&self.config.key, serialized.as_slice()).map_err(MixClientError::Dalek)?; + let mix = MixReq::new(onions.clone(), sig); + + self.async_send_json_request::(&self.addr, "mix", &json!([mix])) + .await + } +} + +#[cfg(test)] +pub mod mock { + use std::collections::HashMap; + + use async_trait::async_trait; + + use grin_onion::onion::Onion; + + use crate::servers::mix_rpc::MixResp; + + use super::{MixClient, MixClientError}; + + pub struct MockMixClient { + results: HashMap, MixResp>, + } + + impl MockMixClient { + pub fn new() -> MockMixClient { + MockMixClient { + results: HashMap::new(), + } + } + + pub fn set_response(&mut self, onions: &Vec, r: MixResp) { + self.results.insert(onions.clone(), r); + } + } + + #[async_trait] + impl MixClient for MockMixClient { + async fn mix_outputs(&self, onions: &Vec) -> Result { + self.results + .get(onions) + .map(|r| Ok(r.clone())) + .unwrap_or(Err(MixClientError::Custom( + "No response set for input".into(), + ))) + } + } +} + +#[cfg(test)] +pub mod test_util { + use std::sync::Arc; + + use async_trait::async_trait; + use grin_core::ser; + use grin_core::ser::ProtocolVersion; + + use grin_onion::crypto::dalek::{self, DalekPublicKey}; + use grin_onion::crypto::secp::SecretKey; + use grin_onion::onion::Onion; + + use crate::servers::mix::MixServer; + use crate::servers::mix_rpc::MixResp; + + use super::{MixClient, MixClientError}; + + /// Implementation of the 'MixClient' trait that calls a mix server implementation directly. + /// No JSON-RPC serialization or socket communication occurs. + #[derive(Clone)] + pub struct DirectMixClient { + pub key: SecretKey, + pub mix_server: Arc, + } + + #[async_trait] + impl MixClient for DirectMixClient { + async fn mix_outputs(&self, onions: &Vec) -> Result { + let serialized = ser::ser_vec(&onions, ProtocolVersion::local()).unwrap(); + let sig = + dalek::sign(&self.key, serialized.as_slice()).map_err(MixClientError::Dalek)?; + + sig.verify( + &DalekPublicKey::from_secret(&self.key), + serialized.as_slice(), + ) + .unwrap(); + Ok(self.mix_server.mix_outputs(&onions, &sig).await.unwrap()) + } + } +} diff --git a/src/node.rs b/src/node.rs index 9c5236b..2bf55c5 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,26 +1,44 @@ -use crate::crypto::secp::Commitment; - -use grin_api::client; -use grin_api::json_rpc::{build_request, Request, Response}; -use grin_api::{OutputPrintable, OutputType, Tip}; -use grin_core::consensus::COINBASE_MATURITY; -use grin_core::core::{Input, OutputFeatures, Transaction}; -use grin_util::ToHex; - -use serde_json::json; use std::net::SocketAddr; use std::sync::Arc; + +use async_trait::async_trait; +use grin_api::LocatedTxKernel; +use grin_api::{OutputPrintable, OutputType, Tip}; +use grin_core::consensus::COINBASE_MATURITY; +use grin_core::core::hash::Hash; +use grin_core::core::{Committed, Input, OutputFeatures, Transaction}; +use grin_util::ToHex; +use serde_json::json; use thiserror::Error; +use grin_onion::crypto::secp::Commitment; + +use crate::http; + +#[async_trait] pub trait GrinNode: Send + Sync { /// Retrieves the unspent output with a matching commitment - fn get_utxo(&self, output_commit: &Commitment) -> Result, NodeError>; + async fn async_get_utxo( + &self, + output_commit: &Commitment, + ) -> Result, NodeError>; - /// Gets the height of the chain tip - fn get_chain_height(&self) -> Result; + /// Gets the height and hash of the chain tip + async fn async_get_chain_tip(&self) -> Result<(u64, Hash), NodeError>; /// Posts a transaction to the grin node - fn post_tx(&self, tx: &Transaction) -> Result<(), NodeError>; + async fn async_post_tx(&self, tx: &Transaction) -> Result<(), NodeError>; + + /// Returns a LocatedTxKernel based on the kernel excess. + /// The min_height and max_height parameters are both optional. + /// If not supplied, min_height will be set to 0 and max_height will be set to the head of the chain. + /// The method will start at the block height max_height and traverse the kernel MMR backwards, until either the kernel is found or min_height is reached. + async fn async_get_kernel( + &self, + excess: &Commitment, + min_height: Option, + max_height: Option, + ) -> Result, NodeError>; } /// Error types for interacting with nodes @@ -30,23 +48,28 @@ pub enum NodeError { DecodeResponseError(serde_json::Error), #[error("JSON-RPC API communication error: {0:?}")] ApiCommError(grin_api::Error), + #[error("Client error: {0:?}")] + NodeCommError(http::HttpError), #[error("Error decoding JSON-RPC response: {0:?}")] ResponseParseError(grin_api::json_rpc::Error), } /// Checks if a commitment is in the UTXO set -pub fn is_unspent(node: &Arc, commit: &Commitment) -> Result { - let utxo = node.get_utxo(&commit)?; +pub async fn async_is_unspent( + node: &Arc, + commit: &Commitment, +) -> Result { + let utxo = node.async_get_utxo(&commit).await?; Ok(utxo.is_some()) } /// Checks whether a commitment is spendable at the block height provided -pub fn is_spendable( +pub async fn async_is_spendable( node: &Arc, commit: &Commitment, next_block_height: u64, ) -> Result { - let output = node.get_utxo(&commit)?; + let output = node.async_get_utxo(&commit).await?; if let Some(out) = output { let is_coinbase = match out.output_type { OutputType::Coinbase => true, @@ -70,11 +93,11 @@ pub fn is_spendable( } /// Builds an input for an unspent output commitment -pub fn build_input( +pub async fn async_build_input( node: &Arc, output_commit: &Commitment, ) -> Result, NodeError> { - let output = node.get_utxo(&output_commit)?; + let output = node.async_get_utxo(&output_commit).await?; if let Some(out) = output { let features = match out.output_type { @@ -89,6 +112,26 @@ pub fn build_input( Ok(None) } +pub async fn async_is_tx_valid( + node: &Arc, + tx: &Transaction, +) -> Result { + let next_block_height = node.async_get_chain_tip().await?.0 + 1; + for input_commit in &tx.inputs_committed() { + if !async_is_spendable(&node, &input_commit, next_block_height).await? { + return Ok(false); + } + } + + for output_commit in &tx.outputs_committed() { + if async_is_unspent(&node, &output_commit).await? { + return Ok(false); + } + } + + Ok(true) +} + /// HTTP (JSON-RPC) implementation of the 'GrinNode' trait #[derive(Clone)] pub struct HttpGrinNode { @@ -106,30 +149,25 @@ impl HttpGrinNode { } } - fn send_json_request( + async fn async_send_request( &self, method: &str, params: &serde_json::Value, ) -> Result { let url = format!("http://{}{}", self.node_url, ENDPOINT); - let req = build_request(method, params); - let res = - client::post::( - url.as_str(), - self.node_api_secret.clone(), - &req, - client::TimeOut::default() - ).map_err(NodeError::ApiCommError)?; - let parsed = res - .clone() - .into_result() - .map_err(NodeError::ResponseParseError)?; + let parsed = http::async_send_json_request(&url, &self.node_api_secret, &method, ¶ms) + .await + .map_err(NodeError::NodeCommError)?; Ok(parsed) } } +#[async_trait] impl GrinNode for HttpGrinNode { - fn get_utxo(&self, output_commit: &Commitment) -> Result, NodeError> { + async fn async_get_utxo( + &self, + output_commit: &Commitment, + ) -> Result, NodeError> { let commits: Vec = vec![output_commit.to_hex()]; let start_height: Option = None; let end_height: Option = None; @@ -143,7 +181,9 @@ impl GrinNode for HttpGrinNode { include_proof, include_merkle_proof ]); - let outputs = self.send_json_request::>("get_outputs", ¶ms)?; + let outputs = self + .async_send_request::>("get_outputs", ¶ms) + .await?; if outputs.is_empty() { return Ok(None); } @@ -151,37 +191,69 @@ impl GrinNode for HttpGrinNode { Ok(Some(outputs[0].clone())) } - fn get_chain_height(&self) -> Result { + async fn async_get_chain_tip(&self) -> Result<(u64, Hash), NodeError> { let params = json!([]); - let tip_json = self.send_json_request::("get_tip", ¶ms)?; + let tip_json = self + .async_send_request::("get_tip", ¶ms) + .await?; let tip = serde_json::from_value::(tip_json).map_err(NodeError::DecodeResponseError)?; - Ok(tip.height) + Ok(( + tip.height, + Hash::from_hex(tip.last_block_pushed.as_str()).unwrap(), + )) } - fn post_tx(&self, tx: &Transaction) -> Result<(), NodeError> { + async fn async_post_tx(&self, tx: &Transaction) -> Result<(), NodeError> { let params = json!([tx, true]); - self.send_json_request::("push_transaction", ¶ms)?; + self.async_send_request::("push_transaction", ¶ms) + .await?; Ok(()) } + + async fn async_get_kernel( + &self, + excess: &Commitment, + min_height: Option, + max_height: Option, + ) -> Result, NodeError> { + let params = json!([excess.0.as_ref().to_hex(), min_height, max_height]); + let value = self + .async_send_request::("get_kernel", ¶ms) + .await?; + + let contents = format!("{:?}", value); + if contents.contains("NotFound") { + return Ok(None); + } + + let located_kernel = serde_json::from_value::(value) + .map_err(NodeError::DecodeResponseError)?; + Ok(Some(located_kernel)) + } } #[cfg(test)] pub mod mock { - use super::{GrinNode, NodeError}; - use crate::crypto::secp::Commitment; - - use grin_api::{OutputPrintable, OutputType}; - use grin_core::core::Transaction; use std::collections::HashMap; use std::sync::RwLock; + use async_trait::async_trait; + use grin_api::{LocatedTxKernel, OutputPrintable, OutputType}; + use grin_core::core::hash::Hash; + use grin_core::core::Transaction; + + use grin_onion::crypto::secp::Commitment; + + use super::{GrinNode, NodeError}; + /// Implementation of 'GrinNode' trait that mocks a grin node instance. /// Use only for testing purposes. pub struct MockGrinNode { utxos: HashMap, txns_posted: RwLock>, + kernels: HashMap, } impl MockGrinNode { @@ -189,6 +261,7 @@ pub mod mock { MockGrinNode { utxos: HashMap::new(), txns_posted: RwLock::new(Vec::new()), + kernels: HashMap::new(), } } @@ -196,6 +269,7 @@ pub mod mock { let mut node = MockGrinNode { utxos: HashMap::new(), txns_posted: RwLock::new(Vec::new()), + kernels: HashMap::new(), }; for utxo in utxos { node.add_default_utxo(utxo); @@ -226,10 +300,16 @@ pub mod mock { let read = self.txns_posted.read().unwrap(); read.clone() } + + pub fn add_kernel(&mut self, kernel: &LocatedTxKernel) { + self.kernels + .insert(kernel.tx_kernel.excess.clone(), kernel.clone()); + } } + #[async_trait] impl GrinNode for MockGrinNode { - fn get_utxo( + async fn async_get_utxo( &self, output_commit: &Commitment, ) -> Result, NodeError> { @@ -240,14 +320,27 @@ pub mod mock { Ok(None) } - fn get_chain_height(&self) -> Result { - Ok(100) + async fn async_get_chain_tip(&self) -> Result<(u64, Hash), NodeError> { + Ok((100, Hash::default())) } - fn post_tx(&self, tx: &Transaction) -> Result<(), NodeError> { + async fn async_post_tx(&self, tx: &Transaction) -> Result<(), NodeError> { let mut write = self.txns_posted.write().unwrap(); write.push(tx.clone()); Ok(()) } + + async fn async_get_kernel( + &self, + excess: &Commitment, + _min_height: Option, + _max_height: Option, + ) -> Result, NodeError> { + if let Some(kernel) = self.kernels.get(&excess) { + return Ok(Some(kernel.clone())); + } + + Ok(None) + } } } diff --git a/src/servers/mix.rs b/src/servers/mix.rs index 4510521..914f283 100644 --- a/src/servers/mix.rs +++ b/src/servers/mix.rs @@ -1,21 +1,26 @@ -use crate::client::MixClient; -use crate::config::ServerConfig; -use crate::tx::TxComponents; -use crate::wallet::Wallet; -use crate::{node, tx, GrinNode}; +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; +use async_trait::async_trait; +use futures::stream::{self, StreamExt}; use grin_core::core::{Output, OutputFeatures, TransactionBody}; use grin_core::global::DEFAULT_ACCEPT_FEE_BASE; use grin_core::ser; use grin_core::ser::ProtocolVersion; +use itertools::Itertools; +use thiserror::Error; + use grin_onion::crypto::dalek::{self, DalekSignature}; use grin_onion::onion::{Onion, OnionError, PeeledOnion}; -use itertools::Itertools; use secp256k1zkp::key::ZERO_KEY; use secp256k1zkp::Secp256k1; -use std::collections::{HashMap, HashSet}; -use std::sync::Arc; -use thiserror::Error; + +use crate::config::ServerConfig; +use crate::mix_client::MixClient; +use crate::node::{self, GrinNode}; +use crate::servers::mix_rpc::MixResp; +use crate::tx::{self, TxComponents}; +use crate::wallet::Wallet; /// Mixer error types #[derive(Error, Debug)] @@ -43,17 +48,18 @@ pub enum MixError { #[error("Wallet error: {0:?}")] WalletError(crate::wallet::WalletError), #[error("Client comm error: {0:?}")] - Client(crate::client::ClientError), + Client(crate::mix_client::MixClientError), } /// An internal MWixnet server - a "Mixer" +#[async_trait] pub trait MixServer: Send + Sync { /// Swaps the outputs provided and returns the final swapped outputs and kernels. - fn mix_outputs( + async fn mix_outputs( &self, onions: &Vec, sig: &DalekSignature, - ) -> Result<(Vec, TxComponents), MixError>; + ) -> Result; } /// The standard MWixnet "Mixer" implementation @@ -130,15 +136,19 @@ impl MixServerImpl { Ok(peeled) } - fn build_final_outputs( + async fn async_build_final_outputs( &self, peeled: &Vec<(usize, PeeledOnion)>, - ) -> Result<(Vec, TxComponents), MixError> { + ) -> Result { // Filter out commitments that already exist in the UTXO set - let filtered: Vec<&(usize, PeeledOnion)> = peeled - .iter() - .filter(|(_, p)| !node::is_unspent(&self.node, &p.onion.commit).unwrap_or(true)) - .collect(); + let filtered: Vec<&(usize, PeeledOnion)> = stream::iter(peeled.iter()) + .filter(|(_, p)| async { + !node::async_is_unspent(&self.node, &p.onion.commit) + .await + .unwrap_or(true) + }) + .collect() + .await; // Build plain outputs for each mix entry let outputs: Vec = filtered @@ -158,7 +168,7 @@ impl MixServerImpl { .map(|(_, p)| p.payload.excess.clone()) .collect(); - let components = tx::assemble_components( + let components = tx::async_assemble_components( &self.wallet, &TxComponents { offset: ZERO_KEY, @@ -169,17 +179,21 @@ impl MixServerImpl { self.get_fee_base(), fees_paid, ) + .await .map_err(MixError::TxError)?; let indices = filtered.iter().map(|(i, _)| *i).collect(); - Ok((indices, components)) + Ok(MixResp { + indices, + components, + }) } - fn call_next_mixer( + async fn call_next_mixer( &self, peeled: &Vec<(usize, PeeledOnion)>, - ) -> Result<(Vec, TxComponents), MixError> { + ) -> Result { // Sort by commitment let mut onions_with_index = peeled.clone(); onions_with_index @@ -191,15 +205,16 @@ impl MixServerImpl { // Call next server let onions = peeled.iter().map(|(_, p)| p.onion.clone()).collect(); - let (mixed_indices, mixed_components) = self + let mixed = self .mix_client .as_ref() .unwrap() .mix_outputs(&onions) + .await .map_err(MixError::Client)?; // Remove filtered entries - let kept_next_indices = HashSet::<_>::from_iter(mixed_indices.clone()); + let kept_next_indices = HashSet::<_>::from_iter(mixed.indices.clone()); let filtered_onions: Vec<&(usize, PeeledOnion)> = onions_with_index .iter() .filter(|(i, _)| { @@ -221,25 +236,30 @@ impl MixServerImpl { let indices = kept_next_indices.into_iter().sorted().collect(); - let components = tx::assemble_components( + let components = tx::async_assemble_components( &self.wallet, - &mixed_components, + &mixed.components, &excesses, self.get_fee_base(), fees_paid, ) + .await .map_err(MixError::TxError)?; - Ok((indices, components)) + Ok(MixResp { + indices, + components, + }) } } +#[async_trait] impl MixServer for MixServerImpl { - fn mix_outputs( + async fn mix_outputs( &self, onions: &Vec, sig: &DalekSignature, - ) -> Result<(Vec, TxComponents), MixError> { + ) -> Result { // Verify Signature let serialized = ser::ser_vec(&onions, ProtocolVersion::local()).unwrap(); sig.verify( @@ -252,10 +272,10 @@ impl MixServer for MixServerImpl { let mut peeled: Vec<(usize, PeeledOnion)> = onions .iter() .enumerate() - .filter_map(|(i, o)| { - if let Some(p) = self.peel_onion(&o).ok() { - Some((i, p)) - } else { + .filter_map(|(i, o)| match self.peel_onion(&o) { + Ok(p) => Some((i, p)), + Err(e) => { + println!("Error peeling onion: {:?}", e); None } }) @@ -271,24 +291,27 @@ impl MixServer for MixServerImpl { } if self.server_config.next_server.is_some() { - self.call_next_mixer(&peeled) + self.call_next_mixer(&peeled).await } else { - self.build_final_outputs(&peeled) + self.async_build_final_outputs(&peeled).await } } } #[cfg(test)] mod test_util { - use crate::client::test_util::DirectMixClient; - use crate::node::mock::MockGrinNode; - use crate::wallet::mock::MockWallet; - use crate::{config, DalekPublicKey, MixClient}; - - use crate::servers::mix::MixServerImpl; - use secp256k1zkp::SecretKey; use std::sync::Arc; + use grin_onion::crypto::dalek::DalekPublicKey; + use secp256k1zkp::SecretKey; + + use crate::config; + use crate::mix_client::MixClient; + use crate::mix_client::test_util::DirectMixClient; + use crate::node::mock::MockGrinNode; + use crate::servers::mix::MixServerImpl; + use crate::wallet::mock::MockWallet; + pub fn new_mixer( server_key: &SecretKey, prev_server: (&SecretKey, &DalekPublicKey), @@ -320,18 +343,21 @@ mod test_util { #[cfg(test)] mod tests { - use crate::node::mock::MockGrinNode; - use crate::{DalekPublicKey, MixClient}; - - use ::function_name::named; - use grin_onion::crypto::secp::{self, Commitment}; - use grin_onion::test_util as onion_test_util; - use grin_onion::{create_onion, new_hop, Hop}; - use secp256k1zkp::pedersen::RangeProof; - use secp256k1zkp::SecretKey; use std::collections::HashSet; use std::sync::Arc; + use ::function_name::named; + + use grin_onion::{create_onion, Hop, new_hop}; + use grin_onion::crypto::dalek::DalekPublicKey; + use grin_onion::crypto::secp::{self, Commitment}; + use grin_onion::test_util as onion_test_util; + use secp256k1zkp::pedersen::RangeProof; + use secp256k1zkp::SecretKey; + + use crate::mix_client::MixClient; + use crate::node::mock::MockGrinNode; + macro_rules! init_test { () => {{ grin_core::global::set_local_chain_type( @@ -373,9 +399,9 @@ mod tests { /// * Swap Server - Simulated by test /// * Mixer 1 - Internal MixServerImpl directly called by test /// * Mixer 2 - Final MixServerImpl called by Mixer 1 - #[test] + #[tokio::test] #[named] - fn mix_lifecycle() -> Result<(), Box> { + async fn mix_lifecycle() -> Result<(), Box> { init_test!(); // Setup Input(s) @@ -426,13 +452,15 @@ mod tests { // Simulate the swap server peeling the onion and then calling mix1 let mix1_onion = onion.peel_layer(&swap_vars.sk)?; - let (mixed_indices, mixed_components) = - mixer1_client.mix_outputs(&vec![mix1_onion.onion.clone()])?; + let mixed = mixer1_client + .mix_outputs(&vec![mix1_onion.onion.clone()]) + .await?; // Verify 3 outputs are returned: mixed output, mixer1's output, and mixer2's output - assert_eq!(mixed_indices, vec![0 as usize]); - assert_eq!(mixed_components.outputs.len(), 3); - let output_commits: HashSet = mixed_components + assert_eq!(mixed.indices, vec![0 as usize]); + assert_eq!(mixed.components.outputs.len(), 3); + let output_commits: HashSet = mixed + .components .outputs .iter() .map(|o| o.identifier.commit.clone()) diff --git a/src/servers/mix_rpc.rs b/src/servers/mix_rpc.rs index 7cb5181..f485d1f 100644 --- a/src/servers/mix_rpc.rs +++ b/src/servers/mix_rpc.rs @@ -1,20 +1,21 @@ -use crate::client::MixClient; +use std::sync::Arc; + +use futures::FutureExt; +use jsonrpc_derive::rpc; +use jsonrpc_http_server::{DomainsValidation, ServerBuilder}; +use jsonrpc_http_server::jsonrpc_core::{self, BoxFuture, IoHandler}; +use serde::{Deserialize, Serialize}; + +use grin_onion::crypto::dalek::{self, DalekSignature}; +use grin_onion::onion::Onion; + use crate::config::ServerConfig; -use crate::crypto::dalek::{self, DalekSignature}; +use crate::mix_client::MixClient; use crate::node::GrinNode; use crate::servers::mix::{MixError, MixServer, MixServerImpl}; +use crate::tx::TxComponents; use crate::wallet::Wallet; -use grin_onion::onion::Onion; -use grin_util::StopState; -use jsonrpc_derive::rpc; -use jsonrpc_http_server::jsonrpc_core::{self as jsonrpc, IoHandler}; -use jsonrpc_http_server::{DomainsValidation, ServerBuilder}; -use serde::{Deserialize, Serialize}; -use std::sync::{Arc, Mutex}; -use std::thread::{sleep, spawn}; -use std::time::Duration; - #[derive(Serialize, Deserialize)] pub struct MixReq { onions: Vec, @@ -22,6 +23,12 @@ pub struct MixReq { sig: DalekSignature, } +#[derive(Clone, Serialize, Deserialize)] +pub struct MixResp { + pub indices: Vec, + pub components: TxComponents, +} + impl MixReq { pub fn new(onions: Vec, sig: DalekSignature) -> Self { MixReq { onions, sig } @@ -31,22 +38,23 @@ impl MixReq { #[rpc(server)] pub trait MixAPI { #[rpc(name = "mix")] - fn mix(&self, mix: MixReq) -> jsonrpc::Result; + fn mix(&self, mix: MixReq) -> BoxFuture>; } #[derive(Clone)] struct RPCMixServer { server_config: ServerConfig, - server: Arc>, + server: Arc>, } impl RPCMixServer { /// Spin up an instance of the JSON-RPC HTTP server. - fn start_http(&self) -> jsonrpc_http_server::Server { + fn start_http(&self, runtime_handle: tokio::runtime::Handle) -> jsonrpc_http_server::Server { let mut io = IoHandler::new(); io.extend_with(RPCMixServer::to_delegate(self.clone())); ServerBuilder::new(io) + .event_loop_executor(runtime_handle) .cors(DomainsValidation::Disabled) .request_middleware(|request: hyper::Request| { if request.uri() == "/v1" { @@ -60,57 +68,55 @@ impl RPCMixServer { } } -impl From for jsonrpc::Error { +impl From for jsonrpc_core::Error { fn from(e: MixError) -> Self { - jsonrpc::Error::invalid_params(e.to_string()) + jsonrpc_core::Error::invalid_params(e.to_string()) } } impl MixAPI for RPCMixServer { - fn mix(&self, mix: MixReq) -> jsonrpc::Result { - self.server - .lock() - .unwrap() - .mix_outputs(&mix.onions, &mix.sig)?; - Ok(jsonrpc::Value::String("success".into())) + fn mix(&self, mix: MixReq) -> BoxFuture> { + let server = self.server.clone(); + async move { + let response = server + .lock() + .await + .mix_outputs(&mix.onions, &mix.sig) + .await?; + Ok(response) + } + .boxed() } } /// Spin up the JSON-RPC web server pub fn listen( + rt_handle: &tokio::runtime::Handle, server_config: ServerConfig, next_server: Option>, wallet: Arc, node: Arc, - stop_state: Arc, -) -> Result<(), Box> { +) -> Result< + ( + Arc>, + jsonrpc_http_server::Server, + ), + Box, +> { let server = MixServerImpl::new( server_config.clone(), next_server, wallet.clone(), node.clone(), ); - let server = Arc::new(Mutex::new(server)); + let server = Arc::new(tokio::sync::Mutex::new(server)); let rpc_server = RPCMixServer { server_config: server_config.clone(), server: server.clone(), }; - let http_server = rpc_server.start_http(); + let http_server = rpc_server.start_http(rt_handle.clone()); - let close_handle = http_server.close_handle(); - let round_handle = spawn(move || loop { - if stop_state.is_stopped() { - close_handle.close(); - break; - } - - sleep(Duration::from_millis(100)); - }); - - http_server.wait(); - round_handle.join().unwrap(); - - Ok(()) + Ok((server, http_server)) } diff --git a/src/servers/swap.rs b/src/servers/swap.rs index a02095c..2b5e0e4 100644 --- a/src/servers/swap.rs +++ b/src/servers/swap.rs @@ -1,23 +1,25 @@ -use crate::client::MixClient; -use crate::config::ServerConfig; -use crate::crypto::comsig::ComSignature; -use crate::crypto::secp::{Commitment, Secp256k1, SecretKey}; -use crate::node::{self, GrinNode}; -use crate::store::{StoreError, SwapData, SwapStatus, SwapStore}; -use crate::tx; -use crate::wallet::Wallet; - -use grin_core::core::hash::Hashed; -use grin_core::core::{Input, Output, OutputFeatures, Transaction, TransactionBody}; -use grin_core::global::DEFAULT_ACCEPT_FEE_BASE; -use grin_onion::onion::{Onion, OnionError}; -use itertools::Itertools; -use secp256k1zkp::key::ZERO_KEY; use std::collections::HashSet; use std::result::Result; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; + +use async_trait::async_trait; +use grin_core::core::{Committed, Input, Output, OutputFeatures, Transaction, TransactionBody}; +use grin_core::global::DEFAULT_ACCEPT_FEE_BASE; +use itertools::Itertools; +use secp256k1zkp::key::ZERO_KEY; use thiserror::Error; +use grin_onion::crypto::comsig::ComSignature; +use grin_onion::crypto::secp::{Commitment, Secp256k1, SecretKey}; +use grin_onion::onion::{Onion, OnionError}; + +use crate::config::ServerConfig; +use crate::mix_client::MixClient; +use crate::node::{self, GrinNode}; +use crate::store::{StoreError, SwapData, SwapStatus, SwapStore, SwapTx}; +use crate::tx; +use crate::wallet::Wallet; + /// Swap error types #[derive(Clone, Error, Debug, PartialEq)] pub enum SwapError { @@ -39,20 +41,53 @@ pub enum SwapError { FeeTooLow { minimum_fee: u64, actual_fee: u64 }, #[error("Error saving swap to data store: {0}")] StoreError(StoreError), + #[error("Error building transaction: {0}")] + TxError(String), + #[error("Node communication error: {0}")] + NodeError(String), #[error("Client communication error: {0:?}")] ClientError(String), + #[error("Swap transaction not found: {0:?}")] + SwapTxNotFound(Commitment), #[error("{0}")] UnknownError(String), } +impl From for SwapError { + fn from(e: StoreError) -> SwapError { + SwapError::StoreError(e) + } +} + +impl From for SwapError { + fn from(e: tx::TxError) -> SwapError { + SwapError::TxError(e.to_string()) + } +} + +impl From for SwapError { + fn from(e: node::NodeError) -> SwapError { + SwapError::NodeError(e.to_string()) + } +} + /// A public MWixnet server - the "Swap Server" +#[async_trait] pub trait SwapServer: Send + Sync { /// Submit a new output to be swapped. - fn swap(&self, onion: &Onion, comsig: &ComSignature) -> Result<(), SwapError>; + async fn swap(&self, onion: &Onion, comsig: &ComSignature) -> Result<(), SwapError>; /// Iterate through all saved submissions, filter out any inputs that are no longer spendable, /// and assemble the coinswap transaction, posting the transaction to the configured node. - fn execute_round(&self) -> Result, Box>; + async fn execute_round(&self) -> Result>, SwapError>; + + /// Verify the previous swap transaction is in the active chain or mempool. + /// If it's not, rebroacast the transaction if it's still valid. + /// If the transaction is no longer valid, perform the swap again. + async fn check_reorg( + &self, + tx: &Arc, + ) -> Result>, SwapError>; } /// The standard MWixnet server implementation @@ -62,7 +97,7 @@ pub struct SwapServerImpl { next_server: Option>, wallet: Arc, node: Arc, - store: Arc>, + store: Arc>, } impl SwapServerImpl { @@ -79,7 +114,7 @@ impl SwapServerImpl { next_server, wallet, node, - store: Arc::new(Mutex::new(store)), + store: Arc::new(tokio::sync::Mutex::new(store)), } } @@ -93,10 +128,127 @@ impl SwapServerImpl { fn get_minimum_swap_fee(&self) -> u64 { TransactionBody::weight_by_iok(1, 1, 1) * self.get_fee_base() } + + async fn async_is_spendable(&self, next_block_height: u64, swap: &SwapData) -> bool { + if let SwapStatus::Unprocessed = swap.status { + if node::async_is_spendable(&self.node, &swap.input.commit, next_block_height) + .await + .unwrap_or(false) + { + if !node::async_is_unspent(&self.node, &swap.output_commit) + .await + .unwrap_or(true) + { + return true; + } + } + } + + false + } + + async fn async_execute_round( + &self, + store: &SwapStore, + mut swaps: Vec, + ) -> Result>, SwapError> { + swaps.sort_by(|a, b| a.output_commit.partial_cmp(&b.output_commit).unwrap()); + + if swaps.len() == 0 { + return Ok(None); + } + + let (filtered, failed, offset, outputs, kernels) = if let Some(client) = &self.next_server { + // Call next mix server + let onions = swaps.iter().map(|s| s.onion.clone()).collect(); + let mixed = client + .mix_outputs(&onions) + .await + .map_err(|e| SwapError::ClientError(e.to_string()))?; + + // Filter out failed entries + let kept_indices = HashSet::<_>::from_iter(mixed.indices.clone()); + let filtered = swaps + .iter() + .enumerate() + .filter(|(i, _)| kept_indices.contains(i)) + .map(|(_, j)| j.clone()) + .collect(); + + let failed = swaps + .iter() + .enumerate() + .filter(|(i, _)| !kept_indices.contains(i)) + .map(|(_, j)| j.clone()) + .collect(); + + ( + filtered, + failed, + mixed.components.offset, + mixed.components.outputs, + mixed.components.kernels, + ) + } else { + // Build plain outputs for each swap entry + let outputs: Vec = swaps + .iter() + .map(|s| { + Output::new( + OutputFeatures::Plain, + s.output_commit, + s.rangeproof.unwrap(), + ) + }) + .collect(); + + (swaps, Vec::new(), ZERO_KEY, outputs, Vec::new()) + }; + + let fees_paid: u64 = filtered.iter().map(|s| s.fee).sum(); + let inputs: Vec = filtered.iter().map(|s| s.input).collect(); + let output_excesses: Vec = filtered.iter().map(|s| s.excess.clone()).collect(); + + let tx = tx::async_assemble_tx( + &self.wallet, + &inputs, + &outputs, + &kernels, + self.get_fee_base(), + fees_paid, + &offset, + &output_excesses, + ) + .await?; + + let chain_tip = self.node.async_get_chain_tip().await?; + self.node.async_post_tx(&tx).await?; + + store.save_swap_tx(&SwapTx { + tx: tx.clone(), + chain_tip, + })?; + + // Update status to in process + let kernel_commit = tx.kernels().first().unwrap().excess; + for mut swap in filtered { + swap.status = SwapStatus::InProcess { kernel_commit }; + store.save_swap(&swap, true)?; + } + + // Update status of failed swaps + for mut swap in failed { + swap.status = SwapStatus::Failed; + store.save_swap(&swap, true)?; + } + + Ok(Some(Arc::new(tx))) + } } +#[async_trait] impl SwapServer for SwapServerImpl { - fn swap(&self, onion: &Onion, comsig: &ComSignature) -> Result<(), SwapError> { + async fn swap(&self, onion: &Onion, comsig: &ComSignature) -> Result<(), SwapError> { // Verify that more than 1 payload exists when there's a next server, // or that exactly 1 payload exists when this is the final server if self.server_config.next_server.is_some() && onion.enc_payloads.len() <= 1 @@ -114,7 +266,8 @@ impl SwapServer for SwapServerImpl { .map_err(|_| SwapError::InvalidComSignature)?; // Verify that commitment is unspent - let input = node::build_input(&self.node, &onion.commit) + let input = node::async_build_input(&self.node, &onion.commit) + .await .map_err(|e| SwapError::UnknownError(e.to_string()))?; let input = input.ok_or(SwapError::CoinNotFound { commit: onion.commit.clone(), @@ -144,7 +297,7 @@ impl SwapServer for SwapServerImpl { return Err(SwapError::MissingRangeproof); } - let locked = self.store.lock().unwrap(); + let locked = self.store.lock().await; locked .save_swap( @@ -153,7 +306,7 @@ impl SwapServer for SwapServerImpl { output_commit: peeled.onion.commit, rangeproof: peeled.payload.rangeproof, input, - fee: fee as u64, + fee, onion: peeled.onion, status: SwapStatus::Unprocessed, }, @@ -168,110 +321,77 @@ impl SwapServer for SwapServerImpl { Ok(()) } - fn execute_round(&self) -> Result, Box> { - let locked_store = self.store.lock().unwrap(); - let next_block_height = self.node.get_chain_height()? + 1; + async fn execute_round(&self) -> Result>, SwapError> { + let next_block_height = self.node.async_get_chain_tip().await?.0 + 1; - let spendable: Vec = locked_store + let locked_store = self.store.lock().await; + let swaps: Vec = locked_store .swaps_iter()? .unique_by(|s| s.output_commit) - .filter(|s| match s.status { - SwapStatus::Unprocessed => true, - _ => false, - }) - .filter(|s| { - node::is_spendable(&self.node, &s.input.commit, next_block_height).unwrap_or(false) - }) - .filter(|s| !node::is_unspent(&self.node, &s.output_commit).unwrap_or(true)) - .sorted_by(|a, b| a.output_commit.partial_cmp(&b.output_commit).unwrap()) .collect(); - - if spendable.len() == 0 { - return Ok(None); + let mut spendable: Vec = vec![]; + for swap in &swaps { + if self.async_is_spendable(next_block_height, &swap).await { + spendable.push(swap.clone()); + } } - let (filtered, failed, offset, outputs, kernels) = if let Some(client) = &self.next_server { - // Call next mix server - let onions = spendable.iter().map(|s| s.onion.clone()).collect(); - let (indices, mixed) = client - .mix_outputs(&onions) - .map_err(|e| SwapError::ClientError(e.to_string()))?; + self.async_execute_round(&locked_store, swaps).await + } - // Filter out failed entries - let kept_indices = HashSet::<_>::from_iter(indices.clone()); - let filtered = spendable - .iter() - .enumerate() - .filter(|(i, _)| kept_indices.contains(i)) - .map(|(_, j)| j.clone()) - .collect(); + async fn check_reorg( + &self, + tx: &Arc, + ) -> Result>, SwapError> { + let excess = tx.kernels().first().unwrap().excess; + let locked_store = self.store.lock().await; + if let Ok(swap_tx) = locked_store.get_swap_tx(&excess) { + // If kernel is in active chain, return tx + if self + .node + .async_get_kernel(&excess, Some(swap_tx.chain_tip.0), None) + .await? + .is_some() + { + return Ok(Some(tx.clone())); + } - let failed = spendable - .iter() - .enumerate() - .filter(|(i, _)| !kept_indices.contains(i)) - .map(|(_, j)| j.clone()) - .collect(); + // If transaction is still valid, rebroadcast and return tx + if node::async_is_tx_valid(&self.node, &tx).await? { + self.node.async_post_tx(&tx).await?; + return Ok(Some(tx.clone())); + } - (filtered, failed, mixed.offset, mixed.outputs, mixed.kernels) + // Collect all swaps based on tx's inputs, and execute_round with those swaps + let next_block_height = self.node.async_get_chain_tip().await?.0 + 1; + let mut swaps = Vec::new(); + for input_commit in &tx.inputs_committed() { + if let Ok(swap) = locked_store.get_swap(&input_commit) { + if self.async_is_spendable(next_block_height, &swap).await { + swaps.push(swap); + } + } + } + + self.async_execute_round(&locked_store, swaps).await } else { - // Build plain outputs for each swap entry - let outputs: Vec = spendable - .iter() - .map(|s| { - Output::new( - OutputFeatures::Plain, - s.output_commit, - s.rangeproof.unwrap(), - ) - }) - .collect(); - - (spendable, Vec::new(), ZERO_KEY, outputs, Vec::new()) - }; - - let fees_paid: u64 = filtered.iter().map(|s| s.fee).sum(); - let inputs: Vec = filtered.iter().map(|s| s.input).collect(); - let output_excesses: Vec = filtered.iter().map(|s| s.excess.clone()).collect(); - - let tx = tx::assemble_tx( - &self.wallet, - &inputs, - &outputs, - &kernels, - self.get_fee_base(), - fees_paid, - &offset, - &output_excesses, - )?; - - self.node.post_tx(&tx)?; - - // Update status to in process - let kernel_hash = tx.kernels().first().unwrap().hash(); - for mut swap in filtered { - swap.status = SwapStatus::InProcess { kernel_hash }; - locked_store.save_swap(&swap, true)?; + Err(SwapError::SwapTxNotFound(excess)) } - - // Update status of failed swaps - for mut swap in failed { - swap.status = SwapStatus::Failed; - locked_store.save_swap(&swap, true)?; - } - - Ok(Some(tx)) } } #[cfg(test)] pub mod mock { - use super::{SwapError, SwapServer}; - use crate::crypto::comsig::ComSignature; - - use grin_core::core::Transaction; - use grin_onion::onion::Onion; use std::collections::HashMap; + use std::sync::Arc; + + use async_trait::async_trait; + use grin_core::core::Transaction; + + use grin_onion::crypto::comsig::ComSignature; + use grin_onion::onion::Onion; + + use super::{SwapError, SwapServer}; pub struct MockSwapServer { errors: HashMap, @@ -289,8 +409,9 @@ pub mod mock { } } + #[async_trait] impl SwapServer for MockSwapServer { - fn swap(&self, onion: &Onion, _comsig: &ComSignature) -> Result<(), SwapError> { + async fn swap(&self, onion: &Onion, _comsig: &ComSignature) -> Result<(), SwapError> { if let Some(e) = self.errors.get(&onion) { return Err(e.clone()); } @@ -298,21 +419,33 @@ pub mod mock { Ok(()) } - fn execute_round(&self) -> Result, Box> { + async fn execute_round(&self) -> Result>, SwapError> { Ok(None) } + + async fn check_reorg( + &self, + tx: &Arc, + ) -> Result>, SwapError> { + Ok(Some(tx.clone())) + } } } #[cfg(test)] pub mod test_util { - use crate::crypto::dalek::DalekPublicKey; - use crate::crypto::secp::SecretKey; - use crate::servers::swap::SwapServerImpl; - use crate::wallet::mock::MockWallet; - use crate::{config, GrinNode, MixClient, SwapStore}; use std::sync::Arc; + use grin_onion::crypto::dalek::DalekPublicKey; + use grin_onion::crypto::secp::SecretKey; + + use crate::config; + use crate::mix_client::MixClient; + use crate::node::GrinNode; + use crate::servers::swap::SwapServerImpl; + use crate::store::SwapStore; + use crate::wallet::mock::MockWallet; + pub fn new_swapper( test_dir: &str, server_key: &SecretKey, @@ -339,23 +472,28 @@ pub mod test_util { #[cfg(test)] mod tests { - use crate::node::mock::MockGrinNode; - use crate::servers::swap::{SwapError, SwapServer}; - use crate::store::{SwapData, SwapStatus}; - use crate::tx::TxComponents; - use crate::{client, tx, MixClient}; + use std::sync::Arc; use ::function_name::named; - use grin_core::core::hash::Hashed; - use grin_core::core::{Committed, Input, Output, OutputFeatures, Transaction, Weighting}; + use grin_core::core::{ + Committed, Input, Inputs, Output, OutputFeatures, Transaction, Weighting, + }; + use secp256k1zkp::key::ZERO_KEY; + use x25519_dalek::PublicKey as xPublicKey; + use grin_onion::crypto::comsig::ComSignature; use grin_onion::crypto::secp; use grin_onion::onion::Onion; use grin_onion::test_util as onion_test_util; use grin_onion::{create_onion, new_hop, Hop}; - use secp256k1zkp::key::ZERO_KEY; - use std::sync::Arc; - use x25519_dalek::PublicKey as xPublicKey; + + use crate::mix_client::{self, MixClient}; + use crate::node::mock::MockGrinNode; + use crate::servers::mix_rpc::MixResp; + use crate::servers::swap::{SwapError, SwapServer}; + use crate::store::{SwapData, SwapStatus}; + use crate::tx; + use crate::tx::TxComponents; macro_rules! assert_error_type { ($result:expr, $error_type:pat) => { @@ -380,9 +518,9 @@ mod tests { } /// Standalone swap server to demonstrate request validation and onion unwrapping. - #[test] + #[tokio::test] #[named] - fn swap_standalone() -> Result<(), Box> { + async fn swap_standalone() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -400,7 +538,7 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - server.swap(&onion, &comsig)?; + server.swap(&onion, &comsig).await?; // Make sure entry is added to server. let expected = SwapData { @@ -418,21 +556,21 @@ mod tests { }; { - let store = server.store.lock().unwrap(); + let store = server.store.lock().await; assert_eq!(1, store.swaps_iter().unwrap().count()); assert!(store.swap_exists(&input_commit).unwrap()); assert_eq!(expected, store.get_swap(&input_commit).unwrap()); } - let tx = server.execute_round()?; + let tx = server.execute_round().await?; assert!(tx.is_some()); { // check that status was updated - let store = server.store.lock().unwrap(); + let store = server.store.lock().await; assert!(match store.get_swap(&input_commit)?.status { - SwapStatus::InProcess { kernel_hash } => - kernel_hash == tx.unwrap().kernels().first().unwrap().hash(), + SwapStatus::InProcess { kernel_commit } => + kernel_commit == tx.unwrap().kernels().first().unwrap().excess, _ => false, }); } @@ -451,9 +589,9 @@ mod tests { } /// Multi-server test to verify proper MixClient communication. - #[test] + #[tokio::test] #[named] - fn swap_multiserver() -> Result<(), Box> { + async fn swap_multiserver() -> Result<(), Box> { let test_dir = init_test!(); // Setup input @@ -486,7 +624,7 @@ mod tests { // Mock mixer let mixer_onion = onion.peel_layer(&swap_sk)?.onion; - let mut mock_mixer = client::mock::MockMixClient::new(); + let mut mock_mixer = mix_client::mock::MockMixClient::new(); let mixer_response = TxComponents { offset: ZERO_KEY, outputs: vec![Output::new( @@ -498,7 +636,10 @@ mod tests { }; mock_mixer.set_response( &vec![mixer_onion.clone()], - (vec![0 as usize], mixer_response), + MixResp { + indices: vec![0 as usize], + components: mixer_response, + }, ); let mixer: Arc = Arc::new(mock_mixer); @@ -508,9 +649,9 @@ mod tests { Some((&mixer_pk, &mixer)), node.clone(), ); - swapper.swap(&onion, &comsig)?; + swapper.swap(&onion, &comsig).await?; - let tx = swapper.execute_round()?; + let tx = swapper.execute_round().await?; assert!(tx.is_some()); // check that the transaction was posted @@ -527,9 +668,9 @@ mod tests { } /// Returns InvalidPayloadLength when too many payloads are provided. - #[test] + #[tokio::test] #[named] - fn swap_too_many_payloads() -> Result<(), Box> { + async fn swap_too_many_payloads() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -549,22 +690,19 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!(Err(SwapError::InvalidPayloadLength), result); // Make sure no entry is added to the store - assert_eq!( - 0, - server.store.lock().unwrap().swaps_iter().unwrap().count() - ); + assert_eq!(0, server.store.lock().await.swaps_iter().unwrap().count()); Ok(()) } /// Returns InvalidComSignature when ComSignature fails to verify. - #[test] + #[tokio::test] #[named] - fn swap_invalid_com_signature() -> Result<(), Box> { + async fn swap_invalid_com_signature() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -585,22 +723,19 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!(Err(SwapError::InvalidComSignature), result); // Make sure no entry is added to the store - assert_eq!( - 0, - server.store.lock().unwrap().swaps_iter().unwrap().count() - ); + assert_eq!(0, server.store.lock().await.swaps_iter().unwrap().count()); Ok(()) } /// Returns InvalidRangeProof when the rangeproof fails to verify for the commitment. - #[test] + #[tokio::test] #[named] - fn swap_invalid_rangeproof() -> Result<(), Box> { + async fn swap_invalid_rangeproof() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -620,22 +755,19 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!(Err(SwapError::InvalidRangeproof), result); // Make sure no entry is added to the store - assert_eq!( - 0, - server.store.lock().unwrap().swaps_iter().unwrap().count() - ); + assert_eq!(0, server.store.lock().await.swaps_iter().unwrap().count()); Ok(()) } /// Returns MissingRangeproof when no rangeproof is provided. - #[test] + #[tokio::test] #[named] - fn swap_missing_rangeproof() -> Result<(), Box> { + async fn swap_missing_rangeproof() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -652,22 +784,19 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!(Err(SwapError::MissingRangeproof), result); // Make sure no entry is added to the store - assert_eq!( - 0, - server.store.lock().unwrap().swaps_iter().unwrap().count() - ); + assert_eq!(0, server.store.lock().await.swaps_iter().unwrap().count()); Ok(()) } /// Returns CoinNotFound when there's no matching output in the UTXO set. - #[test] + #[tokio::test] #[named] - fn swap_utxo_missing() -> Result<(), Box> { + async fn swap_utxo_missing() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -686,7 +815,7 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new()); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!( Err(SwapError::CoinNotFound { commit: input_commit.clone() @@ -695,18 +824,15 @@ mod tests { ); // Make sure no entry is added to the store - assert_eq!( - 0, - server.store.lock().unwrap().swaps_iter().unwrap().count() - ); + assert_eq!(0, server.store.lock().await.swaps_iter().unwrap().count()); Ok(()) } /// Returns AlreadySwapped when trying to swap the same commitment multiple times. - #[test] + #[tokio::test] #[named] - fn swap_already_swapped() -> Result<(), Box> { + async fn swap_already_swapped() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -725,10 +851,10 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - server.swap(&onion, &comsig)?; + server.swap(&onion, &comsig).await?; // Call swap a second time - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!( Err(SwapError::AlreadySwapped { commit: input_commit.clone() @@ -739,10 +865,28 @@ mod tests { Ok(()) } - /// Returns PeelOnionFailure when a failure occurs trying to decrypt the onion payload. - #[test] + /// Returns SwapTxNotFound when trying to check_reorg with a transaction not found in the store. + #[tokio::test] #[named] - fn swap_peel_onion_failure() -> Result<(), Box> { + async fn swap_tx_not_found() -> Result<(), Box> { + let test_dir = init_test!(); + + let server_key = secp::random_secret(); + let node: Arc = Arc::new(MockGrinNode::new()); + let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); + let kern = tx::build_kernel(&secp::random_secret(), 1000u64)?; + let tx: Arc = + Arc::new(Transaction::new(Inputs::default(), &[], &[kern.clone()])); + let result = server.check_reorg(&tx).await; + assert_eq!(Err(SwapError::SwapTxNotFound(kern.excess())), result); + + Ok(()) + } + + /// Returns PeelOnionFailure when a failure occurs trying to decrypt the onion payload. + #[tokio::test] + #[named] + async fn swap_peel_onion_failure() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -763,7 +907,7 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert!(result.is_err()); assert_error_type!(result, SwapError::PeelOnionFailure(_)); @@ -772,9 +916,9 @@ mod tests { } /// Returns FeeTooLow when the minimum fee is not met. - #[test] + #[tokio::test] #[named] - fn swap_fee_too_low() -> Result<(), Box> { + async fn swap_fee_too_low() -> Result<(), Box> { let test_dir = init_test!(); let value: u64 = 200_000_000; @@ -793,11 +937,11 @@ mod tests { let node: Arc = Arc::new(MockGrinNode::new_with_utxos(&vec![&input_commit])); let (server, _) = super::test_util::new_swapper(&test_dir, &server_key, None, node.clone()); - let result = server.swap(&onion, &comsig); + let result = server.swap(&onion, &comsig).await; assert_eq!( Err(SwapError::FeeTooLow { minimum_fee: 12_500_000, - actual_fee: fee as u64 + actual_fee: fee as u64, }), result ); diff --git a/src/servers/swap_rpc.rs b/src/servers/swap_rpc.rs index 788e4c1..4b81183 100644 --- a/src/servers/swap_rpc.rs +++ b/src/servers/swap_rpc.rs @@ -1,22 +1,21 @@ -use crate::client::MixClient; +use std::sync::Arc; + +use futures::FutureExt; +use jsonrpc_core::{BoxFuture, Value}; +use jsonrpc_derive::rpc; +use jsonrpc_http_server::{DomainsValidation, ServerBuilder}; +use serde::{Deserialize, Serialize}; + +use grin_onion::crypto::comsig::{self, ComSignature}; +use grin_onion::onion::Onion; + use crate::config::ServerConfig; +use crate::mix_client::MixClient; use crate::node::GrinNode; use crate::servers::swap::{SwapError, SwapServer, SwapServerImpl}; use crate::store::SwapStore; use crate::wallet::Wallet; -use grin_onion::crypto::comsig::{self, ComSignature}; -use grin_onion::onion::Onion; -use grin_util::StopState; -use jsonrpc_core::Value; -use jsonrpc_derive::rpc; -use jsonrpc_http_server::jsonrpc_core::*; -use jsonrpc_http_server::*; -use serde::{Deserialize, Serialize}; -use std::sync::{Arc, Mutex}; -use std::thread::{sleep, spawn}; -use std::time::Duration; - #[derive(Serialize, Deserialize)] pub struct SwapReq { onion: Onion, @@ -27,22 +26,23 @@ pub struct SwapReq { #[rpc(server)] pub trait SwapAPI { #[rpc(name = "swap")] - fn swap(&self, swap: SwapReq) -> jsonrpc_core::Result; + fn swap(&self, swap: SwapReq) -> BoxFuture>; } #[derive(Clone)] struct RPCSwapServer { server_config: ServerConfig, - server: Arc>, + server: Arc>, } impl RPCSwapServer { /// Spin up an instance of the JSON-RPC HTTP server. - fn start_http(&self) -> jsonrpc_http_server::Server { - let mut io = IoHandler::new(); + fn start_http(&self, runtime_handle: tokio::runtime::Handle) -> jsonrpc_http_server::Server { + let mut io = jsonrpc_core::IoHandler::new(); io.extend_with(RPCSwapServer::to_delegate(self.clone())); ServerBuilder::new(io) + .event_loop_executor(runtime_handle) .cors(DomainsValidation::Disabled) .request_middleware(|request: hyper::Request| { if request.uri() == "/v1" { @@ -56,38 +56,45 @@ impl RPCSwapServer { } } -impl From for Error { +impl From for jsonrpc_core::Error { fn from(e: SwapError) -> Self { match e { - SwapError::UnknownError(_) => Error { + SwapError::UnknownError(_) => jsonrpc_core::Error { message: e.to_string(), - code: ErrorCode::InternalError, + code: jsonrpc_core::ErrorCode::InternalError, data: None, }, - _ => Error::invalid_params(e.to_string()), + _ => jsonrpc_core::Error::invalid_params(e.to_string()), } } } impl SwapAPI for RPCSwapServer { - fn swap(&self, swap: SwapReq) -> jsonrpc_core::Result { - self.server - .lock() - .unwrap() - .swap(&swap.onion, &swap.comsig)?; - Ok(Value::String("success".into())) + fn swap(&self, swap: SwapReq) -> BoxFuture> { + let server = self.server.clone(); + async move { + server.lock().await.swap(&swap.onion, &swap.comsig).await?; + Ok(Value::String("success".into())) + } + .boxed() } } /// Spin up the JSON-RPC web server pub fn listen( - server_config: ServerConfig, + rt_handle: &tokio::runtime::Handle, + server_config: &ServerConfig, next_server: Option>, wallet: Arc, node: Arc, store: SwapStore, - stop_state: Arc, -) -> std::result::Result<(), Box> { +) -> std::result::Result< + ( + Arc>, + jsonrpc_http_server::Server, + ), + Box, +> { let server = SwapServerImpl::new( server_config.clone(), next_server, @@ -95,54 +102,34 @@ pub fn listen( node.clone(), store, ); - let server = Arc::new(Mutex::new(server)); + let server = Arc::new(tokio::sync::Mutex::new(server)); let rpc_server = RPCSwapServer { server_config: server_config.clone(), server: server.clone(), }; - let http_server = rpc_server.start_http(); + let http_server = rpc_server.start_http(rt_handle.clone()); - let close_handle = http_server.close_handle(); - let round_handle = spawn(move || { - let mut secs = 0; - loop { - if stop_state.is_stopped() { - close_handle.close(); - break; - } - - sleep(Duration::from_secs(1)); - secs = (secs + 1) % server_config.interval_s; - - if secs == 0 { - let _ = server.lock().unwrap().execute_round(); - } - } - }); - - http_server.wait(); - round_handle.join().unwrap(); - - Ok(()) + Ok((server, http_server)) } #[cfg(test)] mod tests { - use crate::config::ServerConfig; - use crate::crypto::comsig::ComSignature; - use crate::crypto::secp; - use crate::servers::swap::mock::MockSwapServer; - use crate::servers::swap::{SwapError, SwapServer}; - use crate::servers::swap_rpc::{RPCSwapServer, SwapReq}; - - use grin_onion::create_onion; use std::net::TcpListener; - use std::sync::{Arc, Mutex}; + use std::sync::Arc; use hyper::{Body, Client, Request, Response}; - use tokio::runtime::Runtime; + use tokio::sync::Mutex; + + use grin_onion::create_onion; + use grin_onion::crypto::comsig::ComSignature; + use grin_onion::crypto::secp; + + use crate::config::ServerConfig; + use crate::servers::swap::{SwapError, SwapServer}; + use crate::servers::swap::mock::MockSwapServer; + use crate::servers::swap_rpc::{RPCSwapServer, SwapReq}; async fn body_to_string(req: Response) -> String { let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap(); @@ -150,15 +137,15 @@ mod tests { } /// Spin up a temporary web service, query the API, then cleanup and return response - fn make_request( - server: Arc>, + async fn async_make_request( + server: Arc>, req: String, - ) -> Result> { + runtime_handle: &tokio::runtime::Handle, + ) -> Result> { let server_config = ServerConfig { key: secp::random_secret(), interval_s: 1, addr: TcpListener::bind("127.0.0.1:0")?.local_addr()?, - socks_proxy_addr: TcpListener::bind("127.0.0.1:0")?.local_addr()?, grin_node_url: "127.0.0.1:3413".parse()?, grin_node_secret_path: None, wallet_owner_url: "127.0.0.1:3420".parse()?, @@ -173,28 +160,21 @@ mod tests { }; // Start the JSON-RPC server - let http_server = rpc_server.start_http(); + let http_server = rpc_server.start_http(runtime_handle.clone()); let uri = format!("http://{}/v1", server_config.addr); - let threaded_rt = Runtime::new()?; - let do_request = async move { - let request = Request::post(uri) - .header("Content-Type", "application/json") - .body(Body::from(req)) - .unwrap(); + let request = Request::post(uri) + .header("Content-Type", "application/json") + .body(Body::from(req)) + .unwrap(); - Client::new().request(request).await - }; + let response = Client::new().request(request).await?; - let response = threaded_rt.block_on(do_request)?; - let response_str: String = threaded_rt.block_on(body_to_string(response)); - - // Wait for shutdown - threaded_rt.shutdown_background(); + let response_str: String = body_to_string(response).await; // Execute one round - server.lock().unwrap().execute_round()?; + server.lock().await.execute_round().await?; // Stop the server http_server.close(); @@ -206,7 +186,10 @@ mod tests { /// Demonstrates a successful swap response #[test] - fn swap_success() -> Result<(), Box> { + fn swap_success() -> Result<(), Box> { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; let commitment = secp::commit(1234, &secp::random_secret())?; let onion = create_onion(&commitment, &vec![])?; let comsig = ComSignature::sign(1234, &secp::random_secret(), &onion.serialize()?)?; @@ -221,7 +204,8 @@ mod tests { "{{\"jsonrpc\": \"2.0\", \"method\": \"swap\", \"params\": [{}], \"id\": \"1\"}}", serde_json::json!(swap) ); - let response = make_request(server, req)?; + let rt_handle = rt.handle().clone(); + let response = rt.block_on(async_make_request(server, req, &rt_handle))?; let expected = "{\"jsonrpc\":\"2.0\",\"result\":\"success\",\"id\":\"1\"}\n"; assert_eq!(response, expected); @@ -229,7 +213,10 @@ mod tests { } #[test] - fn swap_bad_request() -> Result<(), Box> { + fn swap_bad_request() -> Result<(), Box> { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; let server: Arc> = Arc::new(Mutex::new(MockSwapServer::new())); let params = "{ \"param\": \"Not a valid Swap request\" }"; @@ -237,7 +224,8 @@ mod tests { "{{\"jsonrpc\": \"2.0\", \"method\": \"swap\", \"params\": [{}], \"id\": \"1\"}}", params ); - let response = make_request(server, req)?; + let rt_handle = rt.handle().clone(); + let response = rt.block_on(async_make_request(server, req, &rt_handle))?; let expected = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params: missing field `onion`.\"},\"id\":\"1\"}\n"; assert_eq!(response, expected); Ok(()) @@ -245,7 +233,11 @@ mod tests { /// Returns "Commitment not found" when there's no matching output in the UTXO set. #[test] - fn swap_utxo_missing() -> Result<(), Box> { + fn swap_utxo_missing() -> Result<(), Box> { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; + let commitment = secp::commit(1234, &secp::random_secret())?; let onion = create_onion(&commitment, &vec![])?; let comsig = ComSignature::sign(1234, &secp::random_secret(), &onion.serialize()?)?; @@ -267,7 +259,8 @@ mod tests { "{{\"jsonrpc\": \"2.0\", \"method\": \"swap\", \"params\": [{}], \"id\": \"1\"}}", serde_json::json!(swap) ); - let response = make_request(server, req)?; + let rt_handle = rt.handle().clone(); + let response = rt.block_on(async_make_request(server, req, &rt_handle))?; let expected = format!( "{{\"jsonrpc\":\"2.0\",\"error\":{{\"code\":-32602,\"message\":\"Output {:?} does not exist, or is already spent.\"}},\"id\":\"1\"}}\n", commitment diff --git a/src/store.rs b/src/store.rs index 2122cfc..dd7a19e 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,9 +1,5 @@ +use grin_core::core::{Input, Transaction}; use grin_core::core::hash::Hash; -use grin_onion::crypto::secp::{self, Commitment, RangeProof, SecretKey}; -use grin_onion::onion::Onion; -use grin_onion::util::{read_optional, write_optional}; - -use grin_core::core::Input; use grin_core::ser::{ self, DeserializationMode, ProtocolVersion, Readable, Reader, Writeable, Writer, }; @@ -11,18 +7,30 @@ use grin_store::{self as store, Store}; use grin_util::ToHex; use thiserror::Error; +use grin_onion::crypto::secp::{self, Commitment, RangeProof, SecretKey}; +use grin_onion::onion::Onion; +use grin_onion::util::{read_optional, write_optional}; + const DB_NAME: &str = "swap"; const STORE_SUBPATH: &str = "swaps"; -const CURRENT_VERSION: u8 = 0; +const CURRENT_SWAP_VERSION: u8 = 0; const SWAP_PREFIX: u8 = b'S'; +const CURRENT_TX_VERSION: u8 = 0; +const TX_PREFIX: u8 = b'T'; + /// Swap statuses #[derive(Clone, Debug, PartialEq)] pub enum SwapStatus { Unprocessed, - InProcess { kernel_hash: Hash }, - Completed { kernel_hash: Hash, block_hash: Hash }, + InProcess { + kernel_commit: Commitment, + }, + Completed { + kernel_commit: Commitment, + block_hash: Hash, + }, Failed, } @@ -32,16 +40,16 @@ impl Writeable for SwapStatus { SwapStatus::Unprocessed => { writer.write_u8(0)?; } - SwapStatus::InProcess { kernel_hash } => { + SwapStatus::InProcess { kernel_commit } => { writer.write_u8(1)?; - kernel_hash.write(writer)?; + kernel_commit.write(writer)?; } SwapStatus::Completed { - kernel_hash, + kernel_commit, block_hash, } => { writer.write_u8(2)?; - kernel_hash.write(writer)?; + kernel_commit.write(writer)?; block_hash.write(writer)?; } SwapStatus::Failed => { @@ -58,14 +66,14 @@ impl Readable for SwapStatus { let status = match reader.read_u8()? { 0 => SwapStatus::Unprocessed, 1 => { - let kernel_hash = Hash::read(reader)?; - SwapStatus::InProcess { kernel_hash } + let kernel_commit = Commitment::read(reader)?; + SwapStatus::InProcess { kernel_commit } } 2 => { - let kernel_hash = Hash::read(reader)?; + let kernel_commit = Commitment::read(reader)?; let block_hash = Hash::read(reader)?; SwapStatus::Completed { - kernel_hash, + kernel_commit, block_hash, } } @@ -99,7 +107,7 @@ pub struct SwapData { impl Writeable for SwapData { fn write(&self, writer: &mut W) -> Result<(), ser::Error> { - writer.write_u8(CURRENT_VERSION)?; + writer.write_u8(CURRENT_SWAP_VERSION)?; writer.write_fixed_bytes(&self.excess)?; writer.write_fixed_bytes(&self.output_commit)?; write_optional(writer, &self.rangeproof)?; @@ -115,7 +123,7 @@ impl Writeable for SwapData { impl Readable for SwapData { fn read(reader: &mut R) -> Result { let version = reader.read_u8()?; - if version != CURRENT_VERSION { + if version != CURRENT_SWAP_VERSION { return Err(ser::Error::UnsupportedProtocolVersion); } @@ -138,6 +146,41 @@ impl Readable for SwapData { } } +/// A transaction created as part of a swap round. +#[derive(Clone, Debug, PartialEq)] +pub struct SwapTx { + pub tx: Transaction, + pub chain_tip: (u64, Hash), + // TODO: Include status +} + +impl Writeable for SwapTx { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + writer.write_u8(CURRENT_TX_VERSION)?; + self.tx.write(writer)?; + writer.write_u64(self.chain_tip.0)?; + self.chain_tip.1.write(writer)?; + Ok(()) + } +} + +impl Readable for SwapTx { + fn read(reader: &mut R) -> Result { + let version = reader.read_u8()?; + if version != CURRENT_TX_VERSION { + return Err(ser::Error::UnsupportedProtocolVersion); + } + + let tx = Transaction::read(reader)?; + let height = reader.read_u64()?; + let block_hash = Hash::read(reader)?; + Ok(SwapTx { + tx, + chain_tip: (height, block_hash), + }) + } +} + /// Storage facility for swap data. pub struct SwapStore { db: Store, @@ -148,6 +191,8 @@ pub struct SwapStore { pub enum StoreError { #[error("Swap entry already exists for '{0:?}'")] AlreadyExists(Commitment), + #[error("Entry does not exist for '{0:?}'")] + NotFound(Commitment), #[error("Error occurred while attempting to open db: {0}")] OpenError(store::lmdb::Error), #[error("Serialization error occurred: {0}")] @@ -193,7 +238,7 @@ impl SwapStore { /// Reads a single value by key fn read + Copy, V: Readable>(&self, prefix: u8, k: K) -> Result { - store::option_to_not_found(self.db.get_ser(&store::to_key(prefix, k)[..], None), || { + store::option_to_not_found(self.db.get_ser(&store::to_key(prefix, k), None), || { format!("{}:{}", prefix, k.to_hex()) }) .map_err(StoreError::ReadError) @@ -236,22 +281,42 @@ impl SwapStore { } /// Reads a swap from the database - #[allow(dead_code)] pub fn get_swap(&self, input_commit: &Commitment) -> Result { self.read(SWAP_PREFIX, input_commit) } + + /// Saves a swap transaction to the database + pub fn save_swap_tx(&self, s: &SwapTx) -> Result<(), StoreError> { + let data = ser::ser_vec(&s, ProtocolVersion::local())?; + self.write( + TX_PREFIX, + &s.tx.kernels().first().unwrap().excess, + &data, + true, + ) + .map_err(StoreError::WriteError)?; + + Ok(()) + } + + /// Reads a swap tx from the database + pub fn get_swap_tx(&self, kernel_excess: &Commitment) -> Result { + self.read(TX_PREFIX, kernel_excess) + } } #[cfg(test)] mod tests { - use crate::store::{SwapData, SwapStatus, SwapStore}; - use crate::StoreError; + use std::cmp::Ordering; + use grin_core::core::{Input, OutputFeatures}; use grin_core::global::{self, ChainTypes}; + use rand::RngCore; + use grin_onion::crypto::secp; use grin_onion::test_util as onion_test_util; - use rand::RngCore; - use std::cmp::Ordering; + + use crate::store::{StoreError, SwapData, SwapStatus, SwapStore}; fn new_store(test_name: &str) -> SwapStore { global::set_local_chain_type(ChainTypes::AutomatedTesting); @@ -278,11 +343,11 @@ mod tests { SwapStatus::Unprocessed } else if s == 1 { SwapStatus::InProcess { - kernel_hash: onion_test_util::rand_hash(), + kernel_commit: onion_test_util::rand_commit(), } } else { SwapStatus::Completed { - kernel_hash: onion_test_util::rand_hash(), + kernel_commit: onion_test_util::rand_commit(), block_hash: onion_test_util::rand_hash(), } }; @@ -330,7 +395,7 @@ mod tests { assert!(store.swap_exists(&swap.input.commit)?); swap.status = SwapStatus::InProcess { - kernel_hash: onion_test_util::rand_hash(), + kernel_commit: onion_test_util::rand_commit(), }; let result = store.save_swap(&swap, false); assert_eq!( diff --git a/src/tor.rs b/src/tor.rs index dfbcb72..2fb7337 100644 --- a/src/tor.rs +++ b/src/tor.rs @@ -1,83 +1,199 @@ -use crate::config::{self, ServerConfig}; +use std::sync::Arc; -use grin_core::global; -use grin_wallet_impls::tor::config as tor_config; -use grin_wallet_impls::tor::process::TorProcess; -use std::collections::HashMap; +use arti_client::config::TorClientConfigBuilder; +use arti_client::{TorClient, TorClientConfig}; +use arti_hyper::ArtiHttpConnector; +use curve25519_dalek::digest::Digest; +use ed25519_dalek::hazmat::ExpandedSecretKey; +use futures::task::SpawnExt; +use sha2::Sha512; use thiserror::Error; +use tls_api::{TlsConnector as TlsConnectorTrait, TlsConnectorBuilder}; +use tls_api_native_tls::TlsConnector; +use tor_hscrypto::pk::{HsIdKey, HsIdKeypair}; +use tor_hsrproxy::config::{ + Encapsulation, ProxyAction, ProxyConfigBuilder, ProxyPattern, ProxyRule, TargetAddr, +}; +use tor_hsrproxy::OnionServiceReverseProxy; +use tor_hsservice::config::OnionServiceConfigBuilder; +use tor_hsservice::{ + HsIdKeypairSpecifier, HsIdPublicKeySpecifier, HsNickname, RunningOnionService, +}; +use tor_keymgr::key_specifier_derive::internal; +use tor_keymgr::{ArtiNativeKeystore, KeyMgrBuilder, KeystoreSelector}; +use tor_llcrypto::pk::ed25519::ExpandedKeypair; +use tor_rtcompat::Runtime; + +use secp256k1zkp::SecretKey; + +use crate::config::ServerConfig; /// Tor error types #[derive(Error, Debug)] pub enum TorError { #[error("Error generating config: {0:?}")] - ConfigError(String), + ConfigError(grin_wallet_impls::Error), #[error("Error starting process: {0:?}")] ProcessError(grin_wallet_impls::tor::process::Error), } -pub fn init_tor_listener(server_config: &ServerConfig) -> Result { - println!("Initializing tor listener"); +pub struct TorService { + tor_client: Option>, + hidden_services: Vec>, +} - let mut tor_dir = config::get_grin_path(&global::get_chain_type()); - tor_dir.push("tor/listener"); +impl TorService { + /// Builds a hyper::Client with an ArtiHttpConnector over the TorClient. + /// The returned Client makes HTTP requests through the TorClient directly, eliminating the need for a socks proxy. + pub fn new_hyper_client( + &self, + ) -> hyper::Client, hyper::Body> { + let tls_connector = TlsConnector::builder().unwrap().build().unwrap(); + let tor_connector = ArtiHttpConnector::new(self.tor_client.clone().unwrap(), tls_connector); - let mut torrc_dir = tor_dir.clone(); - torrc_dir.push("torrc"); + hyper::Client::builder().build::<_, hyper::Body>(tor_connector) + } - tor_config::output_tor_listener_config( - tor_dir.to_str().unwrap(), - server_config.addr.to_string().as_str(), - &vec![server_config.key.clone()], - HashMap::new(), - HashMap::new(), - ) - .map_err(|e| TorError::ConfigError(e.to_string()))?; + pub fn stop(&mut self) { + self.tor_client = None; + self.hidden_services.clear(); + } +} - // Start TOR process - let mut process = TorProcess::new(); - process - .torrc_path(torrc_dir.to_str().unwrap()) - .working_dir(tor_dir.to_str().unwrap()) - .timeout(20) - .completion_percent(100) - .launch() - .map_err(TorError::ProcessError)?; +pub async fn async_init_tor( + runtime: R, + data_dir: &str, + server_config: &ServerConfig, +) -> Result, TorError> +where + R: Runtime, +{ + warn!("Initializing TOR"); - println!( + let state_dir = format!("{}/tor/state", &data_dir); + let cache_dir = format!("{}/tor/cache", &data_dir); + let hs_nickname = HsNickname::new("listener".to_string()).unwrap(); + + let mut client_config_builder = + TorClientConfigBuilder::from_directories(state_dir.clone(), cache_dir.clone()); + client_config_builder + .address_filter() + .allow_onion_addrs(true); + let client_config = client_config_builder.build().unwrap(); + + add_key_to_store(&client_config, &state_dir, &server_config.key, &hs_nickname)?; + let tor_client = TorClient::with_runtime(runtime) + .config(client_config) + .create_bootstrapped() + .await + .unwrap(); + + let service = + async_launch_hidden_service(hs_nickname.clone(), &tor_client, &server_config).await?; + let tor_instance = TorService { + tor_client: Some(tor_client), + hidden_services: vec![service], + }; + Ok(tor_instance) +} + +async fn async_launch_hidden_service( + hs_nickname: HsNickname, + tor_client: &TorClient, + server_config: &ServerConfig, +) -> Result, TorError> +where + R: Runtime, +{ + let svc_cfg = OnionServiceConfigBuilder::default() + .nickname(hs_nickname.clone()) + .build() + .unwrap(); + + let (service, request_stream) = tor_client.launch_onion_service(svc_cfg).unwrap(); + + let proxy_rule = ProxyRule::new( + ProxyPattern::one_port(80).unwrap(), + ProxyAction::Forward(Encapsulation::Simple, TargetAddr::Inet(server_config.addr)), + ); + let mut proxy_cfg_builder = ProxyConfigBuilder::default(); + proxy_cfg_builder.set_proxy_ports(vec![proxy_rule]); + let proxy = OnionServiceReverseProxy::new(proxy_cfg_builder.build().unwrap()); + + { + let proxy = proxy.clone(); + let runtime_clone = tor_client.runtime().clone(); + tor_client + .runtime() + .spawn(async move { + match proxy + .handle_requests(runtime_clone, hs_nickname.clone(), request_stream) + .await + { + Ok(()) => { + debug!("Onion service {} exited cleanly.", hs_nickname); + } + Err(e) => { + warn!("Onion service {} exited with an error: {}", hs_nickname, e); + } + } + }) + .unwrap(); + } + + warn!( "Server listening at http://{}.onion", server_config.onion_address().to_ov3_str() ); - Ok(process) + Ok(service) } -pub fn init_tor_sender(server_config: &ServerConfig) -> Result { - println!( - "Starting TOR Process for send at {:?}", - server_config.socks_proxy_addr +// TODO: Add proper error handling +fn add_key_to_store( + tor_config: &TorClientConfig, + state_dir: &String, + secret_key: &SecretKey, + hs_nickname: &HsNickname, +) -> Result<(), TorError> { + let key_store_dir = format!("{}/keystore", &state_dir); + let arti_store = + ArtiNativeKeystore::from_path_and_mistrust(&key_store_dir, &tor_config.fs_mistrust()) + .unwrap(); + info!("Using keystore from {key_store_dir:?}"); + + let key_manager = KeyMgrBuilder::default() + .default_store(Box::new(arti_store)) + .build() + .map_err(|_| internal!("failed to build keymgr")) + .unwrap(); + + let expanded_sk = ExpandedSecretKey::from_bytes( + Sha512::default() + .chain_update(secret_key) + .finalize() + .as_ref(), ); - let mut tor_dir = config::get_grin_path(&global::get_chain_type()); - tor_dir.push("tor/sender"); + let mut sk_bytes = [0_u8; 64]; + sk_bytes[0..32].copy_from_slice(&expanded_sk.scalar.to_bytes()); + sk_bytes[32..64].copy_from_slice(&expanded_sk.hash_prefix); + let expanded_kp = ExpandedKeypair::from_secret_key_bytes(sk_bytes).unwrap(); - let mut torrc_dir = tor_dir.clone(); - torrc_dir.push("torrc"); + key_manager + .insert( + HsIdKey::from(expanded_kp.public().clone()), + &HsIdPublicKeySpecifier::new(hs_nickname.clone()), + KeystoreSelector::Default, + ) + .unwrap(); - tor_config::output_tor_sender_config( - tor_dir.to_str().unwrap(), - &server_config.socks_proxy_addr.to_string(), - HashMap::new(), - HashMap::new(), - ) - .map_err(|e| TorError::ConfigError(e.to_string()))?; + key_manager + .insert( + HsIdKeypair::from(expanded_kp), + &HsIdKeypairSpecifier::new(hs_nickname.clone()), + KeystoreSelector::Default, + ) + .unwrap(); - // Start TOR process - let mut tor_process = TorProcess::new(); - tor_process - .torrc_path(torrc_dir.to_str().unwrap()) - .working_dir(tor_dir.to_str().unwrap()) - .timeout(20) - .completion_percent(100) - .launch() - .map_err(TorError::ProcessError)?; - Ok(tor_process) + Ok(()) } diff --git a/src/tx.rs b/src/tx.rs index 73ca7fd..4e11a5f 100644 --- a/src/tx.rs +++ b/src/tx.rs @@ -1,10 +1,10 @@ -use crate::crypto::secp; use crate::wallet::Wallet; use grin_core::core::{ FeeFields, Input, Inputs, KernelFeatures, Output, Transaction, TransactionBody, TxKernel, }; use grin_keychain::BlindingFactor; +use grin_onion::crypto::secp; use secp256k1zkp::{ContextFlag, Secp256k1, SecretKey}; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -43,7 +43,7 @@ pub struct TxComponents { } /// Builds and verifies the finalized swap 'Transaction' using the provided components. -pub fn assemble_tx( +pub async fn async_assemble_tx( wallet: &Arc, inputs: &Vec, outputs: &Vec, @@ -57,7 +57,7 @@ pub fn assemble_tx( let min_kernel_fee = TransactionBody::weight_by_iok(inputs.len() as u64, outputs.len() as u64, 1) * fee_base; - let components = add_kernel_and_collect_fees( + let components = async_add_kernel_and_collect_fees( &wallet, &outputs, &kernels, @@ -66,7 +66,8 @@ pub fn assemble_tx( fees_paid, &prev_offset, &output_excesses, - )?; + ) + .await?; // assemble the transaction let tx = Transaction::new( @@ -79,7 +80,7 @@ pub fn assemble_tx( } /// Adds a kernel and output to a collection of transaction components to consume fees and offset excesses. -pub fn assemble_components( +pub async fn async_assemble_components( wallet: &Arc, components: &TxComponents, output_excesses: &Vec, @@ -89,7 +90,7 @@ pub fn assemble_components( // calculate minimum fee required for the kernel let min_kernel_fee = TransactionBody::weight_by_iok(0, 0, 1) * fee_base; - add_kernel_and_collect_fees( + async_add_kernel_and_collect_fees( &wallet, &components.outputs, &components.kernels, @@ -99,9 +100,10 @@ pub fn assemble_components( &components.offset, &output_excesses, ) + .await } -fn add_kernel_and_collect_fees( +async fn async_add_kernel_and_collect_fees( wallet: &Arc, outputs: &Vec, kernels: &Vec, @@ -128,7 +130,10 @@ fn add_kernel_and_collect_fees( let amount = fees_paid - (min_kernel_fee + fee_to_collect); kernel_fee -= amount; - let wallet_output = wallet.build_output(amount).map_err(TxError::WalletError)?; + let wallet_output = wallet + .async_build_output(amount) + .await + .map_err(TxError::WalletError)?; txn_outputs.push(wallet_output.1); let output_excess = SecretKey::from_slice(&secp, &wallet_output.0.as_ref()) @@ -202,11 +207,12 @@ fn add_kernel_and_collect_fees( /// /// ```rust /// use secp256k1zkp::key::SecretKey; -/// use crate::crypto::secp; +/// use secp256k1zkp::rand::thread_rng; +/// use grin_onion::crypto::secp; /// -/// let secret_key = SecretKey::new(&mut secp::rand::thread_rng()); +/// let secret_key = secp::random_secret(); /// let fee = 10; // 10 nanogrin -/// let kernel = build_kernel(&secret_key, fee); +/// let kernel = mwixnet::tx::build_kernel(&secret_key, fee); /// ``` pub fn build_kernel(excess: &SecretKey, fee: u64) -> Result { let mut kernel = TxKernel::with_features(KernelFeatures::Plain { diff --git a/src/wallet.rs b/src/wallet.rs index af3b9bb..3e63535 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -1,36 +1,34 @@ -use crate::crypto::secp; +use std::net::SocketAddr; -use grin_api::client; -use grin_api::json_rpc::{build_request, Request, Response}; +use async_trait::async_trait; use grin_core::core::Output; use grin_core::libtx::secp_ser; use grin_keychain::BlindingFactor; use grin_util::{ToHex, ZeroingString}; -use grin_wallet_api::{EncryptedRequest, EncryptedResponse, JsonId, Token}; -use secp256k1zkp::{PublicKey, Secp256k1, SecretKey}; +use grin_wallet_api::Token; use serde::{Deserialize, Serialize}; use serde_json::json; -use std::net::SocketAddr; use thiserror::Error; +use grin_onion::crypto::secp; +use secp256k1zkp::{PublicKey, Secp256k1, SecretKey}; + +use crate::http; + +#[async_trait] pub trait Wallet: Send + Sync { /// Builds an output for the wallet with the provided amount. - fn build_output(&self, amount: u64) -> Result<(BlindingFactor, Output), WalletError>; + async fn async_build_output( + &self, + amount: u64, + ) -> Result<(BlindingFactor, Output), WalletError>; } /// Error types for interacting with wallets #[derive(Error, Debug)] pub enum WalletError { - #[error("Error encrypting request: {0:?}")] - EncryptRequestError(grin_wallet_libwallet::Error), - #[error("Error decrypting response: {0:?}")] - DecryptResponseError(grin_wallet_libwallet::Error), - #[error("Error decoding JSON response: {0:?}")] - DecodeResponseError(serde_json::Error), - #[error("JSON-RPC API communication error: {0:?}")] - ApiCommError(grin_api::Error), - #[error("Error decoding JSON-RPC response: {0:?}")] - ResponseParseError(grin_api::json_rpc::Error), + #[error("Error communication with wallet: {0:?}")] + WalletCommError(http::HttpError), } /// HTTP (JSONRPC) implementation of the 'Wallet' trait. @@ -55,26 +53,29 @@ pub struct ECDHPubkey { impl HttpWallet { /// Calls the 'open_wallet' using the RPC API. - pub fn open_wallet( + pub async fn async_open_wallet( wallet_owner_url: &SocketAddr, wallet_owner_secret: &Option, wallet_pass: &ZeroingString, ) -> Result { - println!("Opening wallet at {}", wallet_owner_url); - let shared_key = HttpWallet::init_secure_api(&wallet_owner_url, &wallet_owner_secret)?; - + info!("Opening wallet at {}", wallet_owner_url); + let shared_key = + HttpWallet::async_init_secure_api(&wallet_owner_url, &wallet_owner_secret).await?; let open_wallet_params = json!({ "name": null, "password": wallet_pass.to_string() }); - let token: Token = HttpWallet::send_enc_request( - &wallet_owner_url, + let url = format!("http://{}{}", wallet_owner_url, ENDPOINT); + let token: Token = http::async_send_enc_request( + &url, &wallet_owner_secret, "open_wallet", &open_wallet_params, &shared_key, - )?; - println!("Connected to wallet"); + ) + .await + .map_err(WalletError::WalletCommError)?; + info!("Connected to wallet"); Ok(HttpWallet { wallet_owner_url: wallet_owner_url.clone(), @@ -84,23 +85,27 @@ impl HttpWallet { }) } - fn init_secure_api( + async fn async_init_secure_api( wallet_owner_url: &SocketAddr, wallet_owner_secret: &Option, ) -> Result { let secp = Secp256k1::new(); let ephemeral_sk = secp::random_secret(); let ephemeral_pk = PublicKey::from_secret_key(&secp, &ephemeral_sk).unwrap(); + let ephemeral_pk_bytes = ephemeral_pk.serialize_vec(&secp, true); let init_params = json!({ - "ecdh_pubkey": ephemeral_pk.serialize_vec(&secp, true).to_hex() + "ecdh_pubkey": ephemeral_pk_bytes.to_hex() }); - let response_pk: ECDHPubkey = HttpWallet::send_json_request( - &wallet_owner_url, + let url = format!("http://{}{}", wallet_owner_url, ENDPOINT); + let response_pk: ECDHPubkey = http::async_send_json_request( + &url, &wallet_owner_secret, "init_secure_api", &init_params, - )?; + ) + .await + .map_err(WalletError::WalletCommError)?; let shared_key = { let mut shared_pubkey = response_pk.ecdh_pubkey.clone(); @@ -113,59 +118,25 @@ impl HttpWallet { Ok(shared_key) } - fn send_enc_request( - wallet_owner_url: &SocketAddr, - wallet_owner_secret: &Option, + pub async fn async_perform_request( + &self, method: &str, params: &serde_json::Value, - shared_key: &SecretKey, ) -> Result { - let url = format!("http://{}{}", wallet_owner_url, ENDPOINT); - let req = json!({ - "method": method, - "params": params, - "id": JsonId::IntId(1), - "jsonrpc": "2.0", - }); - let enc_req = EncryptedRequest::from_json(&JsonId::IntId(1), &req, &shared_key) - .map_err(WalletError::EncryptRequestError)?; - let res = client::post::( - url.as_str(), - wallet_owner_secret.clone(), - &enc_req, - client::TimeOut::default(), + let url = format!("http://{}{}", self.wallet_owner_url, ENDPOINT); + http::async_send_enc_request( + &url, + &self.wallet_owner_secret, + method, + params, + &self.shared_key, ) - .map_err(WalletError::ApiCommError)?; - let decrypted = res - .decrypt(&shared_key) - .map_err(WalletError::DecryptResponseError)?; - let response: Response = - serde_json::from_value(decrypted).map_err(WalletError::DecodeResponseError)?; - let ok = response.result.unwrap().get("Ok").unwrap().clone(); - let parsed = serde_json::from_value(ok).map_err(WalletError::DecodeResponseError)?; - Ok(parsed) + .await + .map_err(WalletError::WalletCommError) } - fn send_json_request( - wallet_owner_url: &SocketAddr, - wallet_owner_secret: &Option, - method: &str, - params: &serde_json::Value, - ) -> Result { - let url = format!("http://{}{}", wallet_owner_url, ENDPOINT); - let req = build_request(method, params); - let res = - client::post::( - url.as_str(), - wallet_owner_secret.clone(), - &req, - client::TimeOut::default() - ).map_err(WalletError::ApiCommError)?; - let parsed = res - .clone() - .into_result() - .map_err(WalletError::ResponseParseError)?; - Ok(parsed) + pub fn get_token(&self) -> Token { + self.token.clone() } } @@ -179,36 +150,47 @@ pub struct OutputWithBlind { output: Output, } +#[async_trait] impl Wallet for HttpWallet { /// Builds an 'Output' for the wallet using the 'build_output' RPC API. - fn build_output(&self, amount: u64) -> Result<(BlindingFactor, Output), WalletError> { - let req_json = json!({ - "token": self.token.keychain_mask.clone().unwrap().0, + async fn async_build_output( + &self, + amount: u64, + ) -> Result<(BlindingFactor, Output), WalletError> { + let params = json!({ + "token": self.token, "features": "Plain", "amount": amount }); - let output: OutputWithBlind = HttpWallet::send_enc_request( - &self.wallet_owner_url, + + let url = format!("http://{}{}", self.wallet_owner_url, ENDPOINT); + let output: OutputWithBlind = http::async_send_enc_request( + &url, &self.wallet_owner_secret, "build_output", - &req_json, + ¶ms, &self.shared_key, - )?; + ) + .await + .map_err(WalletError::WalletCommError)?; Ok((output.blind, output.output)) } } #[cfg(test)] pub mod mock { - use super::{Wallet, WalletError}; - use crate::crypto::secp; use std::borrow::BorrowMut; + use std::sync::{Arc, Mutex}; + use async_trait::async_trait; use grin_core::core::{Output, OutputFeatures}; use grin_keychain::BlindingFactor; + + use grin_onion::crypto::secp; use secp256k1zkp::pedersen::Commitment; use secp256k1zkp::Secp256k1; - use std::sync::{Arc, Mutex}; + + use super::{Wallet, WalletError}; /// Mock implementation of the 'Wallet' trait for unit-tests. #[derive(Clone)] @@ -230,9 +212,13 @@ pub mod mock { } } + #[async_trait] impl Wallet for MockWallet { /// Builds an 'Output' for the wallet using the 'build_output' RPC API. - fn build_output(&self, amount: u64) -> Result<(BlindingFactor, Output), WalletError> { + async fn async_build_output( + &self, + amount: u64, + ) -> Result<(BlindingFactor, Output), WalletError> { let secp = Secp256k1::new(); let blind = secp::random_secret(); let commit = secp::commit(amount, &blind).unwrap(); diff --git a/tests/common/miner.rs b/tests/common/miner.rs new file mode 100644 index 0000000..11985c0 --- /dev/null +++ b/tests/common/miner.rs @@ -0,0 +1,255 @@ +// Copyright 2021 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Mining service, gets a block to mine, and based on mining configuration +//! chooses a version of the cuckoo miner to mine the block and produce a valid +//! header with its proof-of-work. Any valid mined blocks are submitted to the +//! network. + +use crate::common::types::BlockFees; +use crate::common::wallet::IntegrationGrinWallet; +use chrono::prelude::Utc; +use chrono::{DateTime, NaiveDateTime}; +use grin_chain::Chain; +use grin_core::core::hash::{Hash, Hashed}; +use grin_core::core::{Block, BlockHeader, Transaction}; +use grin_core::{consensus, global}; +use grin_keychain::Identifier; +use grin_util::Mutex; +use rand::{thread_rng, Rng}; +use std::sync::Arc; +use std::time::Duration; + +pub struct Miner { + chain: Arc, +} + +impl Miner { + // Creates a new Miner. Needs references to the chain state and its + /// storage. + pub fn new(chain: Arc) -> Miner { + Miner { chain } + } + + pub async fn async_mine_empty_blocks( + &self, + wallet: &Arc>, + num_blocks: usize, + ) { + for _ in 0..num_blocks { + self.async_mine_next_block(wallet, &vec![]).await; + } + } + + /// Builds a new block on top of the existing chain. + pub async fn async_mine_next_block( + &self, + wallet: &Arc>, + txs: &Vec, + ) { + info!("Starting test miner loop."); + + // iteration, we keep the returned derivation to provide it back when + // nothing has changed. We only want to create a new key_id for each new block. + let mut key_id = None; + + loop { + // get the latest chain state and build a block on top of it + let head = self.chain.head_header().unwrap(); + let mut latest_hash = self.chain.head().unwrap().last_block_h; + + let (mut b, block_fees) = self.async_get_block(wallet, txs, key_id.clone()).await; + let sol = self.inner_mining_loop(&mut b, &head, &mut latest_hash); + + // we found a solution, push our block through the chain processing pipeline + if sol { + info!( + "Found valid proof of work, adding block {} (prev_root {}).", + b.hash(), + b.header.prev_root, + ); + let res = self.chain.process_block(b, grin_chain::Options::MINE); + if let Err(e) = res { + error!("Error validating mined block: {:?}", e); + } else { + return; + } + key_id = None; + } else { + key_id = block_fees.key_id(); + } + } + } + + /// The inner part of mining loop for the internal miner + /// kept around mostly for automated testing purposes + fn inner_mining_loop(&self, b: &mut Block, head: &BlockHeader, latest_hash: &mut Hash) -> bool { + while head.hash() == *latest_hash { + let mut ctx = global::create_pow_context::( + head.height, + global::min_edge_bits(), + global::proofsize(), + 10, + ) + .unwrap(); + ctx.set_header_nonce(b.header.pre_pow(), None, true) + .unwrap(); + if let Ok(proofs) = ctx.find_cycles() { + b.header.pow.proof = proofs[0].clone(); + let proof_diff = b.header.pow.to_difficulty(b.header.height); + if proof_diff >= (b.header.total_difficulty() - head.total_difficulty()) { + return true; + } + } + + b.header.pow.nonce += 1; + *latest_hash = self.chain.head().unwrap().last_block_h; + } + + false + } + + // Ensure a block suitable for mining is built and returned + // If a wallet listener URL is not provided the reward will be "burnt" + // Warning: This call does not return until/unless a new block can be built + async fn async_get_block( + &self, + wallet: &Arc>, + txs: &Vec, + key_id: Option, + ) -> (Block, BlockFees) { + let wallet_retry_interval = 5; + // get the latest chain state and build a block on top of it + let mut result = self.async_build_block(wallet, txs, key_id.clone()).await; + while let Err(e) = result { + println!("Error: {:?}", &e); + let mut new_key_id = key_id.to_owned(); + match e { + grin_servers::common::types::Error::Chain(c) => match c { + grin_chain::Error::DuplicateCommitment(_) => { + debug!( + "Duplicate commit for potential coinbase detected. Trying next derivation." + ); + // use the next available key to generate a different coinbase commitment + new_key_id = None; + } + _ => { + error!("Chain Error: {}", c); + } + }, + grin_servers::common::types::Error::WalletComm(_) => { + error!( + "Error building new block: Can't connect to wallet listener; will retry" + ); + async_std::task::sleep(Duration::from_secs(wallet_retry_interval)).await; + } + ae => { + warn!("Error building new block: {:?}. Retrying.", ae); + } + } + + // only wait if we are still using the same key: a different coinbase commitment is unlikely + // to have duplication + if new_key_id.is_some() { + async_std::task::sleep(Duration::from_millis(100)).await; + } + + result = self.async_build_block(wallet, txs, new_key_id).await; + } + return result.unwrap(); + } + + /// Builds a new block with the chain head as previous and eligible + /// transactions from the pool. + async fn async_build_block( + &self, + wallet: &Arc>, + txs: &Vec, + key_id: Option, + ) -> Result<(Block, BlockFees), grin_servers::common::types::Error> { + let head = self.chain.head_header()?; + + // prepare the block header timestamp + let mut now_sec = Utc::now().timestamp(); + let head_sec = head.timestamp.timestamp(); + if now_sec <= head_sec { + now_sec = head_sec + 1; + } + + // Determine the difficulty our block should be at. + // Note: do not keep the difficulty_iter in scope (it has an active batch). + let difficulty = consensus::next_difficulty(head.height + 1, self.chain.difficulty_iter()?); + + // build the coinbase and the block itself + let fees = txs.iter().map(|tx| tx.fee()).sum(); + let height = head.height + 1; + let block_fees = BlockFees { + fees, + key_id, + height, + }; + + let res = wallet.lock().async_create_coinbase(&block_fees).await?; + let output = res.output; + let kernel = res.kernel; + let block_fees = BlockFees { + key_id: res.key_id, + ..block_fees + }; + let mut b = Block::from_reward(&head, &txs, output, kernel, difficulty.difficulty)?; + + // making sure we're not spending time mining a useless block + b.validate(&head.total_kernel_offset)?; + + b.header.pow.nonce = thread_rng().gen(); + b.header.pow.secondary_scaling = difficulty.secondary_scaling; + b.header.timestamp = DateTime::::from_naive_utc_and_offset( + NaiveDateTime::from_timestamp_opt(now_sec, 0).unwrap(), + Utc, + ); + + debug!( + "Built new block with {} inputs and {} outputs, block difficulty: {}, cumulative difficulty {}", + b.inputs().len(), + b.outputs().len(), + difficulty.difficulty, + b.header.total_difficulty().to_num(), + ); + + // Now set txhashset roots and sizes on the header of the block being built. + match self.chain.set_txhashset_roots(&mut b) { + Ok(_) => Ok((b, block_fees)), + Err(e) => { + match e { + // If this is a duplicate commitment then likely trying to use + // a key that hass already been derived but not in the wallet + // for some reason, allow caller to retry. + grin_chain::Error::DuplicateCommitment(e) => { + Err(grin_servers::common::types::Error::Chain( + grin_chain::Error::DuplicateCommitment(e), + )) + } + + // Some other issue, possibly duplicate kernel + _ => { + error!("Error setting txhashset root to build a block: {:?}", e); + Err(grin_servers::common::types::Error::Chain( + grin_chain::Error::Other(format!("{:?}", e)), + )) + } + } + } + } + } +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..dc3e692 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,5 @@ +pub mod miner; +pub mod node; +pub mod server; +pub mod types; +pub mod wallet; diff --git a/tests/common/node.rs b/tests/common/node.rs new file mode 100644 index 0000000..a554920 --- /dev/null +++ b/tests/common/node.rs @@ -0,0 +1,122 @@ +extern crate grin_wallet_api as apiwallet; +extern crate grin_wallet_config as wallet_config; +extern crate grin_wallet_controller as wallet_controller; +extern crate grin_wallet_impls as wallet; +extern crate grin_wallet_libwallet as libwallet; + +use futures::channel::oneshot; + +use grin_core as core; + +use grin_p2p as p2p; +use grin_servers as servers; + +use grin_util::logger::LogEntry; +use grin_util::{Mutex, StopState}; +use std::default::Default; +use std::net::SocketAddr; + +use mwixnet::{GrinNode, HttpGrinNode}; +use std::sync::{mpsc, Arc}; +use std::thread; + +#[allow(dead_code)] +pub struct IntegrationGrinNode { + server_config: servers::ServerConfig, + stop_state: Arc, + server: Option>, +} + +impl IntegrationGrinNode { + pub fn start(&mut self) -> Arc { + let stop_state_thread = self.stop_state.clone(); + let server_config_thread = self.server_config.clone(); + + // Create a channel to communicate between threads + let (tx, rx) = mpsc::channel(); + + // Start the node in a new thread + thread::spawn(move || { + let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) = + Box::leak(Box::new(oneshot::channel::<()>())); + + servers::Server::start( + server_config_thread.clone(), + None, + move |serv: servers::Server, _: Option>| { + // Signal that the callback has been called + tx.send(serv).unwrap(); + // Do other necessary stuff here + }, + Some(stop_state_thread.clone()), + api_chan, + ) + .unwrap(); + }); + + // Wait for the signal from the node-running thread + let server = Arc::new(rx.recv().unwrap()); + self.server = Some(server.clone()); + + server + } + + pub fn stop(&self) { + self.stop_state.stop(); + } + + pub fn api_address(&self) -> SocketAddr { + self.server_config.api_http_addr.parse().unwrap() + } + + pub fn to_client(&self) -> Arc { + Arc::new(HttpGrinNode::new(&self.api_address(), &None)) + } +} + +#[allow(dead_code)] +pub struct GrinNodeManager { + // base directory for the server instance + working_dir: String, + + nodes: Vec>>, +} + +impl GrinNodeManager { + pub fn new(test_dir: &str) -> GrinNodeManager { + GrinNodeManager { + working_dir: String::from(test_dir), + nodes: vec![], + } + } + + pub fn new_node(&mut self) -> Arc> { + let server_config = servers::ServerConfig { + api_http_addr: format!("127.0.0.1:{}", 20000 + self.nodes.len()), + api_secret_path: None, + db_root: format!("{}/nodes/{}", self.working_dir, self.nodes.len()), + p2p_config: p2p::P2PConfig { + port: 13414, + seeding_type: p2p::Seeding::None, + ..p2p::P2PConfig::default() + }, + chain_type: core::global::ChainTypes::AutomatedTesting, + skip_sync_wait: Some(true), + stratum_mining_config: None, + ..Default::default() + }; + let node = Arc::new(Mutex::new(IntegrationGrinNode { + server_config, + stop_state: Arc::new(StopState::new()), + server: None, + })); + self.nodes.push(node.clone()); + node + } + + pub fn stop_all(&self) { + for node in &self.nodes { + node.lock().stop(); + } + } +} diff --git a/tests/common/server.rs b/tests/common/server.rs new file mode 100644 index 0000000..ec20f1a --- /dev/null +++ b/tests/common/server.rs @@ -0,0 +1,261 @@ +use std::iter; +use std::net::TcpListener; +use std::sync::Arc; + +use grin_core::core::Transaction; +use tor_rtcompat::PreferredRuntime; +use x25519_dalek::{PublicKey as xPublicKey, StaticSecret}; + +use grin_onion::crypto::comsig::ComSignature; +use grin_onion::crypto::dalek::DalekPublicKey; +use grin_onion::onion::Onion; +use mwixnet::mix_client::MixClientImpl; +use mwixnet::tor::TorService; +use mwixnet::{tor, SwapError, SwapServer, SwapStore}; +use secp256k1zkp::SecretKey; + +use crate::common::node::IntegrationGrinNode; +use crate::common::wallet::{GrinWalletManager, IntegrationGrinWallet}; + +pub struct IntegrationSwapServer { + server_key: SecretKey, + tor_instance: Arc>>, + swap_server: Arc>, + rpc_server: jsonrpc_http_server::Server, + _wallet: Arc>, +} + +impl IntegrationSwapServer { + pub async fn async_swap(&self, onion: &Onion, comsig: &ComSignature) -> Result<(), SwapError> { + self.swap_server.lock().await.swap(&onion, &comsig).await + } + + pub async fn async_execute_round(&self) -> Result>, SwapError> { + self.swap_server.lock().await.execute_round().await + } +} + +pub struct IntegrationMixServer { + server_key: SecretKey, + tor_instance: Arc>>, + rpc_server: jsonrpc_http_server::Server, + _wallet: Arc>, +} + +async fn async_new_swap_server( + data_dir: &str, + rt_handle: &tokio::runtime::Handle, + tor_runtime: R, + wallets: &mut GrinWalletManager, + server_key: &SecretKey, + node: &Arc>, + next_server: Option<&IntegrationMixServer>, +) -> IntegrationSwapServer +where + R: tor_rtcompat::Runtime, +{ + let wallet = wallets.async_new_wallet(&node.lock().api_address()).await; + + let server_config = mwixnet::ServerConfig { + key: server_key.clone(), + interval_s: 15, + addr: TcpListener::bind("127.0.0.1:0") + .unwrap() + .local_addr() + .unwrap(), + grin_node_url: node.lock().api_address(), + grin_node_secret_path: None, + wallet_owner_url: wallet.lock().owner_address(), + wallet_owner_secret_path: None, + prev_server: None, + next_server: match next_server { + Some(s) => Some(DalekPublicKey::from_secret(&s.server_key)), + None => None, + }, + }; + + // Open SwapStore + let store = SwapStore::new(format!("{}/db", data_dir).as_str()).unwrap(); + let tor_instance = tor::async_init_tor(tor_runtime, &data_dir, &server_config) + .await + .unwrap(); + let tor_instance = Arc::new(grin_util::Mutex::new(tor_instance)); + + let (swap_server, rpc_server) = mwixnet::swap_listen( + rt_handle, + &server_config, + match next_server { + Some(s) => Some(Arc::new(MixClientImpl::new( + server_config.clone(), + tor_instance.clone(), + DalekPublicKey::from_secret(&s.server_key), + ))), + None => None, + }, + wallet.lock().get_client(), + node.lock().to_client(), + store, + ) + .unwrap(); + + IntegrationSwapServer { + server_key: server_key.clone(), + tor_instance, + swap_server, + rpc_server, + _wallet: wallet, + } +} + +async fn async_new_mix_server( + data_dir: &str, + rt_handle: &tokio::runtime::Handle, + tor_runtime: R, + wallets: &mut GrinWalletManager, + server_key: &SecretKey, + node: &Arc>, + prev_server: DalekPublicKey, + next_server: Option<&IntegrationMixServer>, +) -> IntegrationMixServer +where + R: tor_rtcompat::Runtime, +{ + let wallet = wallets.async_new_wallet(&node.lock().api_address()).await; + let server_config = mwixnet::ServerConfig { + key: server_key.clone(), + interval_s: 15, + addr: TcpListener::bind("127.0.0.1:0") + .unwrap() + .local_addr() + .unwrap(), + grin_node_url: node.lock().api_address(), + grin_node_secret_path: None, + wallet_owner_url: wallet.lock().owner_address(), + wallet_owner_secret_path: None, + prev_server: Some(prev_server), + next_server: match next_server { + Some(s) => Some(DalekPublicKey::from_secret(&s.server_key)), + None => None, + }, + }; + + let tor_instance = tor::async_init_tor(tor_runtime, &data_dir, &server_config) + .await + .unwrap(); + let tor_instance = Arc::new(grin_util::Mutex::new(tor_instance)); + + let (_, rpc_server) = mwixnet::mix_listen( + rt_handle, + server_config.clone(), + match next_server { + Some(s) => Some(Arc::new(MixClientImpl::new( + server_config.clone(), + tor_instance.clone(), + DalekPublicKey::from_secret(&s.server_key), + ))), + None => None, + }, + wallet.lock().get_client(), + node.lock().to_client(), + ) + .unwrap(); + + IntegrationMixServer { + server_key: server_key.clone(), + tor_instance, + rpc_server, + _wallet: wallet, + } +} + +pub struct Servers { + pub swapper: IntegrationSwapServer, + + pub mixers: Vec>, +} + +impl Servers { + pub async fn async_setup( + test_dir: &str, + rt_handle: &tokio::runtime::Handle, + wallets: &mut GrinWalletManager, + node: &Arc>, + num_mixers: usize, + ) -> Servers { + // Pre-generate all server keys + let server_keys: Vec = + iter::repeat_with(|| grin_onion::crypto::secp::random_secret()) + .take(num_mixers + 1) + .collect(); + + // Setup mock tor network + let tor_runtime = PreferredRuntime::current().unwrap(); + + // Build mixers in reverse order + let mut mixers = Vec::new(); + for i in (0..num_mixers).rev() { + let mix_server = async_new_mix_server( + format!("{}/mixers/{}", test_dir, i).as_str(), + rt_handle, + tor_runtime.clone(), + wallets, + &server_keys[i + 1], + &node, + DalekPublicKey::from_secret(&server_keys[i]), + mixers.last(), + ) + .await; + println!( + "Mixer {}: server_key={}, prev_server={}, next_server={}", + i, + DalekPublicKey::from_secret(&server_keys[i + 1]).to_hex(), + DalekPublicKey::from_secret(&server_keys[i]).to_hex(), + match mixers.last() { + Some(s) => DalekPublicKey::from_secret(&s.server_key).to_hex(), + None => "NONE".to_string(), + }, + ); + mixers.push(mix_server); + } + mixers.reverse(); + + let swapper = async_new_swap_server( + format!("{}/swapper", test_dir).as_str(), + rt_handle, + tor_runtime.clone(), + wallets, + &server_keys[0], + &node, + mixers.first(), + ) + .await; + println!( + "Swapper: server_key={}", + DalekPublicKey::from_secret(&server_keys[0]).to_hex() + ); + + Servers { swapper, mixers } + } + + pub fn get_pub_keys(&self) -> Vec { + let mut pub_keys = vec![xPublicKey::from(&StaticSecret::from( + self.swapper.server_key.0.clone(), + ))]; + for mixer in &self.mixers { + pub_keys.push(xPublicKey::from(&StaticSecret::from( + mixer.server_key.0.clone(), + ))) + } + pub_keys + } + + pub fn stop_all(&mut self) { + self.swapper.rpc_server.close_handle().close(); + self.swapper.tor_instance.lock().stop(); + + self.mixers.iter_mut().for_each(|mixer| { + mixer.rpc_server.close_handle().close(); + mixer.tor_instance.lock().stop(); + }); + } +} diff --git a/tests/common/types.rs b/tests/common/types.rs new file mode 100644 index 0000000..dba05dc --- /dev/null +++ b/tests/common/types.rs @@ -0,0 +1,24 @@ +use grin_core::libtx::secp_ser; +use grin_keychain::Identifier; +use serde_derive::{Deserialize, Serialize}; + +/// Fees in block to use for coinbase amount calculation +/// (Duplicated from Grin wallet project) +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct BlockFees { + /// fees + #[serde(with = "secp_ser::string_or_u64")] + pub fees: u64, + /// height + #[serde(with = "secp_ser::string_or_u64")] + pub height: u64, + /// key id + pub key_id: Option, +} + +impl BlockFees { + /// return key id + pub fn key_id(&self) -> Option { + self.key_id.clone() + } +} diff --git a/tests/common/wallet.rs b/tests/common/wallet.rs new file mode 100644 index 0000000..642514d --- /dev/null +++ b/tests/common/wallet.rs @@ -0,0 +1,413 @@ +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::sync::Arc; +use std::thread; + +use grin_core::core::{FeeFields, Output, OutputFeatures, Transaction, TxKernel}; +use grin_core::global::ChainTypes; +use grin_core::libtx::tx_fee; +use grin_keychain::{BlindingFactor, ExtKeychain, Identifier, Keychain, SwitchCommitmentType}; +use grin_util::{Mutex, ZeroingString}; +use grin_wallet_api::Owner; +use grin_wallet_config::WalletConfig; +use grin_wallet_controller::controller; +use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient}; +use grin_wallet_libwallet::{InitTxArgs, Slate, VersionedSlate, WalletInfo, WalletInst}; +use log::error; +use serde_derive::{Deserialize, Serialize}; +use serde_json::json; +use x25519_dalek::PublicKey as xPublicKey; + +use grin_onion::crypto::comsig::ComSignature; +use grin_onion::onion::Onion; +use grin_onion::Hop; +use mwixnet::http; +use mwixnet::wallet::HttpWallet; +use secp256k1zkp::pedersen::Commitment; +use secp256k1zkp::{Secp256k1, SecretKey}; + +use crate::common::types::BlockFees; + +/// Response to build a coinbase output. +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct CbData { + /// Output + pub output: Output, + /// Kernel + pub kernel: TxKernel, + /// Key Id + pub key_id: Option, +} + +pub struct IntegrationGrinWallet { + wallet: Arc< + Mutex< + Box< + dyn WalletInst< + 'static, + DefaultLCProvider<'static, HTTPNodeClient, ExtKeychain>, + HTTPNodeClient, + ExtKeychain, + >, + >, + >, + >, + api_listen_port: u16, + owner_api: Arc< + Owner, HTTPNodeClient, ExtKeychain>, + >, + http_client: Arc, +} + +impl IntegrationGrinWallet { + pub async fn async_new_wallet( + wallet_dir: String, + api_listen_port: u16, + node_api: String, + ) -> IntegrationGrinWallet { + let node_client = HTTPNodeClient::new(&node_api, None).unwrap(); + let mut wallet = Box::new( + DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap(), + ) + as Box< + dyn WalletInst< + 'static, + DefaultLCProvider, + HTTPNodeClient, + ExtKeychain, + >, + >; + + // Wallet LifeCycle Provider provides all functions init wallet and work with seeds, etc... + let lc = wallet.lc_provider().unwrap(); + + let mut wallet_config = WalletConfig::default(); + wallet_config.check_node_api_http_addr = node_api.clone(); + wallet_config.owner_api_listen_port = Some(api_listen_port); + wallet_config.api_secret_path = None; + wallet_config.data_file_dir = wallet_dir.clone(); + + // The top level wallet directory should be set manually (in the reference implementation, + // this is provided in the WalletConfig) + let _ = lc.set_top_level_directory(&wallet_config.data_file_dir); + + lc.create_config( + &ChainTypes::AutomatedTesting, + "grin-wallet.toml", + Some(wallet_config.clone()), + None, + None, + ) + .unwrap(); + + lc.create_wallet(None, None, 12, ZeroingString::from("pass"), false) + .unwrap(); + + // Start owner API + let km = Arc::new(Mutex::new(None)); + let wallet = Arc::new(Mutex::new(wallet)); + let owner_api = Arc::new(Owner::new(wallet.clone(), None)); + + let address_str = format!("127.0.0.1:{}", api_listen_port); + let owner_addr: SocketAddr = address_str.parse().unwrap(); + let thr_wallet = wallet.clone(); + let _thread_handle = thread::spawn(move || { + controller::owner_listener( + thr_wallet, + km, + address_str.as_str(), + None, + None, + Some(true), + None, + false, + ) + .unwrap() + }); + + let http_client = Arc::new( + HttpWallet::async_open_wallet(&owner_addr, &None, &ZeroingString::from("pass")) + .await + .unwrap(), + ); + + IntegrationGrinWallet { + wallet, + api_listen_port, + owner_api, + http_client, + } + } + + pub async fn async_retrieve_summary_info(&self) -> Result { + let params = json!({ + "token": self.http_client.clone().get_token(), + "refresh_from_node": true, + "minimum_confirmations": 1 + }); + let (_, wallet_info): (bool, WalletInfo) = self + .http_client + .clone() + .async_perform_request("retrieve_summary_info", ¶ms) + .await?; + Ok(wallet_info) + } + + pub async fn async_send( + &self, + receiving_wallet: &IntegrationGrinWallet, + amount: u64, + ) -> Result { + let slate = self.async_init_send_tx(amount).await.unwrap(); + let slate = receiving_wallet.async_receive_tx(&slate).await.unwrap(); + let slate = self.async_finalize_tx(&slate).await.unwrap(); + let tx = Slate::from(slate).tx_or_err().unwrap().clone(); + Ok(tx) + } + + async fn async_init_send_tx( + &self, + amount: u64, + ) -> Result { + let args = InitTxArgs { + src_acct_name: None, + amount, + minimum_confirmations: 0, + max_outputs: 10, + num_change_outputs: 1, + selection_strategy_is_use_all: false, + ..Default::default() + }; + let params = json!({ + "token": self.http_client.clone().get_token(), + "args": args + }); + + let slate: VersionedSlate = self + .http_client + .clone() + .async_perform_request("init_send_tx", ¶ms) + .await?; + + let params = json!({ + "token": self.http_client.clone().get_token(), + "slate": &slate + }); + self.http_client + .clone() + .async_perform_request("tx_lock_outputs", ¶ms) + .await?; + + Ok(slate) + } + + pub async fn async_receive_tx( + &self, + slate: &VersionedSlate, + ) -> Result { + let params = json!([slate, null, null]); + let response = + http::async_send_json_request(&self.foreign_api(), &None, "receive_tx", ¶ms) + .await + .map_err(|e| { + let report = format!("Failed to receive tx. Is the wallet listening? {}", e); + error!("{}", report); + grin_servers::common::types::Error::WalletComm(report) + })?; + + Ok(response) + } + + async fn async_finalize_tx( + &self, + slate: &VersionedSlate, + ) -> Result { + let params = json!({ + "token": self.http_client.clone().get_token(), + "slate": slate + }); + + self.http_client + .clone() + .async_perform_request("finalize_tx", ¶ms) + .await + } + + #[allow(dead_code)] + async fn async_post_tx( + &self, + finalized_slate: &VersionedSlate, + fluff: bool, + ) -> Result { + let params = json!({ + "token": self.http_client.clone().get_token(), + "slate": finalized_slate, + "fluff": fluff + }); + + self.http_client + .clone() + .async_perform_request("post_tx", ¶ms) + .await + } + + /// Call the wallet API to create a coinbase output for the given block_fees. + /// Will retry based on default "retry forever with backoff" behavior. + pub async fn async_create_coinbase( + &self, + block_fees: &BlockFees, + ) -> Result { + let params = json!({ + "block_fees": block_fees + }); + let response = + http::async_send_json_request(&self.foreign_api(), &None, "build_coinbase", ¶ms) + .await + .map_err(|e| { + let report = format!("Failed to get coinbase. Is the wallet listening? {}", e); + error!("{}", report); + grin_servers::common::types::Error::WalletComm(report) + })?; + + Ok(response) + } + + pub fn build_onion( + &self, + commitment: &Commitment, + server_pubkeys: &Vec, + ) -> Result<(Onion, ComSignature), grin_wallet_libwallet::Error> { + let keychain = self + .wallet + .lock() + .lc_provider()? + .wallet_inst()? + .keychain(self.keychain_mask().as_ref())?; + let (_, outputs) = + self.owner_api + .retrieve_outputs(self.keychain_mask().as_ref(), false, false, None)?; + + let mut output = None; + for o in &outputs { + if o.commit == *commitment { + output = Some(o.output.clone()); + break; + } + } + + if output.is_none() { + return Err(grin_wallet_libwallet::Error::GenericError(String::from( + "output not found", + ))); + } + + let amount = output.clone().unwrap().value; + let input_blind = keychain.derive_key( + amount, + &output.clone().unwrap().key_id, + SwitchCommitmentType::Regular, + )?; + + let fee = tx_fee(1, 1, 1); + let new_amount = amount - (fee * server_pubkeys.len() as u64); + let new_output = self.owner_api.build_output( + self.keychain_mask().as_ref(), + OutputFeatures::Plain, + new_amount, + )?; + + let secp = Secp256k1::new(); + let mut blind_sum = new_output + .blind + .split(&BlindingFactor::from_secret_key(input_blind.clone()), &secp)?; + + let hops = server_pubkeys + .iter() + .enumerate() + .map(|(i, &p)| { + if (i + 1) == server_pubkeys.len() { + Hop { + server_pubkey: p.clone(), + excess: blind_sum.secret_key(&secp).unwrap(), + fee: FeeFields::from(fee as u32), + rangeproof: Some(new_output.output.proof.clone()), + } + } else { + let hop_excess = BlindingFactor::rand(&secp); + blind_sum = blind_sum.split(&hop_excess, &secp).unwrap(); + Hop { + server_pubkey: p.clone(), + excess: hop_excess.secret_key(&secp).unwrap(), + fee: FeeFields::from(fee as u32), + rangeproof: None, + } + } + }) + .collect(); + + let onion = grin_onion::create_onion(&commitment, &hops).unwrap(); + let comsig = ComSignature::sign(amount, &input_blind, &onion.serialize().unwrap()).unwrap(); + + Ok((onion, comsig)) + } + + pub fn owner_api( + &self, + ) -> Arc< + Owner, HTTPNodeClient, ExtKeychain>, + > { + self.owner_api.clone() + } + + pub fn foreign_api(&self) -> String { + format!("http://127.0.0.1:{}/v2/foreign", self.api_listen_port) + } + + pub fn owner_address(&self) -> SocketAddr { + SocketAddr::new( + IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), + self.api_listen_port, + ) + } + + pub fn keychain_mask(&self) -> Option { + self.http_client.as_ref().get_token().keychain_mask.clone() + } + + pub fn get_client(&self) -> Arc { + self.http_client.clone() + } +} + +#[allow(dead_code)] +pub struct GrinWalletManager { + // base directory for the server instance + working_dir: String, + + wallets: Vec>>, +} + +impl GrinWalletManager { + pub fn new(test_dir: &str) -> GrinWalletManager { + GrinWalletManager { + working_dir: String::from(test_dir), + wallets: vec![], + } + } + + pub async fn async_new_wallet( + &mut self, + node_api_addr: &SocketAddr, + ) -> Arc> { + let wallet_dir = format!("{}/wallets/{}", self.working_dir, self.wallets.len()); + let wallet = Arc::new(Mutex::new( + IntegrationGrinWallet::async_new_wallet( + wallet_dir, + 21000 + self.wallets.len() as u16, + format!("http://{}", node_api_addr), + ) + .await, + )); + self.wallets.push(wallet.clone()); + wallet + } +} diff --git a/tests/e2e.rs b/tests/e2e.rs new file mode 100644 index 0000000..ef7ec4d --- /dev/null +++ b/tests/e2e.rs @@ -0,0 +1,136 @@ +#[macro_use] +extern crate log; + +use std::ops::Deref; + +use function_name::named; +use grin_core::global; +use grin_util::logger::LoggingConfig; +use log::Level; + +use crate::common::miner::Miner; +use crate::common::node::GrinNodeManager; +use crate::common::server::Servers; +use crate::common::wallet::GrinWalletManager; + +mod common; + +/// Just removes all results from previous runs +fn clean_all_output(test_dir: &str) { + if let Err(e) = remove_dir_all::remove_dir_all(test_dir) { + println!("can't remove output from previous test :{}, may be ok", e); + } +} + +fn setup_test(test_name: &str) -> (GrinNodeManager, GrinWalletManager, String) { + let test_dir = format!("./target/tmp/.{}", test_name); + clean_all_output(test_dir.as_str()); + + let mut logger = LoggingConfig::default(); + logger.log_to_file = false; + logger.stdout_log_level = Level::Error; + grin_util::init_logger(Some(logger), None); + global::set_local_chain_type(global::ChainTypes::AutomatedTesting); + global::set_local_accept_fee_base(50_000_000); + global::init_global_chain_type(global::ChainTypes::AutomatedTesting); + + let nodes = GrinNodeManager::new(test_dir.as_str()); + let wallets = GrinWalletManager::new(test_dir.as_str()); + + (nodes, wallets, test_dir) +} + +#[test] +#[named] +fn integration_test() -> Result<(), Box> { + let (mut nodes, mut wallets, test_dir) = setup_test(function_name!()); + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; + + // Create node + let node1 = nodes.new_node(); + let node1_url = node1.lock().api_address(); + let node1_server = node1.lock().start(); + + // Setup swap & mix servers and their wallets + let rt_handle = rt.handle().clone(); + let mut servers = rt.block_on(Servers::async_setup( + test_dir.as_str(), + &rt_handle, + &mut wallets, + &node1, + 2usize, + )); + + rt.block_on(async { + // Setup wallet to use with miner + let mining_wallet = wallets.async_new_wallet(&node1_url).await; + + // Mine enough blocks to have spendable coins + let miner = Miner::new(node1_server.chain.clone()); + miner + .async_mine_empty_blocks(&mining_wallet, 5 + global::coinbase_maturity() as usize) + .await; + + // Setup wallets for swap users + let user1_wallet = wallets.async_new_wallet(&node1_url).await; + let user2_wallet = wallets.async_new_wallet(&node1_url).await; + + // Send from mining_wallet to user1_wallet + let tx1 = mining_wallet + .lock() + .async_send(user1_wallet.lock().deref(), 10_000_000_000) + .await + .unwrap(); + let tx2 = mining_wallet + .lock() + .async_send(user2_wallet.lock().deref(), 20_000_000_000) + .await + .unwrap(); + miner + .async_mine_next_block(&mining_wallet, &vec![tx1, tx2]) + .await; + + let user1_km = user1_wallet.lock().keychain_mask(); + let (_, outputs) = user1_wallet + .lock() + .owner_api() + .retrieve_outputs(user1_km.as_ref(), false, false, None) + .unwrap(); + assert_eq!(outputs.len(), 1); + for output in &outputs { + let (onion, comsig) = user1_wallet + .lock() + .build_onion(&output.commit, &servers.get_pub_keys()) + .unwrap(); + servers.swapper.async_swap(&onion, &comsig).await.unwrap(); + } + + let mining_wallet_info = mining_wallet + .lock() + .async_retrieve_summary_info() + .await + .unwrap(); + println!("Mining wallet: {:?}", mining_wallet_info); + let user1_wallet_info = user1_wallet + .lock() + .async_retrieve_summary_info() + .await + .unwrap(); + println!("User1 wallet: {:?}", user1_wallet_info); + let user2_wallet_info = user2_wallet + .lock() + .async_retrieve_summary_info() + .await + .unwrap(); + println!("User2 wallet: {:?}", user2_wallet_info); + + let _tx = servers.swapper.async_execute_round().await.unwrap(); + }); + + servers.stop_all(); + nodes.stop_all(); + + Ok(()) +}