diff --git a/Cargo.lock b/Cargo.lock index 59d805dd..d55628df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -42,7 +42,7 @@ dependencies = [ "i18n-embed", "i18n-embed-fl", "lazy_static", - "nom 7.1.3", + "nom", "pin-project", "rand 0.7.3", "rand 0.8.5", @@ -64,7 +64,7 @@ dependencies = [ "chacha20poly1305", "cookie-factory", "hkdf", - "nom 7.1.3", + "nom", "rand 0.8.5", "secrecy 0.8.0", "sha2 0.9.9", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -183,9 +183,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -244,25 +244,21 @@ checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" [[package]] name = "bindgen" -version = "0.56.0" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" dependencies = [ "bitflags 1.3.2", "cexpr", "clang-sys", - "clap", - "env_logger", "lazy_static", "lazycell", - "log", "peeking_take_while", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "regex", "rustc-hash", "shlex", - "which", ] [[package]] @@ -285,9 +281,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "blake2-rfc" @@ -367,9 +363,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-tools" @@ -401,9 +397,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cargo-lock" @@ -419,9 +415,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", "libc", @@ -429,11 +425,11 @@ dependencies = [ [[package]] name = "cexpr" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 5.1.3", + "nom", ] [[package]] @@ -475,18 +471,17 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits 0.2.16", "serde", - "time", "wasm-bindgen", - "winapi 0.3.9", + "windows-targets", ] [[package]] @@ -598,9 +593,9 @@ dependencies = [ [[package]] name = "croaring" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00d14ad7d8cc067d7a5c93e8563791bfec3f7182361db955530db11d94ed63c" +checksum = "aff1eea8a79ffa2a743c1322d5c3853d45699b7842197160c7c32a18c32c1866" dependencies = [ "byteorder", "croaring-sys", @@ -609,25 +604,15 @@ dependencies = [ [[package]] name = "croaring-sys" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d6a46501bb403a61e43bc7cd19977b4f9c54efd703949b00259cc61afb5a86" +checksum = "21d77e33a1d5e04573f79846692e72f2e02e0fdd942b90f023c45f146d3447db" dependencies = [ "bindgen", "cc", "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -717,7 +702,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.32", + "quote 1.0.33", "syn 1.0.109", ] @@ -765,8 +750,8 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "strsim 0.10.0", "syn 1.0.109", ] @@ -778,18 +763,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", - "quote 1.0.32", + "quote 1.0.33", "syn 1.0.109", ] [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "lock_api 0.4.10", "once_cell", "parking_lot_core 0.9.8", @@ -914,9 +899,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -981,9 +966,9 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -997,19 +982,6 @@ dependencies = [ "num-traits 0.1.43", ] -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "atty", - "humantime 2.1.0", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1018,9 +990,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -1037,17 +1009,11 @@ dependencies = [ "libc", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "find-crate" @@ -1060,9 +1026,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", @@ -1224,9 +1190,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -1254,7 +1220,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.11", + "pin-project-lite 0.2.13", "pin-utils", "slab", ] @@ -1308,9 +1274,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "git2" @@ -1334,7 +1300,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grin_api" version = "5.2.0-beta.3" -source = "git+https://github.com/mimblewimble/grin?tag=v5.2.0-beta.3#94277bba9db2e31e713f2a4cfdc37b11e46a1630" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "bytes 0.5.6", "easy-jsonrpc-mw", @@ -1366,7 +1332,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "bit-vec", "bitflags 1.3.2", @@ -1389,7 +1355,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "blake2-rfc", "byteorder", @@ -1415,7 +1381,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "blake2-rfc", "byteorder", @@ -1437,7 +1403,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "bitflags 1.3.2", "bytes 0.5.6", @@ -1459,7 +1425,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "blake2-rfc", "chrono", @@ -1492,7 +1458,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "byteorder", "croaring", @@ -1511,7 +1477,7 @@ 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" +source = "git+https://github.com/mimblewimble/grin?branch=master#5e2aa59a15c08b41fa68e9e30d0d1d3e176c2271" dependencies = [ "backtrace", "base64 0.12.3", @@ -1686,15 +1652,18 @@ dependencies = [ "blake2-rfc", "bs58", "byteorder", + "chacha20", "chrono", "curve25519-dalek 2.1.3", "ed25519-dalek", "grin_core", "grin_keychain", + "grin_secp256k1zkp", "grin_store", "grin_util", "grin_wallet_config", "grin_wallet_util", + "hmac 0.12.1", "lazy_static", "log", "num-bigint", @@ -1705,7 +1674,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_with", - "sha2 0.8.2", + "sha2 0.10.8", "strum", "strum_macros", "thiserror", @@ -1756,9 +1725,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" [[package]] name = "heck" @@ -1780,9 +1749,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hkdf" @@ -1819,7 +1788,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "fnv", "itoa 1.0.9", ] @@ -1855,12 +1824,6 @@ dependencies = [ "quick-error", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.13.10" @@ -1946,15 +1909,15 @@ dependencies = [ [[package]] name = "i18n-config" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b987084cadad6e2f2b1e6ea62c44123591a3c044793a1beabf71a8356ea768d5" +checksum = "0c9ce3c48cbc21fd5b22b9331f32b5b51f6ad85d969b99e793427332e76e7640" dependencies = [ "log", "serde", "serde_derive", "thiserror", - "toml 0.7.6", + "toml 0.8.2", "unic-langid", ] @@ -1993,24 +1956,24 @@ dependencies = [ "i18n-embed", "lazy_static", "proc-macro-error", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "strsim 0.10.0", - "syn 2.0.28", + "syn 2.0.37", "unic-langid", ] [[package]] name = "i18n-embed-impl" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a95d065e6be4499e50159172395559a388d20cf13c84c77e4a1e341786f219" +checksum = "a2a4d5bff745c9a6e1459c490059281b353a4ab0a4e1e58b3eeeaef71f97d07b" dependencies = [ "find-crate", "i18n-config", - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 1.0.109", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -2064,12 +2027,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.1", ] [[package]] @@ -2112,7 +2075,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "rustix", "windows-sys", ] @@ -2193,9 +2156,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libgit2-sys" @@ -2260,9 +2223,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "lmdb-zero" @@ -2297,9 +2260,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" dependencies = [ "serde", ] @@ -2320,7 +2283,7 @@ dependencies = [ "chrono", "flate2", "fnv", - "humantime 1.3.0", + "humantime", "libc", "log", "log-mdc", @@ -2346,9 +2309,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap" @@ -2469,9 +2432,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c624fa1b7aab6bd2aff6e9b18565cc0363b6d45cbcd7465c9ed5e3740ebf097" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "libc", - "nix 0.26.2", + "nix 0.26.4", "smallstr", "terminfo", "unicode-normalization", @@ -2522,14 +2485,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "static_assertions", ] [[package]] @@ -2538,16 +2500,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "memchr", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -2659,15 +2611,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", ] [[package]] name = "object" -version = "0.31.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2698,11 +2650,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.56" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if 1.0.0", "foreign-types", "libc", @@ -2717,9 +2669,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -2730,9 +2682,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -2903,9 +2855,9 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -2916,9 +2868,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2982,8 +2934,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", "version_check", ] @@ -2994,8 +2946,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "version_check", ] @@ -3010,9 +2962,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -3040,11 +2992,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 1.0.66", + "proc-macro2 1.0.67", ] [[package]] @@ -3239,9 +3191,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -3249,14 +3201,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3316,9 +3266,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", @@ -3328,9 +3278,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", @@ -3339,9 +3289,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "remove_dir_all" @@ -3380,7 +3330,7 @@ dependencies = [ "mime_guess", "native-tls", "percent-encoding", - "pin-project-lite 0.2.11", + "pin-project-lite 0.2.13", "rustls 0.18.1", "serde", "serde_urlencoded", @@ -3461,10 +3411,10 @@ version = "6.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "rust-embed-utils", - "syn 2.0.28", + "syn 2.0.37", "walkdir", ] @@ -3474,7 +3424,7 @@ version = "7.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" dependencies = [ - "sha2 0.10.7", + "sha2 0.10.8", "walkdir", ] @@ -3498,11 +3448,11 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", @@ -3626,7 +3576,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.10.1", "salsa20", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -3736,9 +3686,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.183" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] @@ -3755,20 +3705,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa 1.0.9", "ryu", @@ -3814,8 +3764,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ "darling", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", ] @@ -3831,18 +3781,6 @@ dependencies = [ "yaml-rust 0.4.5", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.9" @@ -3858,9 +3796,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -3882,9 +3820,9 @@ dependencies = [ [[package]] name = "shlex" -version = "0.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signal-hook-registry" @@ -3903,15 +3841,15 @@ checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg 1.1.0", ] @@ -3927,9 +3865,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" @@ -3948,12 +3886,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[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" @@ -3979,8 +3911,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ "heck", - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", ] @@ -4013,27 +3945,27 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.28" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "unicode-ident", ] [[package]] name = "sysinfo" -version = "0.29.7" +version = "0.29.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165d6d8539689e3d3bc8b98ac59541e1f21c7de7c85d60dc80e43ae0ed2113db" +checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys 0.8.4", @@ -4046,9 +3978,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if 1.0.0", "fastrand", @@ -4078,15 +4010,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "terminfo" version = "0.8.0" @@ -4095,7 +4018,7 @@ checksum = "666cd3a6681775d22b200409aad3b089c5b99fb11ecdd8a204d9d62f8148498f" dependencies = [ "dirs 4.0.0", "fnv", - "nom 7.1.3", + "nom", "phf", "phf_codegen", ] @@ -4111,22 +4034,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -4140,17 +4063,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - [[package]] name = "timer" version = "0.2.0" @@ -4162,9 +4074,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef" +checksum = "b07bb54ef1f8ff27564b08b861144d3b8d40263efe07684f64987f4c0d044e3e" dependencies = [ "displaydoc", ] @@ -4224,8 +4136,8 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", ] @@ -4301,9 +4213,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", @@ -4322,11 +4234,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", @@ -4347,7 +4259,7 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.11", + "pin-project-lite 0.2.13", "tracing-core", ] @@ -4402,9 +4314,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unic-langid" @@ -4427,9 +4339,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -4442,9 +4354,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -4463,9 +4375,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -4500,9 +4412,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -4545,9 +4457,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -4568,12 +4480,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4601,9 +4507,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", "wasm-bindgen-shared", ] @@ -4625,7 +4531,7 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote 1.0.32", + "quote 1.0.33", "wasm-bindgen-macro-support", ] @@ -4635,9 +4541,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4677,15 +4583,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "which" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -dependencies = [ - "libc", -] - [[package]] name = "winapi" version = "0.2.8" @@ -4716,9 +4613,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi 0.3.9", ] @@ -4749,9 +4646,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -4764,51 +4661,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.4" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ "memchr", ] @@ -4884,9 +4781,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6d86b468..29148b7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,16 +48,16 @@ grin_wallet_util = { path = "./util", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# 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_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../grin/core"} diff --git a/api/Cargo.toml b/api/Cargo.toml index bd95b60b..e4e0a5e5 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -36,14 +36,14 @@ grin_wallet_util = { path = "../util", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/api/src/owner.rs b/api/src/owner.rs index 3be98567..2c5215c7 100644 --- a/api/src/owner.rs +++ b/api/src/owner.rs @@ -31,6 +31,7 @@ use crate::libwallet::api_impl::{owner, owner_updater}; use crate::libwallet::contract::types::{ ContractNewArgsAPI, ContractRevokeArgsAPI, ContractSetupArgsAPI, }; +use crate::libwallet::mwmixnet::types::{MixnetReqCreationParams, SwapReq}; use crate::libwallet::{ AcctPathMapping, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping, PaymentProof, Slate, Slatepack, SlatepackAddress, @@ -829,6 +830,19 @@ where owner::contract_revoke(&mut **w, keychain_mask, &args) } + /// Create MXMixnet request + pub fn create_mwmixnet_req( + &self, + keychain_mask: Option<&SecretKey>, + params: &MixnetReqCreationParams, + slate: &Slate, + // use_test_rng: bool, + ) -> Result { + let mut w_lock = self.wallet_inst.lock(); + let w = w_lock.lc_provider()?.wallet_inst()?; + owner::create_mwmixnet_req(&mut **w, keychain_mask, params, slate) + } + /// Processes an invoice tranaction created by another party, essentially /// a `request for payment`. The incoming slate should contain a requested /// amount, an output created by the invoicer convering the amount, and diff --git a/config/Cargo.toml b/config/Cargo.toml index 38ed42a9..532cc346 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -26,12 +26,12 @@ grin_wallet_util = { path = "../util", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/controller/Cargo.toml b/controller/Cargo.toml index 8e4976af..b5121718 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -46,16 +46,16 @@ grin_wallet_config = { path = "../config", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# 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_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../../grin/core"} @@ -76,10 +76,10 @@ remove_dir_all = "0.7" # For beta release -grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_chain = { path = "../../grin/chain"} diff --git a/controller/tests/contract_srs_mwmixnet.rs b/controller/tests/contract_srs_mwmixnet.rs new file mode 100644 index 00000000..8643eb10 --- /dev/null +++ b/controller/tests/contract_srs_mwmixnet.rs @@ -0,0 +1,156 @@ +// Copyright 2022 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. + +//! Test a wallet doing contract SRS flow +// #[macro_use] +extern crate grin_wallet_controller as wallet; +extern crate grin_wallet_impls as impls; +extern crate log; + +use grin_wallet_libwallet as libwallet; + +use impls::test_framework::{self}; +use libwallet::contract::my_fee_contribution; +use libwallet::contract::types::{ContractNewArgsAPI, ContractSetupArgsAPI}; +use libwallet::mwmixnet::onion::crypto::secp; +use libwallet::mwmixnet::types::MixnetReqCreationParams; +use libwallet::{Slate, SlateState, TxLogEntryType}; +use std::sync::atomic::Ordering; +use std::thread; +use std::time::Duration; + +#[macro_use] +mod common; +use common::{clean_output_dir, create_wallets, setup}; + +/// contract SRS flow - just creating an mwmixnet tx at the moment +fn contract_srs_mwmixnet_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { + // create two wallets and mine 4 blocks in each (we want both to have balance to get a payjoin) + let (wallets, chain, stopper, mut bh) = + create_wallets(vec![vec![("default", 4)], vec![("default", 4)]], test_dir).unwrap(); + let send_wallet = wallets[0].0.clone(); + let send_mask = wallets[0].1.as_ref(); + let recv_wallet = wallets[1].0.clone(); + let recv_mask = wallets[1].1.as_ref(); + + let mut slate = Slate::blank(0, true); // this gets overriden below + + wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| { + // Send wallet inititates a standard transaction with --send=5 + let args = &mut ContractNewArgsAPI { + setup_args: ContractSetupArgsAPI { + net_change: Some(-5_000_000_000), + ..Default::default() + }, + ..Default::default() + }; + slate = api.contract_new(m, args)?; + Ok(()) + })?; + assert_eq!(slate.state, SlateState::Standard1); + + wallet::controller::owner_single_use(Some(recv_wallet.clone()), recv_mask, None, |api, m| { + // Receive wallet calls --receive=5 + let args = &mut ContractSetupArgsAPI { + net_change: Some(5_000_000_000), + ..Default::default() + }; + args.proof_args.suppress_proof = true; + slate = api.contract_sign(m, &slate, args)?; + Ok(()) + })?; + assert_eq!(slate.state, SlateState::Standard2); + + // Send wallet finalizes and posts + wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| { + let args = &mut ContractSetupArgsAPI { + ..Default::default() + }; + args.proof_args.suppress_proof = true; + slate = api.contract_sign(m, &slate, args)?; + Ok(()) + })?; + assert_eq!(slate.state, SlateState::Standard3); + + wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| { + let server_key_1 = secp::random_secret(); + let server_key_2 = secp::random_secret(); + let params = MixnetReqCreationParams { + server_keys: vec![server_key_1, server_key_2], + fee_per_hop: 50_000_000, + }; + //api.create_mwmixnet_req(send_mask, ¶ms, &slate)?; + Ok(()) + })?; + + bh += 1; + + /* + let _ = + test_framework::award_blocks_to_wallet(&chain, send_wallet.clone(), send_mask, 3, false); + bh += 3; + + // Assert changes in receive wallet + wallet::controller::owner_single_use(Some(recv_wallet.clone()), recv_mask, None, |api, m| { + let (_, wallet_info) = api.retrieve_summary_info(m, true, 1)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; + assert_eq!(wallet_info.last_confirmed_height, bh); + assert!(refreshed); + assert_eq!(txs.len(), 5); // 4 mined and 1 received + let tx_log = txs[4].clone(); + assert_eq!(tx_log.tx_type, TxLogEntryType::TxReceived); + assert_eq!(tx_log.amount_credited, 5_000_000_000); + assert_eq!(tx_log.amount_debited, 0); + assert_eq!(tx_log.num_inputs, 1); + assert_eq!(tx_log.num_outputs, 1); + let expected_fees_paid = Some(my_fee_contribution(1, 1, 1, 2)?); + assert_eq!(tx_log.fee, expected_fees_paid); + assert_eq!( + wallet_info.amount_currently_spendable, + 4 * 60_000_000_000 + 5_000_000_000 - expected_fees_paid.unwrap().fee() // we expect the balance of 4 mined blocks + 5 Grin - fees paid + ); + Ok(()) + })?; + + // Assert changes in send wallet + wallet::controller::owner_single_use(Some(send_wallet.clone()), send_mask, None, |api, m| { + let (_, wallet_info) = api.retrieve_summary_info(m, true, 1)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; + assert_eq!(wallet_info.last_confirmed_height, bh); + assert!(refreshed); + assert_eq!(txs.len() as u64, bh - 4 + 1); // send wallet didn't mine 4 blocks and made 1 tx + let tx_log = txs[txs.len() - 5].clone(); // TODO: why -5 and not -4? + assert_eq!(tx_log.tx_type, TxLogEntryType::TxSent); + assert_eq!(tx_log.amount_credited, 0); + assert_eq!(tx_log.amount_debited, 5_000_000_000); + assert_eq!(tx_log.num_inputs, 1); + assert_eq!(tx_log.num_outputs, 1); + assert_eq!(tx_log.fee, Some(my_fee_contribution(1, 1, 1, 2)?)); + Ok(()) + })?;*/ + + // let logging finish + stopper.store(false, Ordering::Relaxed); + thread::sleep(Duration::from_millis(200)); + + Ok(()) +} + +#[test] +fn wallet_contract_srs_mwmixnet_tx() -> Result<(), libwallet::Error> { + let test_dir = "test_output/contract_srs_mwmixnet_tx"; + setup(test_dir); + contract_srs_mwmixnet_tx_impl(test_dir)?; + clean_output_dir(test_dir); + Ok(()) +} diff --git a/impls/Cargo.toml b/impls/Cargo.toml index adaa6e6e..1717eb38 100644 --- a/impls/Cargo.toml +++ b/impls/Cargo.toml @@ -52,20 +52,20 @@ grin_wallet_libwallet = { path = "../libwallet", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index 379a767f..a9b97c39 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -24,11 +24,11 @@ lazy_static = "1" strum = "0.18" strum_macros = "0.18" thiserror = "1" -ed25519-dalek = "1.0.0-pre.4" +ed25519-dalek = "1.0.1" x25519-dalek = "0.6" base64 = "0.9" regex = "1.3" -sha2 = "0.8" +sha2 = "0.10.0" bs58 = "0.3" age = "0.7" curve25519-dalek = "2.1" @@ -37,6 +37,12 @@ bech32 = "0.7" byteorder = "1.3" num-bigint = "0.2" +#mwmixnet onion +chacha20 = "0.8.1" +hmac = { version = "0.12.0", features = ["std"]} + +grin_secp256k1zkp = { version = "0.7.12", features = ["bullet-proof-sizing"]} + grin_wallet_util = { path = "../util", version = "5.2.0-beta.1" } grin_wallet_config = { path = "../config", version = "5.2.0-beta.1" } @@ -49,16 +55,16 @@ grin_wallet_config = { path = "../config", version = "5.2.0-beta.1" } # For beta release -grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} -grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } -grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_core = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3"} +# grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing # grin_core = { path = "../../grin/core"} @@ -66,4 +72,8 @@ grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta. # grin_util = { path = "../../grin/util"} # grin_store = { path = "../../grin/store"} +# mw-mixnet + + + ##### diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index efdcb99f..3eaf4c5e 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -22,13 +22,18 @@ use crate::grin_core::core::{Output, OutputFeatures, Transaction}; use crate::grin_core::libtx::proof; use crate::grin_keychain::ViewKey; use crate::grin_util::secp::key::SecretKey; -use crate::grin_util::Mutex; -use crate::grin_util::ToHex; +use crate::grin_util::secp::pedersen; +use crate::grin_util::{static_secp_instance, Mutex, ToHex}; use crate::util::{OnionV3Address, OnionV3AddressError}; use crate::api_impl::owner_updater::StatusMessage; use crate::contract::types::{ContractNewArgsAPI, ContractRevokeArgsAPI, ContractSetupArgsAPI}; use crate::grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType}; +use crate::mwmixnet::onion::create_onion; +use crate::mwmixnet::types::{ + add_excess, new_hop, random_secret, ComSignature, Hop, MixnetReqCreationParams, SwapReq, +}; + use crate::internal::{keys, scan, selection, tx, updater}; use crate::slate::{PaymentInfo, Slate, SlateState}; use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, WalletInfo}; @@ -1654,3 +1659,62 @@ where let context = w.get_private_context(keychain_mask, slate.id.as_bytes())?; slate.find_index_matching_context(&keychain, &context) } + +/// Create MXMixnet request +pub fn create_mwmixnet_req<'a, T: ?Sized, C, K>( + w: &mut T, + keychain_mask: Option<&SecretKey>, + params: &MixnetReqCreationParams, + slate: &Slate, + // use_test_rng: bool, +) -> Result +where + T: WalletBackend<'a, C, K>, + C: NodeClient + 'a, + K: Keychain + 'a, +{ + let context = w.get_private_context(keychain_mask, slate.id.as_bytes())?; + + let my_keys = context.get_private_keys(); + let kernel = slate.tx_or_err()?.kernels()[0]; + + let msg = kernel.msg_to_sign()?; + + let comsig = ComSignature::sign(slate.amount, &my_keys.0, &msg.to_hex().as_bytes().to_vec())?; + + let mut hops: Vec = Vec::new(); + let mut final_commit = kernel.excess.clone(); + let mut final_blind = my_keys.0.clone(); + + for i in 0..params.server_keys.len() { + let excess = params.server_keys[i].clone(); + + let secp = secp256k1zkp::Secp256k1::with_caps(secp256k1zkp::ContextFlag::Commit); + final_blind.add_assign(&secp, &excess).unwrap(); + final_commit = add_excess(&final_commit, &excess).unwrap(); + let proof = if i == params.server_keys.len() - 1 { + let n1 = random_secret(); + let rp = secp.bullet_proof( + slate.amount - (params.fee_per_hop * params.server_keys.len() as u32) as u64, + final_blind.clone(), + n1.clone(), + n1.clone(), + None, + None, + ); + assert!(secp.verify_bullet_proof(final_commit, rp, None).is_ok()); + Some(rp) + } else { + None + }; + + let hop = new_hop(¶ms.server_keys[i], &excess, params.fee_per_hop, proof); + hops.push(hop); + } + + let onion = create_onion(&kernel.excess, &hops)?; + + Ok(SwapReq { comsig, onion }) + + //slate.find_index_matching_context(&keychain, &context) +} diff --git a/libwallet/src/error.rs b/libwallet/src/error.rs index 6c677105..e6cceb4b 100644 --- a/libwallet/src/error.rs +++ b/libwallet/src/error.rs @@ -65,6 +65,14 @@ pub enum Error { #[error("Onion V3 Address Error: {0}")] OnionV3Address(#[from] util::OnionV3AddressError), + /// Comsig error + #[error("Comsig error: {0}")] + ComSig(#[from] crate::mwmixnet::onion::crypto::comsig::ComSigError), + + /// MwMixnet Onion error + #[error("Onion error: {0}")] + Onion(#[from] crate::mwmixnet::onion::onion::OnionError), + /// Callback implementation error conversion #[error("Trait Implementation error")] CallbackImpl(&'static str), diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index e88f8ae7..de17e05f 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -51,6 +51,8 @@ mod internal; mod slate; pub mod slate_versions; pub mod slatepack; + +pub mod mwmixnet; mod types; pub use crate::error::Error; diff --git a/libwallet/src/mwmixnet/mod.rs b/libwallet/src/mwmixnet/mod.rs new file mode 100644 index 00000000..74597a32 --- /dev/null +++ b/libwallet/src/mwmixnet/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2023 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. + +//! Onion modules for mxmixnet +pub mod onion; +pub mod types; diff --git a/libwallet/src/mwmixnet/onion/crypto/comsig.rs b/libwallet/src/mwmixnet/onion/crypto/comsig.rs new file mode 100644 index 00000000..69b3d31d --- /dev/null +++ b/libwallet/src/mwmixnet/onion/crypto/comsig.rs @@ -0,0 +1,210 @@ +// Copyright 2023 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. + +//! Comsig modules for mxmixnet + +use secp256k1zkp::{self, pedersen::Commitment, ContextFlag, Secp256k1, SecretKey}; + +use blake2_rfc::blake2b::Blake2b; +use byteorder::{BigEndian, ByteOrder}; +use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; +use secp256k1zkp::rand::thread_rng; +use thiserror::Error; + +/// A generalized Schnorr signature with a pedersen commitment value & blinding factors as the keys +#[derive(Clone, Debug)] +pub struct ComSignature { + pub_nonce: Commitment, + s: SecretKey, + t: SecretKey, +} + +/// Error types for Commitment Signatures +#[derive(Error, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub enum ComSigError { + /// Invalid com sig + #[error("Commitment signature is invalid")] + InvalidSig, + /// SECP Error Wrapper + #[error("Secp256k1zkp error: {0:?}")] + Secp256k1zkp(secp256k1zkp::Error), +} + +impl From for ComSigError { + fn from(err: secp256k1zkp::Error) -> ComSigError { + ComSigError::Secp256k1zkp(err) + } +} + +impl ComSignature { + /// Create new Com signature from commit and keys + pub fn new(pub_nonce: &Commitment, s: &SecretKey, t: &SecretKey) -> ComSignature { + ComSignature { + pub_nonce: pub_nonce.to_owned(), + s: s.to_owned(), + t: t.to_owned(), + } + } + + #[allow(dead_code)] + /// Sign com signature with kernel values + pub fn sign( + amount: u64, + blind: &SecretKey, + msg: &Vec, + ) -> Result { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + + let mut amt_bytes = [0; 32]; + BigEndian::write_u64(&mut amt_bytes[24..32], amount); + let k_amt = SecretKey::from_slice(&secp, &amt_bytes)?; + + let k_1 = SecretKey::new(&secp, &mut thread_rng()); + let k_2 = SecretKey::new(&secp, &mut thread_rng()); + + let commitment = secp.commit(amount, blind.clone())?; + let nonce_commitment = secp.commit_blind(k_1.clone(), k_2.clone())?; + + let e = ComSignature::calc_challenge(&secp, &commitment, &nonce_commitment, &msg)?; + + // s = k_1 + (e * amount) + let mut s = k_amt.clone(); + s.mul_assign(&secp, &e)?; + s.add_assign(&secp, &k_1)?; + + // t = k_2 + (e * blind) + let mut t = blind.clone(); + t.mul_assign(&secp, &e)?; + t.add_assign(&secp, &k_2)?; + + Ok(ComSignature::new(&nonce_commitment, &s, &t)) + } + + #[allow(non_snake_case)] + /// Verify a com sig + pub fn verify(&self, commit: &Commitment, msg: &Vec) -> Result<(), ComSigError> { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + + let S1 = secp.commit_blind(self.s.clone(), self.t.clone())?; + + let mut Ce = commit.to_pubkey(&secp)?; + let e = ComSignature::calc_challenge(&secp, &commit, &self.pub_nonce, &msg)?; + Ce.mul_assign(&secp, &e)?; + + let commits = vec![Commitment::from_pubkey(&secp, &Ce)?, self.pub_nonce.clone()]; + let S2 = secp.commit_sum(commits, Vec::new())?; + + if S1 != S2 { + return Err(ComSigError::InvalidSig); + } + + Ok(()) + } + + fn calc_challenge( + secp: &Secp256k1, + commit: &Commitment, + nonce_commit: &Commitment, + msg: &Vec, + ) -> Result { + let mut challenge_hasher = Blake2b::new(32); + challenge_hasher.update(&commit.0); + challenge_hasher.update(&nonce_commit.0); + challenge_hasher.update(msg); + + let mut challenge = [0; 32]; + challenge.copy_from_slice(challenge_hasher.finalize().as_bytes()); + + Ok(SecretKey::from_slice(&secp, &challenge)?) + } +} + +/// Serializes a ComSignature to and from hex +pub mod comsig_serde { + use super::ComSignature; + use grin_core::ser::{self, ProtocolVersion}; + use grin_util::ToHex; + use serde::{Deserialize, Serializer}; + + /// Serializes a ComSignature as a hex string + pub fn serialize(comsig: &ComSignature, serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::Error; + let bytes = ser::ser_vec(&comsig, ProtocolVersion::local()).map_err(Error::custom)?; + serializer.serialize_str(&bytes.to_hex()) + } + + /// Creates a ComSignature from a hex string + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + let bytes = String::deserialize(deserializer) + .and_then(|string| grin_util::from_hex(&string).map_err(Error::custom))?; + let sig: ComSignature = ser::deserialize_default(&mut &bytes[..]).map_err(Error::custom)?; + Ok(sig) + } +} + +#[allow(non_snake_case)] +impl Readable for ComSignature { + fn read(reader: &mut R) -> Result { + let R = Commitment::read(reader)?; + let s = super::secp::read_secret_key(reader)?; + let t = super::secp::read_secret_key(reader)?; + Ok(ComSignature::new(&R, &s, &t)) + } +} + +impl Writeable for ComSignature { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + writer.write_fixed_bytes(self.pub_nonce.0)?; + writer.write_fixed_bytes(self.s.0)?; + writer.write_fixed_bytes(self.t.0)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::{ComSigError, ComSignature, ContextFlag, Secp256k1, SecretKey}; + + use rand::Rng; + use secp256k1zkp::rand::{thread_rng, RngCore}; + + /// Test signing and verification of ComSignatures + #[test] + fn verify_comsig() -> Result<(), ComSigError> { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + + let amount = thread_rng().next_u64(); + let blind = SecretKey::new(&secp, &mut thread_rng()); + let msg: [u8; 16] = rand::thread_rng().gen(); + let comsig = ComSignature::sign(amount, &blind, &msg.to_vec())?; + + let commit = secp.commit(amount, blind.clone())?; + assert!(comsig.verify(&commit, &msg.to_vec()).is_ok()); + + let wrong_msg: [u8; 16] = rand::thread_rng().gen(); + assert!(comsig.verify(&commit, &wrong_msg.to_vec()).is_err()); + + let wrong_commit = secp.commit(amount, SecretKey::new(&secp, &mut thread_rng()))?; + assert!(comsig.verify(&wrong_commit, &msg.to_vec()).is_err()); + + Ok(()) + } +} diff --git a/libwallet/src/mwmixnet/onion/crypto/dalek.rs b/libwallet/src/mwmixnet/onion/crypto/dalek.rs new file mode 100644 index 00000000..a8b4f588 --- /dev/null +++ b/libwallet/src/mwmixnet/onion/crypto/dalek.rs @@ -0,0 +1,293 @@ +// Copyright 2023 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. + +//! Dalek key wrapper for mwmixnet primitives + +use super::secp::SecretKey; + +use ed25519_dalek::{Keypair, PublicKey, Signature, Signer, Verifier}; +use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; +use grin_util::ToHex; +use thiserror::Error; + +/// Error types for Dalek structures and logic +#[derive(Clone, Error, Debug, PartialEq)] +pub enum DalekError { + /// Hex deser error + #[error("Hex error {0:?}")] + HexError(String), + /// Key parsing error + #[error("Failed to parse secret key")] + KeyParseError, + /// Error validating signature + #[error("Failed to verify signature")] + SigVerifyFailed, +} + +/// Encapsulates an ed25519_dalek::PublicKey and provides (de-)serialization +#[derive(Clone, Debug, PartialEq)] +pub struct DalekPublicKey(PublicKey); + +impl DalekPublicKey { + /// Convert DalekPublicKey to hex string + pub fn to_hex(&self) -> String { + self.0.to_hex() + } + + /// Convert hex string to DalekPublicKey. + pub fn from_hex(hex: &str) -> Result { + let bytes = grin_util::from_hex(hex) + .map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?; + let pk = PublicKey::from_bytes(bytes.as_ref()) + .map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?; + Ok(DalekPublicKey(pk)) + } + + /// Compute DalekPublicKey from a SecretKey + pub fn from_secret(key: &SecretKey) -> Self { + let secret = ed25519_dalek::SecretKey::from_bytes(&key.0).unwrap(); + let pk: PublicKey = (&secret).into(); + DalekPublicKey(pk) + } +} + +impl AsRef for DalekPublicKey { + fn as_ref(&self) -> &PublicKey { + &self.0 + } +} + +/// Serializes an Option to and from hex +pub mod option_dalek_pubkey_serde { + use super::DalekPublicKey; + use grin_util::ToHex; + use serde::de::Error; + use serde::{Deserialize, Deserializer, Serializer}; + + /// + pub fn serialize(pk: &Option, serializer: S) -> Result + where + S: Serializer, + { + match pk { + Some(pk) => serializer.serialize_str(&pk.0.to_hex()), + None => serializer.serialize_none(), + } + } + + /// + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + Option::::deserialize(deserializer).and_then(|res| match res { + Some(string) => DalekPublicKey::from_hex(&string) + .map_err(|e| Error::custom(e.to_string())) + .and_then(|pk: DalekPublicKey| Ok(Some(pk))), + None => Ok(None), + }) + } +} + +impl Readable for DalekPublicKey { + fn read(reader: &mut R) -> Result { + let pk = PublicKey::from_bytes(&reader.read_fixed_bytes(32)?) + .map_err(|_| ser::Error::CorruptedData)?; + Ok(DalekPublicKey(pk)) + } +} + +impl Writeable for DalekPublicKey { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + writer.write_fixed_bytes(self.0.to_bytes())?; + Ok(()) + } +} + +/// Encapsulates an ed25519_dalek::Signature and provides (de-)serialization +#[derive(Clone, Debug, PartialEq)] +pub struct DalekSignature(Signature); + +impl DalekSignature { + /// Convert hex string to DalekSignature. + pub fn from_hex(hex: &str) -> Result { + let bytes = grin_util::from_hex(hex) + .map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?; + let sig = Signature::from_bytes(bytes.as_ref()) + .map_err(|_| DalekError::HexError(format!("failed to decode {}", hex)))?; + Ok(DalekSignature(sig)) + } + + /// Verifies DalekSignature + pub fn verify(&self, pk: &DalekPublicKey, msg: &[u8]) -> Result<(), DalekError> { + pk.as_ref() + .verify(&msg, &self.0) + .map_err(|_| DalekError::SigVerifyFailed) + } +} + +impl AsRef for DalekSignature { + fn as_ref(&self) -> &Signature { + &self.0 + } +} + +/// Serializes a DalekSignature to and from hex +pub mod dalek_sig_serde { + use super::DalekSignature; + use grin_util::ToHex; + use serde::de::Error; + use serde::{Deserialize, Deserializer, Serializer}; + + /// + pub fn serialize(sig: &DalekSignature, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&sig.0.to_hex()) + } + + /// + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let str = String::deserialize(deserializer)?; + let sig = DalekSignature::from_hex(&str).map_err(|e| Error::custom(e.to_string()))?; + Ok(sig) + } +} + +/// Dalek signature sign wrapper +// TODO: This is likely duplicated throughout crate, check +pub fn sign(sk: &SecretKey, message: &[u8]) -> Result { + let secret = + ed25519_dalek::SecretKey::from_bytes(&sk.0).map_err(|_| DalekError::KeyParseError)?; + let public: PublicKey = (&secret).into(); + let keypair = Keypair { secret, public }; + let sig = keypair.sign(&message); + Ok(DalekSignature(sig)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mwmixnet::onion::test_util::rand_keypair; + use grin_core::ser::{self, ProtocolVersion}; + use grin_util::ToHex; + use rand::Rng; + use serde::{Deserialize, Serialize}; + use serde_json::Value; + + #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] + struct TestPubKeySerde { + #[serde(with = "option_dalek_pubkey_serde", default)] + pk: Option, + } + + #[test] + fn pubkey_test() -> Result<(), Box> { + // Test from_hex + let rand_pk = rand_keypair().1; + let pk_from_hex = DalekPublicKey::from_hex(rand_pk.0.to_hex().as_str()).unwrap(); + assert_eq!(rand_pk.0, pk_from_hex.0); + + // Test ser (de-)serialization + let bytes = ser::ser_vec(&rand_pk, ProtocolVersion::local()).unwrap(); + assert_eq!(bytes.len(), 32); + let pk_from_deser: DalekPublicKey = ser::deserialize_default(&mut &bytes[..]).unwrap(); + assert_eq!(rand_pk.0, pk_from_deser.0); + + // Test serde with Some(rand_pk) + let some = TestPubKeySerde { + pk: Some(rand_pk.clone()), + }; + let val = serde_json::to_value(some.clone()).unwrap(); + if let Value::Object(o) = &val { + if let Value::String(s) = o.get("pk").unwrap() { + assert_eq!(s, &rand_pk.0.to_hex()); + } else { + panic!("Invalid type"); + } + } else { + panic!("Invalid type") + } + assert_eq!(some, serde_json::from_value(val).unwrap()); + + // Test serde with empty pk field + let none = TestPubKeySerde { pk: None }; + let val = serde_json::to_value(none.clone()).unwrap(); + if let Value::Object(o) = &val { + if let Value::Null = o.get("pk").unwrap() { + // ok + } else { + panic!("Invalid type"); + } + } else { + panic!("Invalid type") + } + assert_eq!(none, serde_json::from_value(val).unwrap()); + + // Test serde with no pk field + let none2 = serde_json::from_str::("{}").unwrap(); + assert_eq!(none, none2); + + Ok(()) + } + + #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] + struct TestSigSerde { + #[serde(with = "dalek_sig_serde")] + sig: DalekSignature, + } + + #[test] + fn sig_test() -> Result<(), Box> { + // Sign a message + let (sk, pk) = rand_keypair(); + let msg: [u8; 16] = rand::thread_rng().gen(); + let sig = sign(&sk, &msg).unwrap(); + + // Verify signature + assert!(sig.verify(&pk, &msg).is_ok()); + + // Wrong message + let wrong_msg: [u8; 16] = rand::thread_rng().gen(); + assert!(sig.verify(&pk, &wrong_msg).is_err()); + + // Wrong pubkey + let wrong_pk = rand_keypair().1; + assert!(sig.verify(&wrong_pk, &msg).is_err()); + + // Test from_hex + let sig_from_hex = DalekSignature::from_hex(sig.0.to_hex().as_str()).unwrap(); + assert_eq!(sig.0, sig_from_hex.0); + + // Test serde (de-)serialization + let serde_test = TestSigSerde { sig: sig.clone() }; + let val = serde_json::to_value(serde_test.clone()).unwrap(); + if let Value::Object(o) = &val { + if let Value::String(s) = o.get("sig").unwrap() { + assert_eq!(s, &sig.0.to_hex()); + } else { + panic!("Invalid type"); + } + } else { + panic!("Invalid type") + } + assert_eq!(serde_test, serde_json::from_value(val).unwrap()); + + Ok(()) + } +} diff --git a/libwallet/src/mwmixnet/onion/crypto/mod.rs b/libwallet/src/mwmixnet/onion/crypto/mod.rs new file mode 100644 index 00000000..8ae01a97 --- /dev/null +++ b/libwallet/src/mwmixnet/onion/crypto/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2023 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. + +//! Onion and comsig modules for mxmixnet + +pub mod comsig; +pub mod dalek; +pub mod secp; diff --git a/libwallet/src/mwmixnet/onion/crypto/secp.rs b/libwallet/src/mwmixnet/onion/crypto/secp.rs new file mode 100644 index 00000000..28872ee2 --- /dev/null +++ b/libwallet/src/mwmixnet/onion/crypto/secp.rs @@ -0,0 +1,79 @@ +// Copyright 2023 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. + +//! SECP wrapper functions for onion/comsig +//! TODO: Likely redundant stuff in here, trim + +pub use secp256k1zkp::aggsig; +pub use secp256k1zkp::constants::{ + AGG_SIGNATURE_SIZE, COMPRESSED_PUBLIC_KEY_SIZE, MAX_PROOF_SIZE, PEDERSEN_COMMITMENT_SIZE, + SECRET_KEY_SIZE, +}; +pub use secp256k1zkp::ecdh::SharedSecret; +pub use secp256k1zkp::key::{PublicKey, SecretKey, ZERO_KEY}; +pub use secp256k1zkp::pedersen::{Commitment, RangeProof}; +pub use secp256k1zkp::{ContextFlag, Message, Secp256k1, Signature}; + +use grin_core::ser::{self, Reader}; +use secp256k1zkp::rand::thread_rng; + +/// Generate a random SecretKey. +pub fn random_secret() -> SecretKey { + let secp = Secp256k1::new(); + SecretKey::new(&secp, &mut thread_rng()) +} + +/// Deserialize a SecretKey from a Reader +pub fn read_secret_key(reader: &mut R) -> Result { + let buf = reader.read_fixed_bytes(SECRET_KEY_SIZE)?; + let secp = Secp256k1::with_caps(ContextFlag::None); + let pk = SecretKey::from_slice(&secp, &buf).map_err(|_| ser::Error::CorruptedData)?; + Ok(pk) +} + +/// Build a Pedersen Commitment using the provided value and blinding factor +pub fn commit(value: u64, blind: &SecretKey) -> Result { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + let commit = secp.commit(value, blind.clone())?; + Ok(commit) +} + +/// Add a blinding factor to an existing Commitment +pub fn add_excess( + commitment: &Commitment, + excess: &SecretKey, +) -> Result { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + let excess_commit: Commitment = secp.commit(0, excess.clone())?; + + let commits = vec![commitment.clone(), excess_commit.clone()]; + let sum = secp.commit_sum(commits, Vec::new())?; + Ok(sum) +} + +/// Subtracts a value (v*H) from an existing commitment +pub fn sub_value(commitment: &Commitment, value: u64) -> Result { + let secp = Secp256k1::with_caps(ContextFlag::Commit); + let neg_commit: Commitment = secp.commit(value, ZERO_KEY)?; + let sum = secp.commit_sum(vec![commitment.clone()], vec![neg_commit.clone()])?; + Ok(sum) +} + +/// Signs the message with the provided SecretKey +pub fn sign(sk: &SecretKey, msg: &Message) -> Result { + let secp = Secp256k1::with_caps(ContextFlag::Full); + let pubkey = PublicKey::from_secret_key(&secp, &sk)?; + let sig = aggsig::sign_single(&secp, &msg, &sk, None, None, None, Some(&pubkey), None)?; + Ok(sig) +} diff --git a/libwallet/src/mwmixnet/onion/mod.rs b/libwallet/src/mwmixnet/onion/mod.rs new file mode 100644 index 00000000..bcabf8ec --- /dev/null +++ b/libwallet/src/mwmixnet/onion/mod.rs @@ -0,0 +1,194 @@ +// Copyright 2023 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. + +//! Onion module definition + +pub mod crypto; +pub mod onion; +pub mod util; + +use crypto::secp::{random_secret, Commitment, SecretKey}; +use onion::{new_stream_cipher, Onion, OnionError, Payload, RawBytes}; + +use chacha20::cipher::StreamCipher; +use grin_core::core::FeeFields; +use secp256k1zkp::pedersen::RangeProof; +use x25519_dalek::PublicKey as xPublicKey; +use x25519_dalek::{SharedSecret, StaticSecret}; + +/// Onion hop struct +#[derive(Clone)] +pub struct Hop { + /// Comsig server public key + pub server_pubkey: xPublicKey, + /// Kernel excess + pub excess: SecretKey, + /// Fee + pub fee: FeeFields, + /// Rangeproof + pub rangeproof: Option, +} + +/// Crate a new hop +pub fn new_hop( + server_key: &SecretKey, + hop_excess: &SecretKey, + fee: u32, + proof: Option, +) -> Hop { + Hop { + server_pubkey: xPublicKey::from(&StaticSecret::from(server_key.0.clone())), + excess: hop_excess.clone(), + fee: FeeFields::from(fee as u32), + rangeproof: proof, + } +} + +/// Create an Onion for the Commitment, encrypting the payload for each hop +pub fn create_onion(commitment: &Commitment, hops: &Vec) -> Result { + if hops.is_empty() { + return Ok(Onion { + ephemeral_pubkey: xPublicKey::from([0u8; 32]), + commit: commitment.clone(), + enc_payloads: vec![], + }); + } + + let mut shared_secrets: Vec = Vec::new(); + let mut enc_payloads: Vec = Vec::new(); + let mut ephemeral_sk = StaticSecret::from(random_secret().0); + let onion_ephemeral_pk = xPublicKey::from(&ephemeral_sk); + for i in 0..hops.len() { + let hop = &hops[i]; + let shared_secret = ephemeral_sk.diffie_hellman(&hop.server_pubkey); + shared_secrets.push(shared_secret); + + ephemeral_sk = StaticSecret::from(random_secret().0); + let next_ephemeral_pk = if i < (hops.len() - 1) { + xPublicKey::from(&ephemeral_sk) + } else { + xPublicKey::from([0u8; 32]) + }; + + let payload = Payload { + next_ephemeral_pk, + excess: hop.excess.clone(), + fee: hop.fee.clone(), + rangeproof: hop.rangeproof.clone(), + }; + enc_payloads.push(payload.serialize()?); + } + + for i in (0..shared_secrets.len()).rev() { + let mut cipher = new_stream_cipher(&shared_secrets[i])?; + for j in i..shared_secrets.len() { + cipher.apply_keystream(&mut enc_payloads[j]); + } + } + + let onion = Onion { + ephemeral_pubkey: onion_ephemeral_pk, + commit: commitment.clone(), + enc_payloads, + }; + Ok(onion) +} + +/// Internal tests +#[allow(missing_docs)] +pub mod test_util { + use super::*; + use crypto::dalek::DalekPublicKey; + use crypto::secp; + + use grin_core::core::hash::Hash; + use grin_util::ToHex; + use rand::{thread_rng, RngCore}; + use secp256k1zkp::Secp256k1; + + pub fn rand_onion() -> Onion { + let commit = rand_commit(); + let mut hops = Vec::new(); + let k = (thread_rng().next_u64() % 5) + 1; + for i in 0..k { + let rangeproof = if i == (k - 1) { + Some(rand_proof()) + } else { + None + }; + let hop = new_hop( + &random_secret(), + &random_secret(), + thread_rng().next_u32(), + rangeproof, + ); + hops.push(hop); + } + + create_onion(&commit, &hops).unwrap() + } + + pub fn rand_commit() -> Commitment { + secp::commit(rand::thread_rng().next_u64(), &secp::random_secret()).unwrap() + } + + pub fn rand_hash() -> Hash { + Hash::from_hex(secp::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(), + None, + None, + ) + } + + pub fn proof( + value: u64, + fee: u32, + input_blind: &SecretKey, + hop_excesses: &Vec<&SecretKey>, + ) -> (Commitment, RangeProof) { + let secp = Secp256k1::new(); + + let mut blind = input_blind.clone(); + for hop_excess in hop_excesses { + blind.add_assign(&secp, &hop_excess).unwrap(); + } + + let out_value = value - (fee as u64); + + let rp = secp.bullet_proof( + out_value, + blind.clone(), + secp::random_secret(), + secp::random_secret(), + None, + None, + ); + + (secp::commit(out_value, &blind).unwrap(), rp) + } + + pub fn rand_keypair() -> (SecretKey, DalekPublicKey) { + let sk = random_secret(); + let pk = DalekPublicKey::from_secret(&sk); + (sk, pk) + } +} diff --git a/libwallet/src/mwmixnet/onion/onion.rs b/libwallet/src/mwmixnet/onion/onion.rs new file mode 100644 index 00000000..42560593 --- /dev/null +++ b/libwallet/src/mwmixnet/onion/onion.rs @@ -0,0 +1,430 @@ +// Copyright 2023 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. + +//! Onion defn for mwmixnet + +use super::crypto::secp::{self, Commitment, RangeProof, SecretKey}; +use super::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::convert::TryFrom; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::result::Result; +use thiserror::Error; +use x25519_dalek::{PublicKey as xPublicKey, SharedSecret, StaticSecret}; + +type HmacSha256 = Hmac; +/// Wrap u8 vec +pub type RawBytes = Vec; + +const CURRENT_ONION_VERSION: u8 = 0; + +/// A data packet with layers of encryption +#[derive(Clone, Debug)] +pub struct Onion { + /// The onion originator's portion of the shared secret + pub ephemeral_pubkey: xPublicKey, + /// The pedersen commitment before adjusting the excess and subtracting the fee + pub commit: Commitment, + /// The encrypted payloads which represent the layers of the onion + pub enc_payloads: Vec, +} + +impl PartialEq for Onion { + fn eq(&self, other: &Onion) -> bool { + *self.ephemeral_pubkey.as_bytes() == *other.ephemeral_pubkey.as_bytes() + && self.commit == other.commit + && self.enc_payloads == other.enc_payloads + } +} + +impl Eq for Onion {} + +impl Hash for Onion { + fn hash(&self, state: &mut H) { + state.write(self.ephemeral_pubkey.as_bytes()); + state.write(self.commit.as_ref()); + state.write_usize(self.enc_payloads.len()); + for p in &self.enc_payloads { + state.write(p.as_slice()); + } + } +} + +/// A single, decrypted/peeled layer of an Onion. +#[derive(Debug, Clone)] +pub struct Payload { + /// next ephemeral pk + pub next_ephemeral_pk: xPublicKey, + /// excess + pub excess: SecretKey, + /// fee + pub fee: FeeFields, + /// proof + pub rangeproof: Option, +} + +impl Payload { + /// Deser a payload + pub fn deserialize(bytes: &Vec) -> Result { + let payload: Payload = ser::deserialize_default(&mut &bytes[..])?; + Ok(payload) + } + + /// Serialize a payload + pub fn serialize(&self) -> Result, ser::Error> { + let mut vec = vec![]; + ser::serialize_default(&mut vec, &self)?; + Ok(vec) + } +} + +impl Readable for Payload { + fn read(reader: &mut R) -> Result { + let version = reader.read_u8()?; + if version != CURRENT_ONION_VERSION { + return Err(ser::Error::UnsupportedProtocolVersion); + } + + let next_ephemeral_pk = + xPublicKey::from(vec_to_array::<32>(&reader.read_fixed_bytes(32)?)?); + let excess = secp::read_secret_key(reader)?; + let fee = FeeFields::try_from(reader.read_u64()?).map_err(|_| ser::Error::CorruptedData)?; + let rangeproof = read_optional(reader)?; + Ok(Payload { + next_ephemeral_pk, + excess, + fee, + rangeproof, + }) + } +} + +impl Writeable for Payload { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + writer.write_u8(CURRENT_ONION_VERSION)?; + writer.write_fixed_bytes(&self.next_ephemeral_pk.as_bytes())?; + writer.write_fixed_bytes(&self.excess)?; + writer.write_u64(self.fee.into())?; + write_optional(writer, &self.rangeproof)?; + Ok(()) + } +} + +/// An onion with a layer decrypted +#[derive(Clone, Debug)] +pub struct PeeledOnion { + /// The payload from the peeled layer + pub payload: Payload, + /// The onion remaining after a layer was peeled + pub onion: Onion, +} + +impl Onion { + /// Serialize onion + pub fn serialize(&self) -> Result, ser::Error> { + let mut vec = vec![]; + ser::serialize_default(&mut vec, &self)?; + Ok(vec) + } + + /// Peel a single layer off of the Onion, returning the peeled Onion and decrypted Payload + pub fn peel_layer(&self, server_key: &SecretKey) -> Result { + let shared_secret = StaticSecret::from(server_key.0).diffie_hellman(&self.ephemeral_pubkey); + let mut cipher = new_stream_cipher(&shared_secret)?; + + let mut decrypted_bytes = self.enc_payloads[0].clone(); + cipher.apply_keystream(&mut decrypted_bytes); + let decrypted_payload = Payload::deserialize(&decrypted_bytes) + .map_err(|e| OnionError::DeserializationError(e))?; + + let enc_payloads: Vec = self + .enc_payloads + .iter() + .enumerate() + .filter(|&(i, _)| i != 0) + .map(|(_, enc_payload)| { + let mut p = enc_payload.clone(); + cipher.apply_keystream(&mut p); + p + }) + .collect(); + + let mut commitment = self.commit.clone(); + commitment = secp::add_excess(&commitment, &decrypted_payload.excess) + .map_err(|e| OnionError::CalcCommitError(e))?; + commitment = secp::sub_value(&commitment, decrypted_payload.fee.into()) + .map_err(|e| OnionError::CalcCommitError(e))?; + + let peeled_onion = Onion { + ephemeral_pubkey: decrypted_payload.next_ephemeral_pk, + commit: commitment.clone(), + enc_payloads, + }; + Ok(PeeledOnion { + payload: decrypted_payload, + onion: peeled_onion, + }) + } +} + +/// Create new stream cypher from shared secret +pub fn new_stream_cipher(shared_secret: &SharedSecret) -> Result { + let mut mu_hmac = HmacSha256::new_from_slice(b"MWIXNET")?; + mu_hmac.update(shared_secret.as_bytes()); + let mukey = mu_hmac.finalize().into_bytes(); + + let key = Key::from_slice(&mukey[0..32]); + let nonce = Nonce::from_slice(b"NONCE1234567"); + + Ok(ChaCha20::new(&key, &nonce)) +} + +impl Writeable for Onion { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + writer.write_fixed_bytes(self.ephemeral_pubkey.as_bytes())?; + writer.write_fixed_bytes(&self.commit)?; + writer.write_u64(self.enc_payloads.len() as u64)?; + for p in &self.enc_payloads { + writer.write_u64(p.len() as u64)?; + p.write(writer)?; + } + Ok(()) + } +} + +impl Readable for Onion { + fn read(reader: &mut R) -> Result { + let pubkey_bytes: [u8; 32] = vec_to_array(&reader.read_fixed_bytes(32)?)?; + let ephemeral_pubkey = xPublicKey::from(pubkey_bytes); + let commit = Commitment::read(reader)?; + let mut enc_payloads: Vec = Vec::new(); + let len = reader.read_u64()?; + for _ in 0..len { + let size = reader.read_u64()?; + let bytes = reader.read_fixed_bytes(size as usize)?; + enc_payloads.push(bytes); + } + Ok(Onion { + ephemeral_pubkey, + commit, + enc_payloads, + }) + } +} + +impl serde::ser::Serialize for Onion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + let mut state = serializer.serialize_struct("Onion", 3)?; + + state.serialize_field("pubkey", &self.ephemeral_pubkey.as_bytes().to_hex())?; + state.serialize_field("commit", &self.commit.to_hex())?; + + let hex_payloads: Vec = self.enc_payloads.iter().map(|v| v.to_hex()).collect(); + state.serialize_field("data", &hex_payloads)?; + state.end() + } +} + +impl<'de> serde::de::Deserialize<'de> for Onion { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(field_identifier, rename_all = "snake_case")] + enum Field { + Pubkey, + Commit, + Data, + } + + struct OnionVisitor; + + impl<'de> serde::de::Visitor<'de> for OnionVisitor { + type Value = Onion; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an Onion") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + let mut pubkey = None; + let mut commit = None; + let mut data = None; + + while let Some(key) = map.next_key()? { + match key { + Field::Pubkey => { + let val: String = map.next_value()?; + let vec = + grin_util::from_hex(&val).map_err(serde::de::Error::custom)?; + pubkey = + Some(xPublicKey::from(vec_to_array::<32>(&vec).map_err( + |_| serde::de::Error::custom("Invalid length pubkey"), + )?)); + } + Field::Commit => { + let val: String = map.next_value()?; + let vec = + grin_util::from_hex(&val).map_err(serde::de::Error::custom)?; + commit = Some(Commitment::from_vec(vec)); + } + Field::Data => { + let val: Vec = map.next_value()?; + let mut vec: Vec> = Vec::new(); + for hex in val { + vec.push( + grin_util::from_hex(&hex).map_err(serde::de::Error::custom)?, + ); + } + data = Some(vec); + } + } + } + + Ok(Onion { + ephemeral_pubkey: pubkey.unwrap(), + commit: commit.unwrap(), + enc_payloads: data.unwrap(), + }) + } + } + + const FIELDS: &[&str] = &["pubkey", "commit", "data"]; + deserializer.deserialize_struct("Onion", &FIELDS, OnionVisitor) + } +} + +/// Error types for creating and peeling Onions +#[derive(Clone, Error, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub enum OnionError { + /// Invalid Key Length + #[error("Invalid key length for MAC initialization")] + InvalidKeyLength, + /// Serialization error + #[error("Serialization error occurred: {0:?}")] + SerializationError(ser::Error), + /// Deserialization error + #[error("Deserialization error occurred: {0:?}")] + DeserializationError(ser::Error), + /// Error calculating blinding factor + #[error("Error calculating blinding factor: {0:?}")] + CalcBlindError(secp256k1zkp::Error), + /// Error calculating ephemeral key + #[error("Error calculating ephemeral pubkey: {0:?}")] + CalcPubKeyError(secp256k1zkp::Error), + /// Error calculating commitment + #[error("Error calculating commitment: {0:?}")] + CalcCommitError(secp256k1zkp::Error), +} + +impl From for OnionError { + fn from(_err: InvalidLength) -> OnionError { + OnionError::InvalidKeyLength + } +} + +impl From for OnionError { + fn from(err: ser::Error) -> OnionError { + OnionError::SerializationError(err) + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::mwmixnet::onion::crypto::secp::random_secret; + use crate::mwmixnet::onion::{new_hop, Hop}; + + use grin_core::core::FeeFields; + + /// Test end-to-end Onion creation and unwrapping logic. + #[test] + fn onion() { + let total_fee: u64 = 10; + let fee_per_hop: u32 = 2; + let in_value: u64 = 1000; + let out_value: u64 = in_value - total_fee; + let blind = random_secret(); + let commitment = secp::commit(in_value, &blind).unwrap(); + + let mut hops: Vec = Vec::new(); + let mut keys: Vec = Vec::new(); + let mut final_commit = secp::commit(out_value, &blind).unwrap(); + let mut final_blind = blind.clone(); + for i in 0..5 { + keys.push(random_secret()); + + let excess = random_secret(); + + let secp = secp256k1zkp::Secp256k1::with_caps(secp256k1zkp::ContextFlag::Commit); + final_blind.add_assign(&secp, &excess).unwrap(); + final_commit = secp::add_excess(&final_commit, &excess).unwrap(); + let proof = if i == 4 { + let n1 = random_secret(); + let rp = secp.bullet_proof( + out_value, + final_blind.clone(), + n1.clone(), + n1.clone(), + None, + None, + ); + assert!(secp.verify_bullet_proof(final_commit, rp, None).is_ok()); + Some(rp) + } else { + None + }; + + let hop = new_hop(&keys[i], &excess, fee_per_hop, proof); + hops.push(hop); + } + + let mut onion_packet = crate::mwmixnet::onion::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), + rangeproof: None, + }; + for i in 0..5 { + let peeled = onion_packet.peel_layer(&keys[i]).unwrap(); + payload = peeled.payload; + onion_packet = peeled.onion; + } + + 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)); + } +} diff --git a/libwallet/src/mwmixnet/onion/util.rs b/libwallet/src/mwmixnet/onion/util.rs new file mode 100644 index 00000000..31495dd9 --- /dev/null +++ b/libwallet/src/mwmixnet/onion/util.rs @@ -0,0 +1,185 @@ +// Copyright 2023 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. + +//! Util fns for mwmixnet +//! TODO: possibly redundant, check or move elsewhere + +use grin_core::ser::{self, Readable, Reader, Writeable, Writer}; +use std::convert::TryInto; + +/// Writes an optional value as '1' + value if Some, or '0' if None +/// +/// This function is used to serialize an optional value into a Writer. If the option +/// contains Some value, it writes '1' followed by the serialized value. If the option +/// is None, it just writes '0'. +/// +/// # Arguments +/// +/// * `writer` - A Writer instance where the data will be written. +/// * `o` - The Optional value that will be written. +/// +/// # Returns +/// +/// * If successful, returns Ok with nothing. +/// * If an error occurs during writing, returns Err wrapping the error. +/// +/// # Example +/// +/// ``` +/// use grin_wallet_libwallet::mwmixnet::onion::util::write_optional; +/// let mut writer:Vec = vec![]; +/// let optional_value: Option = Some(10); +/// //write_optional(&mut writer, &optional_value); +/// ``` +pub fn write_optional( + writer: &mut W, + o: &Option, +) -> Result<(), ser::Error> { + match &o { + Some(o) => { + writer.write_u8(1)?; + o.write(writer)?; + } + None => writer.write_u8(0)?, + }; + Ok(()) +} + +/// Reads an optional value as '1' + value if Some, or '0' if None +/// +/// This function is used to deserialize an optional value from a Reader. If the first byte +/// read is '0', it returns None. If the first byte is '1', it reads the next value and +/// returns Some(value). +/// +/// # Arguments +/// +/// * `reader` - A Reader instance from where the data will be read. +/// +/// # Returns +/// +/// * If successful, returns Ok wrapping an optional value. If the first byte read was '0', +/// returns None. If it was '1', returns Some(value). +/// * If an error occurs during reading, returns Err wrapping the error. +/// +/// # Example +/// +/// ``` +/// use grin_wallet_libwallet::mwmixnet::onion::util::read_optional; +/// use grin_core::ser::{BinReader, ProtocolVersion, DeserializationMode}; +/// 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(); +/// assert_eq!(optional_value, Some(10)); +/// ``` +pub fn read_optional(reader: &mut R) -> Result, ser::Error> { + let o = if reader.read_u8()? == 0 { + None + } else { + Some(O::read(reader)?) + }; + Ok(o) +} + +/// Convert a vector to an array of size `S`. +/// +/// # Arguments +/// +/// * `vec` - The input vector. +/// +/// # Returns +/// +/// * If successful, returns an `Ok` wrapping an array of size `S` containing +/// the first `S` bytes of `vec`. +/// * If `vec` is smaller than `S`, returns an `Err` indicating a count error. +/// +/// # Example +/// +/// ``` +/// use grin_wallet_libwallet::mwmixnet::onion::util::vec_to_array; +/// let v = vec![0, 1, 2, 3, 4, 5]; +/// let a = 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> { + if vec.len() < S { + return Err(ser::Error::CountError); + } + let arr: [u8; S] = vec[0..S].try_into().unwrap(); + Ok(arr) +} + +#[cfg(test)] +mod tests { + use super::*; + use grin_core::ser::{BinReader, BinWriter, DeserializationMode, ProtocolVersion}; + + #[test] + fn test_write_optional() { + // Test with Some value + let mut buf: Vec = vec![]; + let val: Option = Some(10); + write_optional(&mut BinWriter::default(&mut buf), &val).unwrap(); + assert_eq!(buf, &[1, 0, 0, 0, 10]); // 1 for Some, then 10 as a little-endian u32 + + // Test with None value + buf.clear(); + let val: Option = None; + write_optional(&mut BinWriter::default(&mut buf), &val).unwrap(); + assert_eq!(buf, &[0]); // 0 for None + } + + #[test] + fn test_read_optional() { + // Test with Some value + let mut buf: &[u8] = &[1, 0, 0, 0, 10]; // 1 for Some, then 10 as a little-endian u32 + let val: Option = read_optional(&mut BinReader::new( + &mut buf, + ProtocolVersion::local(), + DeserializationMode::default(), + )) + .unwrap(); + assert_eq!(val, Some(10)); + + // Test with None value + buf = &[0]; // 0 for None + let val: Option = read_optional(&mut BinReader::new( + &mut buf, + ProtocolVersion::local(), + DeserializationMode::default(), + )) + .unwrap(); + assert_eq!(val, None); + } + + #[test] + fn test_vec_to_array_success() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let a = vec_to_array::<4>(&v).unwrap(); + assert_eq!(a, [1, 2, 3, 4]); + } + + #[test] + fn test_vec_to_array_too_small() { + let v = vec![1, 2, 3]; + let res = vec_to_array::<4>(&v); + assert!(res.is_err()); + } + + #[test] + fn test_vec_to_array_empty() { + let v = vec![]; + let res = vec_to_array::<4>(&v); + assert!(res.is_err()); + } +} diff --git a/libwallet/src/mwmixnet/types.rs b/libwallet/src/mwmixnet/types.rs new file mode 100644 index 00000000..7e62ed88 --- /dev/null +++ b/libwallet/src/mwmixnet/types.rs @@ -0,0 +1,42 @@ +// Copyright 2022 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. + +//! Types related to mwmixnet requests required by rest of lib crate apis +//! Should rexport all needed types here + +pub use super::onion::crypto::comsig::{self, ComSignature}; +pub use super::onion::crypto::secp::{add_excess, random_secret}; +pub use super::onion::onion::Onion; +pub use super::onion::{new_hop, Hop}; +use crate::grin_util::secp::key::SecretKey; +use serde::{Deserialize, Serialize}; + +/// A Swap request +#[derive(Serialize, Deserialize)] +pub struct SwapReq { + /// Com signature + #[serde(with = "comsig::comsig_serde")] + pub comsig: ComSignature, + /// Onion + pub onion: Onion, +} + +/// MWMixnetRequest Creation Params + +pub struct MixnetReqCreationParams { + /// List of all the server keys + pub server_keys: Vec, + /// Fees per hop + pub fee_per_hop: u32, +} diff --git a/libwallet/src/slatepack/armor.rs b/libwallet/src/slatepack/armor.rs index 12a0ced2..f3555491 100644 --- a/libwallet/src/slatepack/armor.rs +++ b/libwallet/src/slatepack/armor.rs @@ -189,10 +189,10 @@ fn format_slatepack(slatepack: &str) -> Result { // Returns the first four bytes of a double sha256 hash of some bytes fn generate_check(payload: &[u8]) -> Result, Error> { let mut first_hash = Sha256::new(); - first_hash.input(payload); + first_hash.update(payload); let mut second_hash = Sha256::new(); - second_hash.input(first_hash.result()); - let checksum = second_hash.result(); + second_hash.update(first_hash.finalize()); + let checksum = second_hash.finalize(); let check_bytes: Vec = checksum[0..4].to_vec(); Ok(check_bytes) } diff --git a/libwallet/src/slatepack/types.rs b/libwallet/src/slatepack/types.rs index 90c20031..fe08c933 100644 --- a/libwallet/src/slatepack/types.rs +++ b/libwallet/src/slatepack/types.rs @@ -190,8 +190,8 @@ impl Slatepack { let mut b = [0u8; 32]; b.copy_from_slice(&dec_key.as_bytes()[0..32]); let mut hasher = Sha512::new(); - hasher.input(b); - let result = hasher.result(); + hasher.update(b); + let result = hasher.finalize(); b.copy_from_slice(&result[0..32]); let x_dec_secret = StaticSecret::from(b); diff --git a/util/Cargo.toml b/util/Cargo.toml index 244f340b..95e0063f 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -25,10 +25,10 @@ thiserror = "1" # For beta release -grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } # For local testing