diff --git a/.cargo/config.toml b/.cargo/config.toml index c99b3e6e4..fb4d53361 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,3 +3,11 @@ runner = 'wasm-bindgen-test-runner' [alias] xtask = "run --package xtask --" +b = "build" +c = "check" +t = "test" +r = "run" +xli = "run --bin xmtp_cli" + +[build] +rustflags = ["--cfg", "tracing_unstable"] diff --git a/Cargo.lock b/Cargo.lock index 25ad0dfc8..9887f3196 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,20 +98,11 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -124,43 +115,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" [[package]] name = "arrayref" @@ -206,7 +197,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -266,7 +257,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -277,7 +268,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -305,7 +296,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -562,9 +553,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" dependencies = [ "serde", ] @@ -644,9 +635,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.31" +version = "1.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" dependencies = [ "jobserver", "libc", @@ -766,7 +757,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -838,7 +829,7 @@ dependencies = [ "eyre", "indenter", "once_cell", - "owo-colors", + "owo-colors 3.5.0", "tracing-error", ] @@ -849,16 +840,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", - "owo-colors", + "owo-colors 3.5.0", "tracing-core", "tracing-error", ] [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" @@ -1082,7 +1073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1118,7 +1109,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1142,7 +1133,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1153,7 +1144,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1194,19 +1185,28 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.18" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] name = "diesel" -version = "2.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +version = "2.2.4" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "diesel_derives", "downcast-rs", @@ -1236,19 +1236,19 @@ dependencies = [ [[package]] name = "diesel_derives" version = "2.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] name = "diesel_migrations" version = "2.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "diesel", "migrations_internals", @@ -1258,9 +1258,9 @@ dependencies = [ [[package]] name = "diesel_table_macro_syntax" version = "0.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1326,6 +1326,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "downcast" version = "0.11.0" @@ -1341,14 +1352,14 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dsl_auto_type" version = "0.1.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "darling", "either", "heck", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1480,9 +1491,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1511,16 +1522,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "erased-serde" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" -dependencies = [ - "serde", - "typeid", -] - [[package]] name = "errno" version = "0.3.9" @@ -1667,7 +1668,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.82", + "syn 2.0.87", "toml 0.8.19", "walkdir", ] @@ -1685,7 +1686,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1711,7 +1712,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.82", + "syn 2.0.87", "tempfile", "thiserror", "tiny-keccak", @@ -1744,7 +1745,6 @@ dependencies = [ "auto_impl", "ethers-contract", "ethers-core", - "ethers-etherscan", "ethers-providers", "ethers-signers", "futures-channel", @@ -1866,22 +1866,6 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" -[[package]] -name = "femme" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" -dependencies = [ - "cfg-if", - "js-sys", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "ff" version = "0.12.1" @@ -2078,7 +2062,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -2302,9 +2286,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hashers" @@ -2362,9 +2346,6 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] [[package]] name = "hkdf" @@ -2591,7 +2572,7 @@ dependencies = [ "http 1.1.0", "hyper 1.5.0", "hyper-util", - "rustls 0.23.15", + "rustls 0.23.16", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -2600,9 +2581,9 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ "hyper 1.5.0", "hyper-util", @@ -2642,9 +2623,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -2682,6 +2663,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2690,12 +2789,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2759,7 +2869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", ] [[package]] @@ -2930,15 +3040,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lalrpop" version = "0.20.2" @@ -3005,9 +3106,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -3097,6 +3198,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -3112,10 +3219,6 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -dependencies = [ - "serde", - "value-bag", -] [[package]] name = "matchers" @@ -3151,7 +3254,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "migrations_internals" version = "2.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "serde", "toml 0.8.19", @@ -3160,7 +3263,7 @@ dependencies = [ [[package]] name = "migrations_macros" version = "2.2.0" -source = "git+https://github.com/diesel-rs/diesel?branch=master#b170af753cc3c6774f578aae1081711a09dfa2ac" +source = "git+https://github.com/diesel-rs/diesel?branch=master#cd4300bd88c9dd53f41b7d87ca134b0cbb9d0f93" dependencies = [ "migrations_internals", "proc-macro2", @@ -3185,9 +3288,9 @@ dependencies = [ [[package]] name = "minicov" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" dependencies = [ "cc", "walkdir", @@ -3235,15 +3338,12 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "ed25519-dalek", "ethers", "futures", "hex", "openmls", - "openmls_basic_credential", "openmls_rust_crypto", "rand", - "sha2 0.10.8", "thiserror", "tokio", "tonic", @@ -3280,7 +3380,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3362,7 +3462,7 @@ dependencies = [ "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3377,7 +3477,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3495,7 +3595,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3570,24 +3670,14 @@ name = "openmls" version = "0.6.0" source = "git+https://github.com/xmtp/openmls?rev=043b347cb18d528647df36f500725ab57c41c7db#043b347cb18d528647df36f500725ab57c41c7db" dependencies = [ - "backtrace", "fluvio-wasm-timer", "getrandom", - "itertools 0.10.5", "log", - "once_cell", - "openmls_basic_credential", - "openmls_memory_storage", - "openmls_rust_crypto", - "openmls_test", "openmls_traits", - "rand", "rayon", "serde", - "serde_json", "thiserror", "tls_codec", - "wasm-bindgen-test", ] [[package]] @@ -3608,7 +3698,6 @@ name = "openmls_memory_storage" version = "0.3.0" source = "git+https://github.com/xmtp/openmls?rev=043b347cb18d528647df36f500725ab57c41c7db#043b347cb18d528647df36f500725ab57c41c7db" dependencies = [ - "hex", "log", "openmls_traits", "serde", @@ -3640,21 +3729,6 @@ dependencies = [ "tls_codec", ] -[[package]] -name = "openmls_test" -version = "0.1.0" -source = "git+https://github.com/xmtp/openmls?rev=043b347cb18d528647df36f500725ab57c41c7db#043b347cb18d528647df36f500725ab57c41c7db" -dependencies = [ - "ansi_term", - "openmls_rust_crypto", - "openmls_traits", - "proc-macro2", - "quote", - "rstest", - "rstest_reuse", - "syn 2.0.82", -] - [[package]] name = "openmls_traits" version = "0.3.0" @@ -3687,7 +3761,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3698,9 +3772,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.3.2+3.3.2" +version = "300.4.0+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" +checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" dependencies = [ "cc", ] @@ -3736,6 +3810,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" + [[package]] name = "p256" version = "0.13.2" @@ -3988,7 +4068,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -4011,29 +4091,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -4179,12 +4259,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -4221,9 +4301,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -4271,7 +4351,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.82", + "syn 2.0.87", "tempfile", ] @@ -4285,7 +4365,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -4413,9 +4493,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -4501,9 +4581,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -4626,44 +4706,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "rstest" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de1bb486a691878cd320c2f0d319ba91eeaa2e894066d8b5f8f117c000e9d962" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290ca1a1c8ca7edb7c3283bd44dc35dd54fdec6253a3912e201ba1072018fca8" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", - "unicode-ident", -] - -[[package]] -name = "rstest_reuse" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f80dcc84beab3a327bbe161f77db25f336a1452428176787c8c79ac79d7073" -dependencies = [ - "quote", - "rand", - "rustc_version", - "syn 1.0.109", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4687,9 +4729,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags 2.6.0", "errno", @@ -4712,9 +4754,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "log", "once_cell", @@ -4815,9 +4857,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.3" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +checksum = "1aa7ffc1c0ef49b0452c6e2986abf2b07743320641ffd5fc63d552458e3b779b" dependencies = [ "cfg-if", "derive_more", @@ -4827,14 +4869,14 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.3" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +checksum = "46385cc24172cf615450267463f937c10072516359b3ff1cb24228a4a08bf951" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -4884,7 +4926,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -4983,9 +5025,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -5003,22 +5045,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", -] - -[[package]] -name = "serde_fmt" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" -dependencies = [ - "serde", + "syn 2.0.87", ] [[package]] @@ -5240,6 +5273,12 @@ dependencies = [ "der 0.7.9", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -5284,7 +5323,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -5293,84 +5332,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "sval" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6dc0f9830c49db20e73273ffae9b5240f63c42e515af1da1fceefb69fceafd8" - -[[package]] -name = "sval_buffer" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "429922f7ad43c0ef8fd7309e14d750e38899e32eb7e8da656ea169dd28ee212f" -dependencies = [ - "sval", - "sval_ref", -] - -[[package]] -name = "sval_dynamic" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f16ff5d839396c11a30019b659b0976348f3803db0626f736764c473b50ff4" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_fmt" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01c27a80b6151b0557f9ccbe89c11db571dc5f68113690c1e028d7e974bae94" -dependencies = [ - "itoa", - "ryu", - "sval", -] - -[[package]] -name = "sval_json" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0deef63c70da622b2a8069d8600cf4b05396459e665862e7bdb290fd6cf3f155" -dependencies = [ - "itoa", - "ryu", - "sval", -] - -[[package]] -name = "sval_nested" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a39ce5976ae1feb814c35d290cf7cf8cd4f045782fe1548d6bc32e21f6156e9f" -dependencies = [ - "sval", - "sval_buffer", - "sval_ref", -] - -[[package]] -name = "sval_ref" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7c6ee3751795a728bc9316a092023529ffea1783499afbc5c66f5fabebb1fa" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_serde" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5572d0321b68109a343634e3a5d576bf131b82180c6c442dee06349dfc652a" -dependencies = [ - "serde", - "sval", - "sval_nested", -] - [[package]] name = "svm-rs" version = "0.3.5" @@ -5404,9 +5365,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.82" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -5428,6 +5389,17 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -5472,9 +5444,9 @@ dependencies = [ [[package]] name = "talc" -version = "4.4.1" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04be12ec299aadd63a0bf781d893e4b6139d33cdca6dcd6f6be31f849cedcac8" +checksum = "3fcad3be1cfe36eb7d716a04791eba36a197da9d9b6ea1e28e64ac569da3701d" dependencies = [ "lock_api", ] @@ -5526,22 +5498,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -5616,6 +5588,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5660,14 +5642,14 @@ checksum = "8d9ef545650e79f30233c0003bcc2504d7efac6dad25fca40744de773fe2049c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -5690,7 +5672,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -5719,7 +5701,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.15", + "rustls 0.23.16", "rustls-pki-types", "tokio", ] @@ -5921,7 +5903,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -5965,21 +5947,39 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", + "valuable", + "valuable-serde", +] + [[package]] name = "tracing-subscriber" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "chrono", "matchers", "nu-ansi-term", "once_cell", "regex", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-serde", + "valuable", + "valuable-serde", ] [[package]] @@ -6001,7 +6001,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -6050,12 +6050,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "typeid" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" - [[package]] name = "typenum" version = "1.17.0" @@ -6086,27 +6080,12 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -6181,7 +6160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c801f0f05b06df456a2da4c41b9c2c4fdccc6b9916643c6c67275c4c9e4d07" dependencies = [ "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -6212,7 +6191,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", + "syn 2.0.87", "toml 0.5.11", "uniffi_meta", ] @@ -6279,9 +6258,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -6295,6 +6274,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -6326,41 +6317,29 @@ name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "value-bag" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" dependencies = [ - "value-bag-serde1", - "value-bag-sval2", + "valuable-derive", ] [[package]] -name = "value-bag-serde1" -version = "1.9.0" +name = "valuable-derive" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccacf50c5cb077a9abb723c5bcb5e0754c1a433f1e1de89edc328e2760b6328b" +checksum = "9d44690c645190cfce32f91a1582281654b2338c6073fa250b0949fd25c55b32" dependencies = [ - "erased-serde", - "serde", - "serde_fmt", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "value-bag-sval2" -version = "1.9.0" +name = "valuable-serde" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1785bae486022dfb9703915d42287dcb284c1ee37bd1080eeba78cc04721285b" +checksum = "5285cfff30cdabe26626736a54d989687dd9cab84f51f4048b61d6d0ae8b0907" dependencies = [ - "sval", - "sval_buffer", - "sval_dynamic", - "sval_fmt", - "sval_json", - "sval_ref", - "sval_serde", + "serde", + "valuable", ] [[package]] @@ -6450,8 +6429,6 @@ checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", - "serde", - "serde_json", "wasm-bindgen-macro", ] @@ -6466,7 +6443,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -6500,7 +6477,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6534,14 +6511,14 @@ checksum = "c97b2ef2c8d627381e51c071c2ab328eac606d3f69dd82bcbca20a9e389d95f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] name = "wasm-streams" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -6836,6 +6813,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -6916,7 +6905,7 @@ dependencies = [ "async-stream", "async-trait", "futures", - "reqwest 0.12.8", + "reqwest 0.12.9", "serde", "serde_json", "thiserror", @@ -6931,18 +6920,21 @@ name = "xmtp_cli" version = "0.1.0" dependencies = [ "clap", + "color-eyre", "ethers", - "femme", "futures", "hex", - "kv-log-macro", - "log", + "owo-colors 4.1.0", "prost", "serde", "serde_json", "thiserror", "timeago", "tokio", + "tracing", + "tracing-subscriber", + "valuable", + "valuable-serde", "xmtp_api_grpc", "xmtp_cryptography", "xmtp_id", @@ -6954,12 +6946,16 @@ dependencies = [ name = "xmtp_cryptography" version = "0.1.0" dependencies = [ + "bincode", "curve25519-dalek", "ecdsa 0.16.9", + "ed25519-dalek", "ethers", "getrandom", "hex", "k256 0.13.4", + "openmls_basic_credential", + "openmls_traits", "rand", "rand_chacha", "rustc-hex", @@ -6967,10 +6963,11 @@ dependencies = [ "sha2 0.10.8", "sha3", "thiserror", - "tokio", + "tls_codec", "tracing", "wasm-bindgen-futures", "wasm-bindgen-test", + "zeroize", ] [[package]] @@ -7022,7 +7019,6 @@ dependencies = [ "diesel-wasm-sqlite", "diesel_migrations", "dyn-clone", - "ed25519-dalek", "ethers", "futures", "getrandom", @@ -7042,10 +7038,9 @@ dependencies = [ "parking_lot 0.12.3", "prost", "rand", - "reqwest 0.12.8", + "reqwest 0.12.9", "serde", "serde_json", - "sha2 0.10.8", "tempfile", "thiserror", "tls_codec", @@ -7165,6 +7160,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -7183,7 +7202,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", ] [[package]] @@ -7203,7 +7243,29 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2235e3930..10e32e567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ chrono = "0.4.38" wasm-timer = "0.2" ctor = "0.2" ed25519 = "2.2.3" -ed25519-dalek = "2.1.1" +ed25519-dalek = { version = "2.1.1", features = ["zeroize"] } ethers = { version = "2.0", default-features = false } futures = "0.3.30" futures-core = "0.3.30" @@ -54,6 +54,7 @@ rustc-hex = "2.1.0" serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false } sha2 = "0.10.8" +sha3 = "0.10.8" thiserror = "1.0" tls_codec = "0.4.1" tokio = { version = "1.35.1", default-features = false } @@ -82,6 +83,8 @@ libsqlite3-sys = { version = "0.29", features = ["bundled-sqlcipher-vendored-ope dyn-clone = "1" trait-variant = "0.1.2" url = "2.5.0" +zeroize = "1.8" +bincode = "1.3" # Internal Crate Dependencies xmtp_cryptography = { path = "xmtp_cryptography" } diff --git a/deny.toml b/deny.toml index ce308874a..768c009b3 100644 --- a/deny.toml +++ b/deny.toml @@ -1,7 +1,10 @@ [advisories] -ignore = [ - {id="RUSTSEC-2021-0139", reason="The maintainer has advised that this crate is deprecated and will not receive any maintenance. https://rustsec.org/advisories/RUSTSEC-2021-0139.html"}, -] +# This rustsec can be added to ignore list if using mls `test_utils` for tests +# { +# id="RUSTSEC-2021-0139", +# reason="The maintainer has advised that this crate is deprecated and will not receive any maintenance. https://rustsec.org/advisories/RUSTSEC-2021-0139.html" +# }, +ignore = [] [licenses] allow = [ @@ -13,7 +16,8 @@ allow = [ "Unicode-DFS-2016", "GPL-3.0", "CC0-1.0", - "BSD-2-Clause" + "BSD-2-Clause", + "Unicode-3.0" ] confidence-threshold = 1.0 @@ -30,4 +34,4 @@ version = "*" expression = "MIT AND ISC AND OpenSSL" license-files = [ { path = "LICENSE", hash = 0xbd0eed23 } -] \ No newline at end of file +] diff --git a/dev/test-wasm b/dev/test-wasm index 2231e8826..df74ed5cd 100755 --- a/dev/test-wasm +++ b/dev/test-wasm @@ -6,7 +6,7 @@ WASM_BINDGEN_SPLIT_LINKED_MODULES=1 \ WASM_BINDGEN_TEST_TIMEOUT=120 \ CHROMEDRIVER="chromedriver" \ cargo test --target wasm32-unknown-unknown --release \ - -p xmtp_mls -p xmtp_id -p xmtp_api_http -- \ + -p xmtp_mls -p xmtp_id -p xmtp_api_http -p xmtp_cryptography -- \ --skip xmtp_mls::subscriptions \ --skip xmtp_mls::groups::subscriptions \ --skip xmtp_mls::storage::encrypted_store::group_message::tests::it_cannot_insert_message_without_group \ diff --git a/examples/cli/Cargo.toml b/examples/cli/Cargo.toml index 8fd457d7a..012bae1d2 100644 --- a/examples/cli/Cargo.toml +++ b/examples/cli/Cargo.toml @@ -2,36 +2,35 @@ default-run = "xmtp_cli" edition = "2021" keywords = ["xmtp", "messaging", "web3", "group-chat"] -license = "MIT" name = "xmtp_cli" readme = "README.md" repository = "https://github.com/xmtp/libxmtp" -version = "0.1.0" +version.workspace = true +license.workspace = true [[bin]] name = "xmtp_cli" path = "cli-client.rs" [dependencies] +tracing = { workspace = true, features = ["valuable"] } +tracing-subscriber = { workspace = true, features = ["json", "valuable", "env-filter", "ansi", "chrono"] } +valuable = { version = "0.1", features = ["derive"] } +valuable-serde = "0.1" clap = { version = "4.4.6", features = ["derive"] } -ethers = "2.0.4" -femme = "2.2.1" +ethers.workspace = true futures.workspace = true -hex = "0.4.3" -kv-log-macro = "1.0.7" -log = { version = "0.4", features = [ - "kv_unstable", - "std", - "kv_unstable_serde", -] } +hex.workspace = true prost.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true thiserror.workspace = true timeago = "0.4.1" -tokio = "1.28.1" +tokio.workspace = true xmtp_api_grpc = { path = "../../xmtp_api_grpc" } xmtp_cryptography = { path = "../../xmtp_cryptography" } xmtp_id = { path = "../../xmtp_id" } xmtp_mls = { path = "../../xmtp_mls" } xmtp_proto = { path = "../../xmtp_proto", features = ["proto_full"] } +color-eyre = "0.6" +owo-colors = "4.1" diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index f06259b15..b14b14076 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -3,41 +3,42 @@ XLI is a Commandline client using XMTPv3. */ -mod json_logger; +mod pretty; mod serializable; -extern crate ethers; -extern crate log; -extern crate xmtp_mls; - use std::iter::Iterator; use std::{fs, path::PathBuf, time::Duration}; +use crate::serializable::{SerializableGroup, SerializableMessage}; use clap::{Parser, Subcommand, ValueEnum}; +use color_eyre::eyre::eyre; use ethers::signers::{coins_bip39::English, LocalWallet, MnemonicBuilder}; use futures::future::join_all; -use kv_log_macro::{error, info}; +use owo_colors::OwoColorize; use prost::Message; -use xmtp_api_grpc::replication_client::ClientV4; -use xmtp_id::associations::unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}; -use xmtp_mls::groups::device_sync::DeviceSyncContent; -use xmtp_mls::storage::group::GroupQueryArgs; -use xmtp_mls::storage::group_message::{GroupMessageKind, MsgQueryArgs}; -use xmtp_mls::XmtpApi; -use xmtp_proto::xmtp::mls::message_contents::DeviceSyncKind; - -use crate::{ - json_logger::make_value, - serializable::{SerializableGroup, SerializableMessage}, -}; use serializable::maybe_get_text; use thiserror::Error; +use tracing::Dispatch; +use tracing_subscriber::field::MakeExt; +use tracing_subscriber::EnvFilter; +use tracing_subscriber::{ + fmt::{format, time}, + layer::SubscriberExt, + Registry, +}; +use valuable::Valuable; use xmtp_api_grpc::grpc_api_helper::Client as ClientV3; +use xmtp_api_grpc::replication_client::ClientV4; use xmtp_cryptography::{ signature::{RecoverableSignature, SignatureError}, utils::rng, }; -use xmtp_id::associations::{generate_inbox_id, AssociationError}; +use xmtp_id::associations::unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}; +use xmtp_id::associations::{generate_inbox_id, AssociationError, AssociationState, MemberKind}; +use xmtp_mls::groups::device_sync::DeviceSyncContent; +use xmtp_mls::storage::group::GroupQueryArgs; +use xmtp_mls::storage::group_message::{GroupMessageKind, MsgQueryArgs}; +use xmtp_mls::XmtpApi; use xmtp_mls::{ builder::ClientBuilderError, client::ClientError, @@ -51,6 +52,10 @@ use xmtp_mls::{ utils::time::now_ns, InboxOwner, }; +use xmtp_proto::xmtp::mls::message_contents::DeviceSyncKind; + +#[macro_use] +extern crate tracing; type Client = xmtp_mls::client::Client>; type MlsGroup = xmtp_mls::groups::MlsGroup; @@ -176,12 +181,35 @@ impl InboxOwner for Wallet { } #[tokio::main] -async fn main() { +async fn main() -> color_eyre::eyre::Result<()> { + color_eyre::install()?; let cli = Cli::parse(); if cli.json { - crate::json_logger::start(log::LevelFilter::Info); + let fmt = tracing_subscriber::fmt::format() + .json() + .flatten_event(true) + .with_thread_ids(true) + .with_level(true) + .with_timer(time::ChronoLocal::new("%s".into())); + tracing_subscriber::fmt().event_format(fmt).init(); } else { - femme::with_level(femme::LevelFilter::Info); + let crate_name = env!("CARGO_PKG_NAME"); + let filter = EnvFilter::builder().parse(format!("{crate_name}=INFO,xmtp_mls=INFO"))?; + let layer = tracing_subscriber::fmt::layer() + .without_time() + .map_event_format(|_| pretty::PrettyTarget) + .fmt_fields( + format::debug_fn(|writer, field, value| { + if field.name() == "message" { + write!(writer, "{:?}", value.white()) + } else { + write!(writer, "{} {:?}", field.bold(), value.white()) + } + }) + .delimited("\n\t"), + ); + let subscriber = Registry::default().with(filter).with(layer); + let _ = tracing::dispatcher::set_global_default(Dispatch::new(subscriber)); } info!("Starting CLI Client...."); @@ -213,12 +241,10 @@ async fn main() { if let Err(e) = register(&cli, seed_phrase.clone(), grpc).await { error!("Registration failed: {:?}", e) } - return; + return Ok(()); } - let client = create_client(&cli, IdentityStrategy::CachedOnly, grpc) - .await - .unwrap(); + let client = create_client(&cli, IdentityStrategy::CachedOnly, grpc).await?; match &cli.command { #[allow(unused_variables)] @@ -227,12 +253,19 @@ async fn main() { } Commands::Info {} => { info!("Info"); - let installation_id = hex::encode(client.installation_public_key()); - info!("identity info", { command_output: true, account_address: client.inbox_id(), installation_id: installation_id }); + let (recovery, ids, addrs) = pretty_association_state(&client.inbox_state(true).await?); + info!( + command_output = true, + inbox_id = client.inbox_id(), + recovery_address = recovery, + installation_ids = &ids.as_value(), + addressess = &addrs.as_value(), + "identity info", + ); } Commands::ListGroups {} => { info!("List Groups"); - let conn = client.store().conn().unwrap(); + let conn = client.store().conn()?; client .sync_welcomes(&conn) .await @@ -253,21 +286,28 @@ async fn main() { let serializable_group_list = join_all(serializable_group_list).await; info!( + command_output = true, + groups = &serializable_group_list.as_value(), "group members", - { - command_output: true, - groups: make_value(&serializable_group_list), - } ); } Commands::Send { group_id, msg } => { - info!("Sending message to group", { group_id: group_id, message: msg }); + info!( + group_id = group_id, + message = msg, + "Sending message to group" + ); info!("Inbox ID is: {}", client.inbox_id()); let group = get_group(&client, hex::decode(group_id).expect("group id decode")) .await .expect("failed to get group"); - send(group, msg.clone()).await.unwrap(); - info!("sent message", { command_output: true, group_id: group_id, message: msg }); + send(group, msg.clone()).await?; + info!( + command_output = true, + group_id = group_id, + message = msg, + "sent message" + ); } Commands::ListGroupMessages { group_id } => { info!("Recv"); @@ -276,13 +316,18 @@ async fn main() { .await .expect("failed to get group"); - let messages = group.find_messages(&MsgQueryArgs::default()).unwrap(); + let messages = group.find_messages(&MsgQueryArgs::default())?; if cli.json { let json_serializable_messages = messages .iter() .map(SerializableMessage::from_stored_message) .collect::>(); - info!("messages", { command_output: true, messages: make_value(&json_serializable_messages), group_id: group_id }); + info!( + command_output = true, + messages = &json_serializable_messages.as_value(), + group_id = group_id, + "messages", + ); } else { let messages = format_messages(messages, client.inbox_id()).expect("failed to get messages"); @@ -307,8 +352,11 @@ async fn main() { .expect("failed to add member"); info!( + command_output = true, + group_id = group_id, "Successfully added {} to group {}", - account_addresses.join(", "), group_id, { command_output: true, group_id: group_id} + account_addresses.join(", "), + group_id, ); } Commands::RemoveGroupMembers { @@ -325,8 +373,10 @@ async fn main() { .expect("failed to add member"); info!( + command_output = true, "Successfully removed {} from group {}", - account_addresses.join(", "), group_id, { command_output: true } + account_addresses.join(", "), + group_id ); } Commands::CreateGroup { permissions } => { @@ -343,7 +393,12 @@ async fn main() { ) .expect("failed to create group"); let group_id = hex::encode(group.group_id); - info!("Created group {}", group_id, { command_output: true, group_id: group_id}) + info!( + command_output = true, + group_id = group_id, + "Created group {}", + group_id + ); } Commands::GroupInfo { group_id } => { let group = &client @@ -351,68 +406,79 @@ async fn main() { .expect("group not found"); group.sync().await.unwrap(); let serializable = SerializableGroup::from(group).await; - info!("Group {}", group_id, { command_output: true, group_id: group_id, group_info: make_value(&serializable) }) + info!( + command_output = true, + group_id = group_id, + group_info = &serializable.as_value(), + "Group {}", + group_id + ); } Commands::RequestHistorySync {} => { - let conn = client.store().conn().unwrap(); - let provider = client.mls_provider().unwrap(); - client.sync_welcomes(&conn).await.unwrap(); - client.enable_sync(&provider).await.unwrap(); + let conn = client.store().conn()?; + let provider = client.mls_provider()?; + client.sync_welcomes(&conn).await?; + client.enable_sync(&provider).await?; let (group_id, _) = client .send_sync_request(&provider, DeviceSyncKind::MessageHistory) - .await - .unwrap(); + .await?; let group_id_str = hex::encode(group_id); - info!("Sent history sync request in sync group {group_id_str}", { group_id: group_id_str}) + info!( + group_id = group_id_str, + "Sent history sync request in sync group {group_id_str}" + ); } Commands::ReplyToHistorySyncRequest {} => { - let provider = client.mls_provider().unwrap(); - let group = client.get_sync_group().unwrap(); + let provider = client.mls_provider()?; + let group = client.get_sync_group()?; let group_id_str = hex::encode(group.group_id); let reply = client .reply_to_sync_request(&provider, DeviceSyncKind::MessageHistory) - .await - .unwrap(); + .await?; - info!("Sent history sync reply in sync group {group_id_str}", { group_id: group_id_str}); + info!( + group_id = group_id_str, + "Sent history sync reply in sync group {group_id_str}" + ); info!("Reply: {:?}", reply); } Commands::ProcessHistorySyncReply {} => { - let conn = client.store().conn().unwrap(); - let provider = client.mls_provider().unwrap(); - client.sync_welcomes(&conn).await.unwrap(); - client.enable_sync(&provider).await.unwrap(); + let conn = client.store().conn()?; + let provider = client.mls_provider()?; + client.sync_welcomes(&conn).await?; + client.enable_sync(&provider).await?; client .process_sync_reply(&provider, DeviceSyncKind::MessageHistory) - .await - .unwrap(); + .await?; - info!("History bundle downloaded and inserted into user DB", {}) + info!("History bundle downloaded and inserted into user DB") } Commands::ProcessConsentSyncReply {} => { - let conn = client.store().conn().unwrap(); - let provider = client.mls_provider().unwrap(); - client.sync_welcomes(&conn).await.unwrap(); - client.enable_sync(&provider).await.unwrap(); + let conn = client.store().conn()?; + let provider = client.mls_provider()?; + client.sync_welcomes(&conn).await?; + client.enable_sync(&provider).await?; client .process_sync_reply(&provider, DeviceSyncKind::Consent) - .await - .unwrap(); + .await?; - info!("Consent bundle downloaded and inserted into user DB", {}) + info!("Consent bundle downloaded and inserted into user DB") } Commands::ListHistorySyncMessages {} => { - let conn = client.store().conn().unwrap(); - let provider = client.mls_provider().unwrap(); - client.sync_welcomes(&conn).await.unwrap(); - client.enable_sync(&provider).await.unwrap(); - let group = client.get_sync_group().unwrap(); + let conn = client.store().conn()?; + let provider = client.mls_provider()?; + client.sync_welcomes(&conn).await?; + client.enable_sync(&provider).await?; + let group = client.get_sync_group()?; let group_id_str = hex::encode(group.group_id.clone()); - group.sync().await.unwrap(); + group.sync().await?; let messages = group - .find_messages(&MsgQueryArgs::default().kind(GroupMessageKind::Application)) - .unwrap(); - info!("Listing history sync messages", { group_id: group_id_str, messages: messages.len()}); + .find_messages(&MsgQueryArgs::default().kind(GroupMessageKind::Application))?; + info!( + group_id = group_id_str, + messages = messages.len(), + "Listing history sync messages" + ); for message in messages { let message_history_content = serde_json::from_slice::(&message.decrypted_message_bytes); @@ -431,9 +497,11 @@ async fn main() { } } Commands::Clear {} => { - fs::remove_file(cli.db.unwrap()).unwrap(); + fs::remove_file(cli.db.ok_or(eyre!("DB Missing"))?)?; } } + + Ok(()) } async fn create_client( @@ -457,37 +525,6 @@ async fn create_client( Ok(client) } -/* -async fn create_client(cli: &Cli, account: IdentityStrategy) -> Result { - let msg_store = get_encrypted_store(&cli.db).await.unwrap(); - let mut builder = ClientBuilder::new(account).store(msg_store); - - if cli.local { - info!("Using local network"); - builder = builder - .api_client( - ApiClient::create("http://localhost:5556".into(), false) - .await - .unwrap(), - ) - .history_sync_url(MessageHistoryUrls::LOCAL_ADDRESS); - } else { - info!("Using dev network"); - builder = builder - .api_client( - ApiClient::create("https://grpc.dev.xmtp.network:443".into(), true) - .await - .unwrap(), - ) - .history_sync_url(MessageHistoryUrls::DEV_ADDRESS); - } - - let client = builder.build().await.map_err(CliError::ClientBuilder)?; - - Ok(client) -} -*/ - async fn register( cli: &Cli, maybe_seed_phrase: Option, @@ -531,7 +568,12 @@ where error!("Initialization Failed: {}", e.to_string()); panic!("Could not init"); }; - info!("Registered identity", {account_address: client.inbox_id(), installation_id: hex::encode(client.installation_public_key()), command_output: true}); + info!( + account_address = client.inbox_id(), + installation_id = hex::encode(client.installation_public_key()), + command_output = true, + "Registered identity" + ); Ok(()) } @@ -615,3 +657,20 @@ fn pretty_delta(now: u64, then: u64) -> String { let diff = if now > then { now - then } else { then - now }; f.convert(Duration::from_nanos(diff)) } + +fn pretty_association_state(state: &AssociationState) -> (String, Vec, Vec) { + let recovery_address = state.recovery_address().clone(); + let installation_ids = state + .installation_ids() + .into_iter() + .map(hex::encode) + .collect::>(); + + let addresses = state + .members_by_kind(MemberKind::Address) + .into_iter() + .map(|m| m.identifier.to_address().unwrap()) + .collect::>(); + + (recovery_address, installation_ids, addresses) +} diff --git a/examples/cli/pretty.rs b/examples/cli/pretty.rs new file mode 100644 index 000000000..cefe1542e --- /dev/null +++ b/examples/cli/pretty.rs @@ -0,0 +1,31 @@ +use owo_colors::OwoColorize; +use tracing::{Event, Subscriber}; +use tracing_subscriber::{ + fmt::{format::Writer, FmtContext, FormatEvent, FormatFields}, + registry::LookupSpan, +}; + +pub struct PrettyTarget; +impl FormatEvent for PrettyTarget +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + // Required method + fn format_event( + &self, + ctx: &FmtContext<'_, S, N>, + mut writer: Writer<'_>, + event: &Event<'_>, + ) -> std::fmt::Result { + if writer.has_ansi_escapes() { + write!(&mut writer, "{} ", event.metadata().target().green().bold())?; + } else { + write!(&mut writer, "{} ", event.metadata().target())?; + } + + ctx.format_fields(writer.by_ref(), event)?; + + writeln!(writer) + } +} diff --git a/examples/cli/serializable.rs b/examples/cli/serializable.rs index 741482c89..cbc3190a6 100644 --- a/examples/cli/serializable.rs +++ b/examples/cli/serializable.rs @@ -1,5 +1,6 @@ use prost::Message; use serde::Serialize; +use valuable::Valuable; use xmtp_mls::{ codecs::{text::TextCodec, ContentCodec}, groups::MlsGroup, @@ -8,13 +9,13 @@ use xmtp_mls::{ }; use xmtp_proto::xmtp::mls::message_contents::EncodedContent; -#[derive(Serialize, Debug)] +#[derive(Serialize, Debug, Valuable)] pub struct SerializableGroupMetadata { creator_inbox_id: String, policy: String, } -#[derive(Serialize, Debug)] +#[derive(Serialize, Debug, Valuable)] pub struct SerializableGroup { pub group_id: String, pub members: Vec, @@ -55,7 +56,7 @@ impl SerializableGroup { } } -#[derive(Serialize, Debug, Clone)] +#[derive(Serialize, Debug, Clone, Valuable)] pub struct SerializableMessage { sender_inbox_id: String, sent_at_ns: u64, @@ -80,7 +81,7 @@ pub fn maybe_get_text(msg: &StoredGroupMessage) -> Option { return None; }; let Ok(decoded) = TextCodec::decode(encoded_content) else { - log::warn!("Skipping over unrecognized codec"); + warn!("Skipping over unrecognized codec"); return None; }; Some(decoded) diff --git a/mls_validation_service/Cargo.toml b/mls_validation_service/Cargo.toml index 5937944bc..fd6e37edd 100644 --- a/mls_validation_service/Cargo.toml +++ b/mls_validation_service/Cargo.toml @@ -14,14 +14,12 @@ vergen = { version = "8.3.2", features = ["git", "git2"] } [dependencies] clap = { version = "4.4.6", features = ["derive"] } -ed25519-dalek = { workspace = true, features = ["digest"] } ethers = { workspace = true } futures = { workspace = true } hex = { workspace = true } openmls = { workspace = true } openmls_rust_crypto = { workspace = true } thiserror.workspace = true -tokio = { workspace = true, features = ["rt-multi-thread", "signal"] } tonic = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter", "ansi"] } tracing.workspace = true @@ -30,13 +28,12 @@ xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id.workspace = true xmtp_mls.workspace = true xmtp_proto = { path = "../xmtp_proto", features = ["proto_full", "convert"] } +tokio = { workspace = true, features = ["signal", "rt-multi-thread"] } [dev-dependencies] anyhow.workspace = true ethers.workspace = true -openmls_basic_credential = { workspace = true, features = ["test-utils"] } rand = { workspace = true } -sha2.workspace = true xmtp_id = { workspace = true, features = ["test-utils"] } xmtp_mls = { workspace = true, features = ["test-utils"] } diff --git a/mls_validation_service/src/handlers.rs b/mls_validation_service/src/handlers.rs index cd43ab815..ef96904dd 100644 --- a/mls_validation_service/src/handlers.rs +++ b/mls_validation_service/src/handlers.rs @@ -317,7 +317,6 @@ mod tests { use std::sync::Arc; use associations::AccountId; - use ed25519_dalek::SigningKey; use ethers::{ abi::Token, signers::{LocalWallet, Signer as _}, @@ -325,11 +324,11 @@ mod tests { }; use openmls::{ extensions::{ApplicationIdExtension, Extension, Extensions}, + key_packages::KeyPackage, prelude::{tls_codec::Serialize, Credential as OpenMlsCredential, CredentialWithKey}, - prelude_test::KeyPackage, }; - use openmls_basic_credential::SignatureKeyPair; use openmls_rust_crypto::OpenMlsRustCrypto; + use xmtp_cryptography::XmtpInstallationCredential; use xmtp_id::{ associations::{ generate_inbox_id, @@ -356,8 +355,8 @@ mod tests { } } - fn generate_inbox_id_credential() -> (String, SigningKey) { - let signing_key = SigningKey::generate(&mut rand::thread_rng()); + fn generate_inbox_id_credential() -> (String, XmtpInstallationCredential) { + let signing_key = XmtpInstallationCredential::new(); let wallet = LocalWallet::new(&mut rand::thread_rng()); let address = format!("0x{}", hex::encode(wallet.address())); @@ -368,7 +367,7 @@ mod tests { } fn build_key_package_bytes( - keypair: &SignatureKeyPair, + keypair: &XmtpInstallationCredential, credential_with_key: &CredentialWithKey, account_address: Option, ) -> Vec { @@ -395,17 +394,6 @@ mod tests { kp.key_package().tls_serialize_detached().unwrap() } - fn to_signature_keypair(key: SigningKey) -> SignatureKeyPair { - let secret = key.to_bytes(); - let public = key.verifying_key().to_bytes(); - - SignatureKeyPair::from_raw( - CIPHERSUITE.signature_algorithm(), - secret.into(), - public.into(), - ) - } - // this test will panic until signature recovery is added // and `MockSignature` is updated with signatures that can be recovered #[tokio::test] @@ -439,8 +427,6 @@ mod tests { #[tokio::test] async fn test_validate_inbox_id_key_package_happy_path() { let (inbox_id, keypair) = generate_inbox_id_credential(); - let keypair = to_signature_keypair(keypair); - let credential: OpenMlsCredential = InboxIdMlsCredential { inbox_id: inbox_id.clone(), } @@ -449,7 +435,7 @@ mod tests { let credential_with_key = CredentialWithKey { credential, - signature_key: keypair.to_public_vec().into(), + signature_key: keypair.public_slice().into(), }; let key_package_bytes = build_key_package_bytes(&keypair, &credential_with_key, None); @@ -465,9 +451,13 @@ mod tests { .await .unwrap(); - let first_response = &res.into_inner().responses[0]; + let res = res.into_inner(); + let first_response = &res.responses[0]; assert!(first_response.is_ok); - assert_eq!(first_response.installation_public_key, keypair.public()); + assert_eq!( + first_response.installation_public_key, + keypair.public_bytes() + ); assert_eq!( first_response.credential.as_ref().unwrap().inbox_id, inbox_id @@ -479,9 +469,6 @@ mod tests { let (inbox_id, keypair) = generate_inbox_id_credential(); let (_, other_keypair) = generate_inbox_id_credential(); - let keypair = to_signature_keypair(keypair); - let other_keypair = to_signature_keypair(other_keypair); - let credential: OpenMlsCredential = InboxIdMlsCredential { inbox_id: inbox_id.clone(), } @@ -490,7 +477,7 @@ mod tests { let credential_with_key = CredentialWithKey { credential, - signature_key: other_keypair.to_public_vec().into(), + signature_key: other_keypair.public_slice().into(), }; let key_package_bytes = build_key_package_bytes(&keypair, &credential_with_key, None); diff --git a/xmtp_cryptography/Cargo.toml b/xmtp_cryptography/Cargo.toml index 40eb40df7..41dcbaf21 100644 --- a/xmtp_cryptography/Cargo.toml +++ b/xmtp_cryptography/Cargo.toml @@ -9,19 +9,24 @@ license.workspace = true targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown", "aarch64-apple-darwin"] [dependencies] -tracing.workspace = true +openmls_basic_credential.workspace = true +openmls_traits.workspace = true curve25519-dalek = "4" ecdsa = "0.16.9" -ethers = { workspace = true } -hex = { workspace = true } k256 = { version = "0.13.3", features = ["ecdh"] } rand = { workspace = true } rand_chacha = "0.3.1" +tracing.workspace = true +ethers = { workspace = true } +hex = { workspace = true } rustc-hex.workspace = true serde = { workspace = true } -sha2 = "0.10.7" -sha3 = "0.10.6" +sha2.workspace = true +sha3.workspace = true thiserror = { workspace = true } +tls_codec.workspace = true +ed25519-dalek = { workspace = true, features = ["digest"] } +zeroize.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] getrandom = { workspace = true, features = ["js"] } @@ -32,7 +37,8 @@ wasm-bindgen-futures.workspace = true ws = ["ethers/ws"] [dev-dependencies] -tokio = { version = "1.28.1", features = ["rt", "macros"] } +openmls_basic_credential = { workspace = true, features = ["test-utils"] } +bincode.workspace = true [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test.workspace = true diff --git a/xmtp_cryptography/src/basic_credential.rs b/xmtp_cryptography/src/basic_credential.rs new file mode 100644 index 000000000..9518c9a24 --- /dev/null +++ b/xmtp_cryptography/src/basic_credential.rs @@ -0,0 +1,324 @@ +use std::io::BufReader; + +use ed25519_dalek::SigningKey; +use k256::schnorr::CryptoRngCore; +use openmls_basic_credential::SignatureKeyPair; +use openmls_traits::signatures::Signer; +use openmls_traits::{signatures, types::SignatureScheme}; +use serde::de::Error; +use tls_codec::SecretTlsVecU8; +use zeroize::Zeroizing; + +/// Wrapper for [`signatures::SignerError`] that implements [`std::fmt::Display`] +#[derive(thiserror::Error, Debug)] +pub struct SignerError { + inner: signatures::SignerError, +} + +impl From for SignerError { + fn from(err: signatures::SignerError) -> SignerError { + SignerError { inner: err } + } +} + +impl std::fmt::Display for SignerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use signatures::SignerError::*; + match self.inner { + SigningError => write!(f, "signing error"), + InvalidSignature => write!(f, "invalid signature"), + CryptoError(c) => write!(f, "{}", c), + } + } +} + +mod private { + /// A rudimentary form of specialization + /// this allows implementing CredentialSigning + /// on `XmtpInstallationCredential` in foreign crates. + /// A `private::NotSpecialized` trait may only be defined in `xmtp_cryptography`. + /// Since it is not defined, implementations in their own crates are preferred. + pub struct NotSpecialized; +} + +/// Sign with some public/private keypair credential +pub trait CredentialSign { + /// the hashed context this credential signature takes place in + // If this is not defined the context will be empty + const CONTEXT: &[u8] = b""; + type Error; + + fn credential_sign>(&self, text: S) -> Result, Self::Error>; +} + +/// Verify a credential signature with its public key +pub trait CredentialVerify { + /// the hashed context this credential signature verification takes place in + /// if this is not defined, the context will be empty + const CONTEXT: &[u8] = b""; + type Error; + + fn credential_verify( + &self, + signature_text: impl AsRef, + signature_bytes: &[u8; 64], + ) -> Result<(), Self::Error>; +} + +/// The credential for an XMTP Installation +/// an XMTP Installation often refers to one specific device, +/// and is an ed25519 key +// Boxing the inner value avoids creating large enums if an enum stores multiple installation +// credentials +#[derive(Debug, Clone)] +pub struct XmtpInstallationCredential(Box); + +impl Default for XmtpInstallationCredential { + fn default() -> Self { + Self(Box::new(SigningKey::generate(&mut crate::utils::rng()))) + } +} + +impl XmtpInstallationCredential { + /// Create a new [`XmtpInstallationCredential`] with [`rand_chacha::ChaCha20Rng`] + pub fn new() -> Self { + Self(Box::new(SigningKey::generate(&mut crate::utils::rng()))) + } + + /// Create a new [`XmtpInstallationCredential`] with custom RNG + pub fn with_rng(rng: &mut R) -> Self { + Self(Box::new(SigningKey::generate(rng))) + } + + /// Get a reference to the public [`ed25519_dalek::VerifyingKey`] + /// Can be used to verify signatures + pub fn verifying_key(&self) -> ed25519_dalek::VerifyingKey { + self.0.verifying_key() + } + + /// View the public [`ed25519_dalek::VerifyingKey`] as constant-sized bytes + pub fn public_bytes(&self) -> &[u8; 32] { + self.0.as_ref().as_ref().as_bytes() + } + + /// View the public [`ed25519_dalek::VerifyingKey`] as a slice + pub fn public_slice(&self) -> &[u8] { + self.0.as_ref().as_ref().as_ref() + } + + /// get the scheme, prefer the public [`Signer::signature_scheme`] + fn scheme(&self) -> SignatureScheme { + SignatureScheme::ED25519 + } + + pub fn with_context<'k, 'v>( + &'k self, + context: &'v [u8], + ) -> Result, ed25519_dalek::SignatureError> { + self.0.with_context(context) + } + + /// Internal helper function to safely create a credential from its raw parts + /// private and public must be exactly 32 bytes large. + fn from_raw(private: &[u8], public: &[u8]) -> Result { + let keypair = Zeroizing::new({ + let mut keypair = [0u8; 64]; + keypair[0..32].copy_from_slice(private); + keypair[32..].copy_from_slice(public); + keypair + }); + + let signing_key = SigningKey::from_keypair_bytes(&keypair)?; + Ok(Self(Box::new(signing_key))) + } +} + +/// The signer here must maintain compatability with `SignatureKeyPair` +impl Signer for XmtpInstallationCredential { + fn sign(&self, payload: &[u8]) -> Result, signatures::SignerError> { + SignatureKeyPair::from(self).sign(payload) + } + + fn signature_scheme(&self) -> SignatureScheme { + self.scheme() + } +} + +// The signer here must maintain compatability with `SignatureKeyPair` +impl<'a> Signer for &'a XmtpInstallationCredential { + fn sign(&self, payload: &[u8]) -> Result, signatures::SignerError> { + SignatureKeyPair::from(*self).sign(payload) + } + + fn signature_scheme(&self) -> SignatureScheme { + self.scheme() + } +} + +impl tls_codec::Deserialize for XmtpInstallationCredential { + fn tls_deserialize(bytes: &mut R) -> Result + where + Self: Sized, + { + // a bufreader consumes its input, unlike just a `Read` instance. + let mut buf = BufReader::new(bytes); + let private = SecretTlsVecU8::tls_deserialize(&mut buf)?; + let public = SecretTlsVecU8::tls_deserialize(&mut buf)?; + let scheme = SignatureScheme::tls_deserialize(&mut buf)?; + if scheme != SignatureScheme::ED25519 { + return Err(tls_codec::Error::DecodingError( + "XMTP InstallationCredential must be Ed25519".into(), + )); + } + + Self::from_raw(private.as_slice(), public.as_slice()) + .map_err(|e| tls_codec::Error::DecodingError(e.to_string())) + } +} + +impl From for SignatureKeyPair { + fn from(key: XmtpInstallationCredential) -> SignatureKeyPair { + SignatureKeyPair::from_raw( + key.signature_scheme(), + key.0.to_bytes().into(), + key.0.verifying_key().to_bytes().into(), + ) + } +} + +impl<'a> From<&'a XmtpInstallationCredential> for SignatureKeyPair { + fn from(key: &'a XmtpInstallationCredential) -> SignatureKeyPair { + SignatureKeyPair::from_raw( + key.signature_scheme(), + key.0.to_bytes().into(), + key.0.verifying_key().to_bytes().into(), + ) + } +} + +impl From for XmtpInstallationCredential { + fn from(signing_key: SigningKey) -> Self { + Self(Box::new(signing_key)) + } +} + +impl<'a> From<&'a SigningKey> for XmtpInstallationCredential { + fn from(signing_key: &'a SigningKey) -> Self { + Self(Box::new(signing_key.clone())) + } +} + +impl tls_codec::Serialize for XmtpInstallationCredential { + fn tls_serialize(&self, writer: &mut W) -> Result { + SignatureKeyPair::from(self).tls_serialize(writer) + } +} + +impl tls_codec::Size for XmtpInstallationCredential { + fn tls_serialized_len(&self) -> usize { + SignatureKeyPair::from(self).tls_serialized_len() + } +} + +impl serde::Serialize for XmtpInstallationCredential { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + SignatureKeyPair::from(self).serialize(serializer) + } +} + +impl<'de> serde::Deserialize<'de> for XmtpInstallationCredential { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(serde::Deserialize, zeroize::ZeroizeOnDrop)] + struct SignatureKeyPairRemote { + private: Vec, + public: Vec, + #[allow(dead_code)] + #[zeroize(skip)] + _signature_scheme: SignatureScheme, + } + + let SignatureKeyPairRemote { + ref private, + ref public, + .. + } = SignatureKeyPairRemote::deserialize(deserializer)?; + + Self::from_raw(private.as_slice(), public.as_slice()) + .map_err(|e| >::Error::custom(format!("{}", e))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use tls_codec::{Deserialize as _, Serialize as _}; + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn test_is_binary_compatible_with_mls_deser() { + // XmtpInstallationCredential needs to be binary-compatible/tls-codec/serde compatible with + // `SignatureKeyPair` from xmtp_basic_credential + let keypair = SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(); + let mut serialized: Vec = Vec::new(); + + keypair.tls_serialize(&mut serialized).unwrap(); + let x_kp = XmtpInstallationCredential::tls_deserialize(&mut serialized.as_slice()).unwrap(); + assert_eq!(keypair.private(), &x_kp.0.to_bytes()); + assert_eq!(keypair.public(), &x_kp.0.verifying_key().to_bytes()); + } + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn test_is_binary_compatible_with_mls_ser() { + let keypair = XmtpInstallationCredential::new(); + let mut serialized: Vec = Vec::new(); + + keypair.tls_serialize(&mut serialized).unwrap(); + let mls_kp = SignatureKeyPair::tls_deserialize(&mut serialized.as_slice()).unwrap(); + assert_eq!(mls_kp.private(), &keypair.0.to_bytes()); + assert_eq!(mls_kp.public(), &keypair.0.verifying_key().to_bytes()); + assert_eq!(mls_kp.signature_scheme(), keypair.scheme()); + } + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn test_is_binary_compatible_with_mls_deser_serde() { + // XmtpInstallationCredential needs to be serde compatible with + // `SignatureKeyPair` from xmtp_basic_credential + let keypair = SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(); + let serialized: Vec = bincode::serialize(&keypair).unwrap(); + + let x_kp: XmtpInstallationCredential = bincode::deserialize(serialized.as_slice()).unwrap(); + assert_eq!(keypair.private(), &x_kp.0.to_bytes()); + assert_eq!(keypair.public(), &x_kp.0.verifying_key().to_bytes()); + } + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn test_is_binary_compatible_with_mls_ser_serde() { + let keypair = XmtpInstallationCredential::new(); + let serialized: Vec = bincode::serialize(&keypair).unwrap(); + + let mls_kp: SignatureKeyPair = bincode::deserialize(serialized.as_slice()).unwrap(); + assert_eq!(mls_kp.private(), &keypair.0.to_bytes()); + assert_eq!(mls_kp.public(), &keypair.0.verifying_key().to_bytes()); + assert_eq!(mls_kp.signature_scheme(), keypair.scheme()); + } + + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn secret_key_can_not_be_exposed() { + let keypair = XmtpInstallationCredential::new(); + let secret = keypair.0.as_ref(); + + assert_ne!(keypair.public_bytes(), secret.as_bytes()); + assert_ne!(keypair.public_slice(), secret.as_bytes()); + assert_ne!(keypair.verifying_key().as_bytes(), &secret.to_bytes()); + } +} diff --git a/xmtp_cryptography/src/lib.rs b/xmtp_cryptography/src/lib.rs index 0e26c257a..6c9b4ce75 100644 --- a/xmtp_cryptography/src/lib.rs +++ b/xmtp_cryptography/src/lib.rs @@ -1,7 +1,10 @@ +pub mod basic_credential; pub mod hash; pub mod signature; pub mod utils; +pub use basic_credential::*; + #[cfg(test)] pub mod tests { #[cfg(target_arch = "wasm32")] diff --git a/xmtp_cryptography/src/signature.rs b/xmtp_cryptography/src/signature.rs index e72755c23..0c4a454d7 100644 --- a/xmtp_cryptography/src/signature.rs +++ b/xmtp_cryptography/src/signature.rs @@ -1,7 +1,7 @@ use curve25519_dalek::{edwards::CompressedEdwardsY, traits::IsIdentity}; use ethers::core::types::{self as ethers_types, H160}; use ethers::types::Address; -pub use k256::ecdsa::{RecoveryId, SigningKey, VerifyingKey}; +pub use k256::ecdsa::{RecoveryId, SigningKey}; use k256::Secp256k1; use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; @@ -202,9 +202,10 @@ pub mod tests { use crate::signature::{is_valid_ed25519_public_key, RecoverableSignature}; - pub async fn generate_random_signature(msg: &str) -> (String, Vec) { + pub fn generate_random_signature(msg: &str) -> (String, Vec) { let wallet = LocalWallet::new(&mut thread_rng()); - let signature = wallet.sign_message(msg).await.unwrap(); + let message_hash = ethers::core::utils::hash_message(msg); + let signature = wallet.sign_hash(message_hash).unwrap(); ( hex::encode(wallet.address().to_fixed_bytes()), signature.to_vec(), @@ -216,16 +217,16 @@ pub mod tests { } #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] - async fn oracle_signature() { + #[cfg_attr(not(target_arch = "wasm32"), test)] + fn oracle_signature() { let msg = "hello"; - let (addr, bytes) = generate_random_signature(msg).await; + let (addr, bytes) = generate_random_signature(msg); let sig = RecoverableSignature::Eip191Signature(bytes); sig.verify_signature(&addr, msg) .expect("Baseline Signature failed"); - let (other_addr, mut other_bytes) = generate_random_signature(msg).await; + let (other_addr, mut other_bytes) = generate_random_signature(msg); toggle(5, &mut other_bytes); // Invalidate Signature by making a small change let other = RecoverableSignature::Eip191Signature(other_bytes); diff --git a/xmtp_id/Cargo.toml b/xmtp_id/Cargo.toml index 410536cc5..3488b23d3 100644 --- a/xmtp_id/Cargo.toml +++ b/xmtp_id/Cargo.toml @@ -31,8 +31,8 @@ wasm-timer.workspace = true ethers = { workspace = true, features = ["rustls"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -getrandom = { version = "0.2", features = ["js"] } openmls = { workspace = true, features = ["js"] } +getrandom = { version = "0.2", features = ["js"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] openmls.workspace = true diff --git a/xmtp_id/src/associations/builder.rs b/xmtp_id/src/associations/builder.rs index be6ccc3bf..8cc0dcfd2 100644 --- a/xmtp_id/src/associations/builder.rs +++ b/xmtp_id/src/associations/builder.rs @@ -419,6 +419,7 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); use ethers::signers::{LocalWallet, Signer}; + use xmtp_cryptography::XmtpInstallationCredential; use crate::{ associations::{ @@ -433,7 +434,6 @@ pub(crate) mod tests { }, InboxOwner, }; - use ed25519_dalek::SigningKey as Ed25519SigningKey; use super::*; @@ -470,13 +470,12 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn create_and_add_identity() { let wallet = LocalWallet::new(&mut rand::thread_rng()); - let installation_key = Ed25519SigningKey::generate(&mut rand::thread_rng()); + let installation_key = XmtpInstallationCredential::new(); let account_address = wallet.get_address(); - let installation_key_id = installation_key.verifying_key().as_bytes().to_vec(); let nonce = 0; let inbox_id = generate_inbox_id(&account_address, &nonce).unwrap(); let existing_member_identifier: MemberIdentifier = account_address.into(); - let new_member_identifier: MemberIdentifier = installation_key_id.into(); + let new_member_identifier: MemberIdentifier = (&installation_key).into(); let mut signature_request = SignatureRequestBuilder::new(inbox_id) .create_inbox(existing_member_identifier.clone(), nonce) diff --git a/xmtp_id/src/associations/member.rs b/xmtp_id/src/associations/member.rs index c54a7610b..de7008a62 100644 --- a/xmtp_id/src/associations/member.rs +++ b/xmtp_id/src/associations/member.rs @@ -1,3 +1,5 @@ +use xmtp_cryptography::XmtpInstallationCredential; + #[derive(Clone, Debug, PartialEq)] pub enum MemberKind { Installation, @@ -47,6 +49,26 @@ impl MemberIdentifier { None } } + + /// Get the value for [`MemberIdentifier::Address`], consuming the [`MemberIdentifier`] + /// in the process + pub fn to_address(self) -> Option { + if let Self::Address(address) = self { + Some(address) + } else { + None + } + } + + /// Get the value for [`MemberIdentifier::Installation`] variant. + /// Returns `None` if the type is not the correct variant. + pub fn to_installation(&self) -> Option<&[u8]> { + if let Self::Installation(ref installation) = self { + Some(installation) + } else { + None + } + } } impl std::fmt::Display for MemberIdentifier { @@ -72,6 +94,18 @@ impl From> for MemberIdentifier { } } +impl<'a> From<&'a XmtpInstallationCredential> for MemberIdentifier { + fn from(cred: &'a XmtpInstallationCredential) -> MemberIdentifier { + MemberIdentifier::Installation(cred.public_slice().to_vec()) + } +} + +impl From for MemberIdentifier { + fn from(cred: XmtpInstallationCredential) -> MemberIdentifier { + MemberIdentifier::Installation(cred.public_slice().to_vec()) + } +} + /// A Member of Inbox #[derive(Clone, Debug, PartialEq)] pub struct Member { diff --git a/xmtp_id/src/associations/serialization.rs b/xmtp_id/src/associations/serialization.rs index 9348e07bd..e9ccf051f 100644 --- a/xmtp_id/src/associations/serialization.rs +++ b/xmtp_id/src/associations/serialization.rs @@ -70,6 +70,8 @@ pub enum DeserializationError { InvalidAccountId, #[error("Invalid hash (needs to be 32 bytes)")] InvalidHash, + #[error("Error creating public key from proto bytes")] + Ed25519(#[from] ed25519_dalek::ed25519::Error), } impl TryFrom for UnverifiedIdentityUpdate { @@ -172,9 +174,12 @@ impl TryFrom for UnverifiedSignature { sig.delegated_key.ok_or(DeserializationError::Signature)?, )) } - SignatureKindProto::InstallationKey(sig) => UnverifiedSignature::InstallationKey( - UnverifiedInstallationKeySignature::new(sig.bytes, sig.public_key), - ), + SignatureKindProto::InstallationKey(sig) => { + UnverifiedSignature::InstallationKey(UnverifiedInstallationKeySignature::new( + sig.bytes, + sig.public_key.as_slice().try_into()?, + )) + } SignatureKindProto::Erc6492(sig) => UnverifiedSignature::SmartContractWallet( UnverifiedSmartContractWalletSignature::new( sig.signature, @@ -266,12 +271,13 @@ impl From for SignatureWrapperProto { signature: sig.signature_bytes, }) } - UnverifiedSignature::InstallationKey(sig) => { - SignatureKindProto::InstallationKey(RecoverableEd25519SignatureProto { - bytes: sig.signature_bytes, - public_key: sig.verifying_key, - }) - } + UnverifiedSignature::InstallationKey(UnverifiedInstallationKeySignature { + signature_bytes, + verifying_key, + }) => SignatureKindProto::InstallationKey(RecoverableEd25519SignatureProto { + bytes: signature_bytes, + public_key: verifying_key.as_bytes().to_vec(), + }), UnverifiedSignature::LegacyDelegated(sig) => { SignatureKindProto::DelegatedErc191(LegacyDelegatedSignatureProto { delegated_key: Some(sig.signed_public_key_proto), diff --git a/xmtp_id/src/associations/signature.rs b/xmtp_id/src/associations/signature.rs index 54c36b906..ff7d68ed6 100644 --- a/xmtp_id/src/associations/signature.rs +++ b/xmtp_id/src/associations/signature.rs @@ -1,7 +1,12 @@ +use ed25519_dalek::{DigestSigner, Signature}; use ethers::signers::{LocalWallet, Signer}; use prost::Message; +use sha2::{Digest as _, Sha512}; use std::array::TryFromSliceError; use thiserror::Error; +use xmtp_cryptography::{ + CredentialSign, CredentialVerify, SignerError, XmtpInstallationCredential, +}; use xmtp_proto::xmtp::message_contents::{ signed_private_key, SignedPrivateKey as LegacySignedPrivateKeyProto, }; @@ -42,6 +47,43 @@ pub enum SignatureError { DecodeError(#[from] prost::DecodeError), #[error(transparent)] AccountIdError(#[from] AccountIdError), + #[error(transparent)] + Signer(#[from] SignerError), +} + +/// Xmtp Installation Credential for Specialized for XMTP Identity +pub struct InboxIdInstallationCredential; + +impl CredentialSign for XmtpInstallationCredential { + const CONTEXT: &[u8] = crate::constants::INSTALLATION_KEY_SIGNATURE_CONTEXT; + type Error = SignatureError; + + fn credential_sign>(&self, text: S) -> Result, Self::Error> { + let mut prehashed: Sha512 = Sha512::new(); + prehashed.update(text.as_ref()); + let context = self.with_context(Self::CONTEXT)?; + let sig = context + .try_sign_digest(prehashed) + .map_err(SignatureError::from)?; + Ok(sig.to_bytes().into()) + } +} + +impl CredentialVerify for ed25519_dalek::VerifyingKey { + const CONTEXT: &[u8] = crate::constants::INSTALLATION_KEY_SIGNATURE_CONTEXT; + type Error = SignatureError; + + fn credential_verify( + &self, + signature_text: impl AsRef, + signature_bytes: &[u8; 64], + ) -> Result<(), Self::Error> { + let signature = Signature::from_bytes(signature_bytes); + let mut prehashed = Sha512::new(); + prehashed.update(signature_text.as_ref()); + self.verify_prehashed(prehashed, Some(Self::CONTEXT), &signature)?; + Ok(()) + } } #[derive(Clone, Debug, PartialEq)] diff --git a/xmtp_id/src/associations/test_utils.rs b/xmtp_id/src/associations/test_utils.rs index c76f69042..a6cf00f09 100644 --- a/xmtp_id/src/associations/test_utils.rs +++ b/xmtp_id/src/associations/test_utils.rs @@ -5,18 +5,15 @@ use super::{ unverified::{UnverifiedAction, UnverifiedCreateInbox, UnverifiedSignature}, AccountId, }; -use crate::{ - constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, - scw_verifier::{SmartContractSignatureVerifier, ValidationResponse, VerifierError}, -}; -use ed25519_dalek::SigningKey as Ed25519SigningKey; +use crate::scw_verifier::{SmartContractSignatureVerifier, ValidationResponse, VerifierError}; use ethers::{ core::types::BlockNumber, signers::{LocalWallet, Signer}, types::Bytes, }; use rand::Rng; -use sha2::{Digest, Sha512}; +use xmtp_cryptography::basic_credential::XmtpInstallationCredential; +use xmtp_cryptography::CredentialSign; pub fn rand_string() -> String { let hex_chars = "0123456789abcdef"; @@ -83,20 +80,13 @@ pub async fn add_wallet_signature(signature_request: &mut SignatureRequest, wall pub async fn add_installation_key_signature( signature_request: &mut SignatureRequest, - installation_key: &Ed25519SigningKey, + installation_key: &XmtpInstallationCredential, ) { let signature_text = signature_request.signature_text(); - let verifying_key = installation_key.verifying_key(); - let mut prehashed: Sha512 = Sha512::new(); - prehashed.update(signature_text); + let sig = installation_key.credential_sign(signature_text).unwrap(); - let sig = installation_key - .sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) - .unwrap(); - let unverified_sig = UnverifiedSignature::new_installation_key( - sig.to_bytes().to_vec(), - verifying_key.as_bytes().to_vec(), - ); + let unverified_sig = + UnverifiedSignature::new_installation_key(sig, installation_key.verifying_key()); signature_request .add_signature( diff --git a/xmtp_id/src/associations/unverified.rs b/xmtp_id/src/associations/unverified.rs index c5cbeaf9b..a1ac2c849 100644 --- a/xmtp_id/src/associations/unverified.rs +++ b/xmtp_id/src/associations/unverified.rs @@ -256,7 +256,7 @@ impl UnverifiedSignature { UnverifiedSignature::InstallationKey(sig) => VerifiedSignature::from_installation_key( signature_text, &sig.signature_bytes, - &sig.verifying_key, + *sig.verifying_key(), ), UnverifiedSignature::RecoverableEcdsa(sig) => { VerifiedSignature::from_recoverable_ecdsa(signature_text, &sig.signature_bytes) @@ -283,7 +283,10 @@ impl UnverifiedSignature { Self::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new(signature)) } - pub fn new_installation_key(signature: Vec, verifying_key: Vec) -> Self { + pub fn new_installation_key( + signature: Vec, + verifying_key: ed25519_dalek::VerifyingKey, + ) -> Self { Self::InstallationKey(UnverifiedInstallationKeySignature::new( signature, verifying_key, @@ -316,16 +319,26 @@ impl UnverifiedSignature { #[derive(Debug, Clone, PartialEq)] pub struct UnverifiedInstallationKeySignature { pub(crate) signature_bytes: Vec, - pub(crate) verifying_key: Vec, + /// The Signature Verifying Key + // boxing avoids large enum variants if an enum contains multiple signature + pub(crate) verifying_key: Box, } impl UnverifiedInstallationKeySignature { - pub fn new(signature_bytes: Vec, verifying_key: Vec) -> Self { + pub fn new(signature_bytes: Vec, verifying_key: ed25519_dalek::VerifyingKey) -> Self { Self { signature_bytes, - verifying_key, + verifying_key: Box::new(verifying_key), } } + + pub fn verifying_key(&self) -> &ed25519_dalek::VerifyingKey { + self.verifying_key.as_ref() + } + + pub fn verifying_key_bytes(&self) -> Vec { + self.verifying_key.as_ref().as_ref().to_vec() + } } #[derive(Debug, Clone, PartialEq)] diff --git a/xmtp_id/src/associations/verified_signature.rs b/xmtp_id/src/associations/verified_signature.rs index 075f73d7f..4bfedf405 100644 --- a/xmtp_id/src/associations/verified_signature.rs +++ b/xmtp_id/src/associations/verified_signature.rs @@ -1,14 +1,11 @@ #![allow(dead_code)] - -use ed25519_dalek::{Signature as Ed25519Signature, VerifyingKey as Ed25519VerifyingKey}; use ethers::types::Signature as EthersSignature; use ethers::utils::hash_message; use ethers::{core::k256::ecdsa::VerifyingKey as EcdsaVerifyingKey, utils::public_key_to_address}; -use sha2::{Digest, Sha512}; use xmtp_cryptography::signature::h160addr_to_string; +use xmtp_cryptography::CredentialVerify; use xmtp_proto::xmtp::message_contents::SignedPublicKey as LegacySignedPublicKeyProto; -use crate::constants::INSTALLATION_KEY_SIGNATURE_CONTEXT; use crate::scw_verifier::SmartContractSignatureVerifier; use super::{ @@ -87,21 +84,11 @@ impl VerifiedSignature { pub fn from_installation_key>( signature_text: Text, signature_bytes: &[u8], - verifying_key_bytes: &[u8], + verifying_key: ed25519_dalek::VerifyingKey, ) -> Result { - let signature = Ed25519Signature::from_bytes(signature_bytes.try_into()?); - let verifying_key = Ed25519VerifyingKey::from_bytes(verifying_key_bytes.try_into()?)?; - let mut prehashed = Sha512::new(); - prehashed.update(signature_text.as_ref()); - - verifying_key.verify_prehashed( - prehashed, - Some(INSTALLATION_KEY_SIGNATURE_CONTEXT), - &signature, - )?; - + verifying_key.credential_verify(signature_text, signature_bytes.try_into()?)?; Ok(Self::new( - MemberIdentifier::Installation(verifying_key_bytes.to_vec()), + MemberIdentifier::Installation(verifying_key.as_bytes().to_vec()), SignatureKind::InstallationKey, signature_bytes.to_vec(), None, @@ -188,12 +175,11 @@ mod tests { verified_signature::VerifiedSignature, MemberIdentifier, SignatureKind, }, - constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, InboxOwner, }; - use ed25519_dalek::SigningKey as Ed25519SigningKey; use ethers::signers::{LocalWallet, Signer}; use prost::Message; + use xmtp_cryptography::{CredentialSign, XmtpInstallationCredential}; use xmtp_proto::xmtp::message_contents::{ signature::Union as SignatureUnion, signed_private_key, SignedPrivateKey as LegacySignedPrivateKeyProto, @@ -231,41 +217,32 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_installation_key() { - let signing_key = Ed25519SigningKey::generate(&mut rand::thread_rng()); - let verifying_key = signing_key.verifying_key(); - + let key = XmtpInstallationCredential::new(); + let verifying_key = key.verifying_key(); let signature_text = "test signature text"; - let mut prehashed: Sha512 = Sha512::new(); - prehashed.update(signature_text); - - let sig = signing_key - .sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) - .unwrap(); + let sig = key.credential_sign(signature_text).unwrap(); - let verified_sig = VerifiedSignature::from_installation_key( - signature_text, - sig.to_bytes().as_slice(), - verifying_key.as_bytes(), - ) - .expect("should succeed"); + let verified_sig = + VerifiedSignature::from_installation_key(signature_text, sig.as_slice(), verifying_key) + .expect("should succeed"); let expected = MemberIdentifier::Installation(verifying_key.as_bytes().to_vec()); assert_eq!(expected, verified_sig.signer); assert_eq!(SignatureKind::InstallationKey, verified_sig.kind); - assert_eq!(verified_sig.raw_bytes, sig.to_bytes().as_slice()); + assert_eq!(verified_sig.raw_bytes, sig.as_slice()); // Make sure it fails with the wrong signature text VerifiedSignature::from_installation_key( "wrong signature text", - sig.to_bytes().as_slice(), - verifying_key.as_bytes(), + sig.as_slice(), + verifying_key, ) .expect_err("should fail with incorrect signature text"); // Make sure it fails with the wrong verifying key VerifiedSignature::from_installation_key( signature_text, - sig.to_bytes().as_slice(), - &[verifying_key.as_bytes().as_slice(), vec![2, 3].as_slice()].concat(), + sig.as_slice(), + XmtpInstallationCredential::new().verifying_key(), ) .expect_err("should fail with incorrect verifying key"); } diff --git a/xmtp_id/src/constants.rs b/xmtp_id/src/constants.rs index ec962fea4..1dbde531f 100644 --- a/xmtp_id/src/constants.rs +++ b/xmtp_id/src/constants.rs @@ -1,2 +1,2 @@ -// DO NOT CHANGE. SIGNATURES WILL BREAK +/// DO NOT CHANGE. SIGNATURES WILL BREAK pub const INSTALLATION_KEY_SIGNATURE_CONTEXT: &[u8] = b"IDENTITY UPDATE SIGNATURE"; diff --git a/xmtp_id/src/lib.rs b/xmtp_id/src/lib.rs index fd6875b59..a02e7c537 100755 --- a/xmtp_id/src/lib.rs +++ b/xmtp_id/src/lib.rs @@ -4,6 +4,7 @@ pub mod associations; pub mod constants; pub mod scw_verifier; pub mod utils; + use ethers::{ middleware::Middleware, providers::{Http, Provider}, @@ -26,6 +27,8 @@ pub enum IdentityError { ProviderError(#[from] ethers::providers::ProviderError), #[error(transparent)] UrlParseError(#[from] url::ParseError), + #[error("MLS signer error {0}")] + Signing(#[from] xmtp_cryptography::SignerError), } /// The global InboxID Type. diff --git a/xmtp_mls/Cargo.toml b/xmtp_mls/Cargo.toml index 85f0ca089..2bacc0cbb 100644 --- a/xmtp_mls/Cargo.toml +++ b/xmtp_mls/Cargo.toml @@ -39,23 +39,19 @@ test-utils = [ update-schema = ["toml"] [dependencies] +openmls_rust_crypto = { workspace = true } +openmls_traits = { workspace = true } aes-gcm = { version = "0.10.3", features = ["std"] } async-stream.workspace = true async-trait.workspace = true -bincode = "1.3.3" -dyn-clone = "1" -ed25519-dalek = "2.1.1" +bincode.workspace = true futures.workspace = true hex.workspace = true -openmls_basic_credential = { workspace = true } -openmls_rust_crypto = { workspace = true } -openmls_traits = { workspace = true } parking_lot.workspace = true prost = { workspace = true, features = ["prost-derive"] } rand = { workspace = true } serde = { workspace = true } serde_json.workspace = true -sha2.workspace = true thiserror = { workspace = true } tls_codec = { workspace = true } tokio-stream = { version = "0.1", default-features = false, features = [ @@ -64,6 +60,8 @@ tokio-stream = { version = "0.1", default-features = false, features = [ tracing.workspace = true trait-variant.workspace = true wasm-timer.workspace = true +reqwest = { version = "0.12.4", features = ["stream"] } +diesel_migrations.workspace = true # XMTP/Local xmtp_cryptography = { workspace = true } @@ -72,7 +70,6 @@ xmtp_proto = { workspace = true, features = ["convert"] } # Optional/Features console_error_panic_hook = { version = "0.1", optional = true } -reqwest = { version = "0.12.4", features = ["stream"] } toml = { version = "0.8.4", optional = true } tracing-wasm = { version = "0.2", optional = true } xmtp_api_http = { path = "../xmtp_api_http", optional = true } @@ -94,18 +91,16 @@ tracing-subscriber = { workspace = true, features = [ [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -# Native Dependencies +openmls.workspace = true +openssl-sys.workspace = true +openssl.workspace = true chrono = { workspace = true, features = ["clock"] } diesel = { workspace = true, features = [ "r2d2", "returning_clauses_for_sqlite_3_35", "sqlite", ] } -diesel_migrations = { workspace = true, features = ["sqlite"] } libsqlite3-sys = { workspace = true } -openmls = { workspace = true, features = ["test-utils"] } -openssl-sys.workspace = true -openssl.workspace = true tokio = { workspace = true, features = [ "macros", "tracing", @@ -113,30 +108,32 @@ tokio = { workspace = true, features = [ "rt-multi-thread", ] } xmtp_api_grpc = { path = "../xmtp_api_grpc", optional = true } - +dyn-clone.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] +openmls = { workspace = true, features = ["js"] } chrono = { workspace = true, features = ["wasmbind"] } diesel = { workspace = true, features = [ "r2d2", "returning_clauses_for_sqlite_3_35", ] } -diesel-wasm-sqlite = { workspace = true, features = ["r2d2"] } -diesel_migrations.workspace = true +diesel-wasm-sqlite = { workspace = true } getrandom = { workspace = true, features = ["js"] } gloo-timers = { workspace = true, features = ["futures"] } -openmls = { workspace = true, features = ["test-utils", "js"] } tokio = { workspace = true, features = ["macros", "rt", "time"] } wasm-bindgen-futures.workspace = true web-sys.workspace = true + [dev-dependencies] +openmls_basic_credential.workspace = true anyhow.workspace = true mockall = "0.13.0" xmtp_id = { path = "../xmtp_id", features = ["test-utils"] } -xmtp_proto = { workspace = true, features = ["test-utils"] } +xmtp_proto = { workspace = true, features = ["test-utils" ]} [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +openmls = { workspace = true } ctor.workspace = true ethers = { workspace = true, features = ["openssl"] } mockito = "1.4.0" @@ -150,6 +147,7 @@ xmtp_api_grpc = { path = "../xmtp_api_grpc", features = ["test-utils"] } xmtp_api_http = { path = "../xmtp_api_http", features = ["test-utils"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] +openmls = { workspace = true, features = ["js"] } console_error_panic_hook = { version = "0.1" } diesel-wasm-sqlite = { workspace = true, features = [ "unsafe-debug-query", diff --git a/xmtp_mls/src/builder.rs b/xmtp_mls/src/builder.rs index 85d060daf..f48cb0eda 100644 --- a/xmtp_mls/src/builder.rs +++ b/xmtp_mls/src/builder.rs @@ -227,10 +227,9 @@ pub(crate) mod tests { }; use openmls::credentials::{Credential, CredentialType}; - use openmls_basic_credential::SignatureKeyPair; - use openmls_traits::types::SignatureScheme; use prost::Message; use xmtp_cryptography::utils::{generate_local_wallet, rng}; + use xmtp_cryptography::XmtpInstallationCredential; use xmtp_id::associations::test_utils::MockSmartContractSignatureVerifier; use xmtp_id::associations::unverified::{ UnverifiedRecoverableEcdsaSignature, UnverifiedSignature, @@ -444,6 +443,9 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_2nd_time_client_creation() { let (legacy_key, legacy_account_address) = generate_random_legacy_key().await; + let id = generate_inbox_id(&legacy_account_address, &0).unwrap(); + println!("{}", id.len()); + let identity_strategy = IdentityStrategy::CreateIfNotFound( generate_inbox_id(&legacy_account_address, &0).unwrap(), legacy_account_address.clone(), @@ -613,7 +615,7 @@ pub(crate) mod tests { let stored: StoredIdentity = (&Identity { inbox_id: inbox_id.clone(), - installation_keys: SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(), + installation_keys: XmtpInstallationCredential::new(), credential: Credential::new(CredentialType::Basic, rand_vec()), signature_request: None, is_ready: AtomicBool::new(true), @@ -650,7 +652,7 @@ pub(crate) mod tests { let stored: StoredIdentity = (&Identity { inbox_id: stored_inbox_id.clone(), - installation_keys: SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(), + installation_keys: Default::default(), credential: Credential::new(CredentialType::Basic, rand_vec()), signature_request: None, is_ready: AtomicBool::new(true), diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index ebf5f369d..a14f2dcdd 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -256,7 +256,7 @@ pub struct XmtpMlsLocalContext { impl XmtpMlsLocalContext { /// The installation public key is the primary identifier for an installation pub fn installation_public_key(&self) -> Vec { - self.identity.installation_keys.to_public_vec() + self.identity.installation_keys.public_slice().to_vec() } /// Get the account address of the blockchain account associated with this client diff --git a/xmtp_mls/src/groups/group_metadata.rs b/xmtp_mls/src/groups/group_metadata.rs index 920450d43..b66fe3cc3 100644 --- a/xmtp_mls/src/groups/group_metadata.rs +++ b/xmtp_mls/src/groups/group_metadata.rs @@ -172,7 +172,6 @@ impl TryFrom for DmMembers { pub fn extract_group_metadata(group: &OpenMlsGroup) -> Result { let extension = group - .export_group_context() .extensions() .immutable_metadata() .ok_or(GroupMetadataError::MissingExtension)?; diff --git a/xmtp_mls/src/groups/group_mutable_metadata.rs b/xmtp_mls/src/groups/group_mutable_metadata.rs index c693782e5..36facf8d5 100644 --- a/xmtp_mls/src/groups/group_mutable_metadata.rs +++ b/xmtp_mls/src/groups/group_mutable_metadata.rs @@ -252,8 +252,8 @@ impl TryFrom<&OpenMlsGroup> for GroupMutableMetadata { type Error = GroupMutableMetadataError; /// Attempts to extract GroupMutableMetadata from an OpenMlsGroup. - fn try_from(value: &OpenMlsGroup) -> Result { - let extensions = value.export_group_context().extensions(); + fn try_from(group: &OpenMlsGroup) -> Result { + let extensions = group.extensions(); extensions.try_into() } } diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index d78a6f68d..62aedf158 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -148,7 +148,7 @@ impl TryFrom<&OpenMlsGroup> for GroupMutablePermissions { type Error = GroupMutablePermissionsError; fn try_from(value: &OpenMlsGroup) -> Result { - let extensions = value.export_group_context().extensions(); + let extensions = value.extensions(); extensions.try_into() } } @@ -157,7 +157,7 @@ impl TryFrom<&OpenMlsGroup> for GroupMutablePermissions { pub fn extract_group_permissions( group: &OpenMlsGroup, ) -> Result { - let extensions = group.export_group_context().extensions(); + let extensions = group.extensions(); extensions.try_into() } diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 91347c2f5..664ba318d 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -198,6 +198,8 @@ pub enum GroupError { SyncFailedToWait, #[error("cannot change metadata of DM")] DmGroupMetadataForbidden, + #[error("Group intent could not be committed")] + IntentNotCommitted, } impl RetryableError for GroupError { @@ -328,7 +330,7 @@ impl MlsGroup { &group_config, CredentialWithKey { credential: context.identity.credential(), - signature_key: context.identity.installation_keys.to_public_vec().into(), + signature_key: context.identity.installation_keys.public_slice().into(), }, )?; @@ -379,7 +381,7 @@ impl MlsGroup { &group_config, CredentialWithKey { credential: context.identity.credential(), - signature_key: context.identity.installation_keys.to_public_vec().into(), + signature_key: context.identity.installation_keys.public_slice().into(), }, )?; @@ -535,7 +537,7 @@ impl MlsGroup { &group_config, CredentialWithKey { credential: context.identity.credential(), - signature_key: context.identity.installation_keys.to_public_vec().into(), + signature_key: context.identity.installation_keys.public_slice().into(), }, )?; @@ -1109,7 +1111,7 @@ impl MlsGroup { &group_config, CredentialWithKey { credential: context.identity.credential(), - signature_key: context.identity.installation_keys.to_public_vec().into(), + signature_key: context.identity.installation_keys.public_slice().into(), }, )?; diff --git a/xmtp_mls/src/groups/node_sync.rs b/xmtp_mls/src/groups/node_sync.rs index 194ddb922..46d1f3316 100644 --- a/xmtp_mls/src/groups/node_sync.rs +++ b/xmtp_mls/src/groups/node_sync.rs @@ -45,16 +45,15 @@ use openmls::{ extensions::Extensions, framing::{ContentType, ProtocolMessage}, group::{GroupEpoch, StagedCommit}, + key_packages::KeyPackage, prelude::{ tls_codec::{Deserialize, Serialize}, LeafNodeIndex, MlsGroup as OpenMlsGroup, MlsMessageBodyIn, MlsMessageIn, PrivateMessageIn, ProcessedMessage, ProcessedMessageContent, Sender, }, - prelude_test::KeyPackage, treesync::LeafNodeParameters, }; -use openmls_basic_credential::SignatureKeyPair; -use openmls_traits::OpenMlsProvider; +use openmls_traits::{signatures::Signer, OpenMlsProvider}; use prost::bytes::Bytes; use prost::Message; use tracing::debug; @@ -193,9 +192,7 @@ where "not retrying intent ID {id}. since it is in state Error. {:?}", last_err ); - return Err(last_err.unwrap_or(GroupError::Generic( - "Group intent could not be committed".to_string(), - ))); + return Err(last_err.unwrap_or(GroupError::IntentNotCommitted)); } Ok(Some(StoredGroupIntent { id, state, .. })) => { tracing::warn!("retrying intent ID {id}. intent currently in state {state:?}"); @@ -1132,7 +1129,7 @@ async fn apply_update_group_membership_intent( provider: &XmtpOpenMlsProvider, openmls_group: &mut OpenMlsGroup, intent_data: UpdateGroupMembershipIntentData, - signer: &SignatureKeyPair, + signer: impl Signer, ) -> Result, GroupError> { let extensions: Extensions = openmls_group.extensions().clone(); @@ -1193,7 +1190,7 @@ async fn apply_update_group_membership_intent( // Create the commit let (commit, maybe_welcome_message, _) = openmls_group.update_group_membership( provider, - signer, + &signer, &new_key_packages, &leaf_nodes_to_remove, new_extensions, @@ -1232,12 +1229,13 @@ fn get_and_clear_pending_commit( openmls_group: &mut OpenMlsGroup, provider: &XmtpOpenMlsProvider, ) -> Result>, GroupError> { - // TODO: remove clone - if let Some(commit) = openmls_group.clone().pending_commit() { - openmls_group.clear_pending_commit(provider.storage())?; - return Ok(Some(db_serialize(&commit)?)); - } - Ok(None) + let commit = openmls_group + .pending_commit() + .as_ref() + .map(db_serialize) + .transpose()?; + openmls_group.clear_pending_commit(provider.storage())?; + Ok(commit) } fn decode_staged_commit(data: Vec) -> Result { diff --git a/xmtp_mls/src/groups/validated_commit.rs b/xmtp_mls/src/groups/validated_commit.rs index 53fe5a227..567603a3d 100644 --- a/xmtp_mls/src/groups/validated_commit.rs +++ b/xmtp_mls/src/groups/validated_commit.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use openmls::{ credentials::{errors::BasicCredentialError, BasicCredential, Credential as OpenMlsCredential}, extensions::{Extension, Extensions, UnknownExtension}, - group::{GroupContext, MlsGroup as OpenMlsGroup, StagedCommit}, + group::{MlsGroup as OpenMlsGroup, StagedCommit}, messages::proposals::Proposal, prelude::{LeafNodeIndex, Sender}, treesync::LeafNode, @@ -228,18 +228,18 @@ impl ValidatedCommit { let group_permissions: GroupMutablePermissions = extensions.try_into()?; let current_group_members = get_current_group_members(openmls_group); - let existing_group_context = openmls_group.export_group_context(); - let new_group_context = staged_commit.group_context(); + let existing_group_extensions = openmls_group.extensions(); + let new_group_extensions = staged_commit.group_context().extensions(); let metadata_changes = extract_metadata_changes( &immutable_metadata, &mutable_metadata, - existing_group_context, - new_group_context, + existing_group_extensions, + new_group_extensions, )?; let permissions_changed = - extract_permissions_changed(&group_permissions, new_group_context)?; + extract_permissions_changed(&group_permissions, new_group_extensions)?; // Get the actor who created the commit. // Because we don't allow for multiple actors in a commit, this will error if two proposals come from different authors. let actor = extract_actor( @@ -278,7 +278,7 @@ impl ValidatedCommit { conn, &client, staged_commit, - existing_group_context, + existing_group_extensions, &immutable_metadata, &mutable_metadata, ) @@ -465,11 +465,11 @@ async fn extract_expected_diff<'diff>( conn: &DbConnection, client: impl ScopedGroupClient, staged_commit: &StagedCommit, - existing_group_context: &GroupContext, + existing_group_extensions: &Extensions, immutable_metadata: &GroupMetadata, mutable_metadata: &GroupMutableMetadata, ) -> Result { - let old_group_membership = extract_group_membership(existing_group_context.extensions())?; + let old_group_membership = extract_group_membership(existing_group_extensions)?; let new_group_membership = get_latest_group_membership(staged_commit)?; let membership_diff = old_group_membership.diff(&new_group_membership); @@ -626,12 +626,12 @@ fn extract_metadata_changes( immutable_metadata: &GroupMetadata, // We already have the old mutable metadata, so save parsing it a second time old_mutable_metadata: &GroupMutableMetadata, - old_group_context: &GroupContext, - new_group_context: &GroupContext, + old_group_extensions: &Extensions, + new_group_extensions: &Extensions, ) -> Result { - let old_mutable_metadata_ext = find_mutable_metadata_extension(old_group_context.extensions()) + let old_mutable_metadata_ext = find_mutable_metadata_extension(old_group_extensions) .ok_or(CommitValidationError::MissingMutableMetadata)?; - let new_mutable_metadata_ext = find_mutable_metadata_extension(new_group_context.extensions()) + let new_mutable_metadata_ext = find_mutable_metadata_extension(new_group_extensions) .ok_or(CommitValidationError::MissingMutableMetadata)?; // Before even decoding the new metadata, make sure that something has changed. Otherwise we know there is @@ -678,10 +678,9 @@ fn extract_metadata_changes( // Returns true if the permissions have changed, false otherwise fn extract_permissions_changed( old_group_permissions: &GroupMutablePermissions, - new_group_context: &GroupContext, + new_group_extensions: &Extensions, ) -> Result { - let new_group_permissions: GroupMutablePermissions = - new_group_context.extensions().try_into()?; + let new_group_permissions: GroupMutablePermissions = new_group_extensions.try_into()?; Ok(!old_group_permissions.eq(&new_group_permissions)) } diff --git a/xmtp_mls/src/identity.rs b/xmtp_mls/src/identity.rs index b273d3a26..322b92d8c 100644 --- a/xmtp_mls/src/identity.rs +++ b/xmtp_mls/src/identity.rs @@ -1,4 +1,3 @@ -use std::array::TryFromSliceError; use std::sync::atomic::{AtomicBool, Ordering}; use crate::configuration::GROUP_PERMISSIONS_EXTENSION_ID; @@ -15,28 +14,25 @@ use crate::{ XmtpApi, }; use crate::{retryable, Fetch, Store}; -use ed25519_dalek::SigningKey; use openmls::prelude::hash_ref::HashReference; -use openmls::prelude::tls_codec::Serialize; use openmls::{ credentials::{errors::BasicCredentialError, BasicCredential, CredentialWithKey}, extensions::{ ApplicationIdExtension, Extension, ExtensionType, Extensions, LastResortExtension, }, + key_packages::KeyPackage, messages::proposals::ProposalType, - prelude::{Capabilities, Credential as OpenMlsCredential}, - prelude_test::KeyPackage, + prelude::{tls_codec::Serialize, Capabilities, Credential as OpenMlsCredential}, }; -use openmls_basic_credential::SignatureKeyPair; use openmls_traits::storage::StorageProvider; use openmls_traits::types::CryptoError; use openmls_traits::OpenMlsProvider; use prost::Message; -use sha2::{Digest, Sha512}; use thiserror::Error; use tracing::debug; use tracing::info; -use xmtp_id::associations::unverified::{UnverifiedInstallationKeySignature, UnverifiedSignature}; +use xmtp_cryptography::{CredentialSign, XmtpInstallationCredential}; +use xmtp_id::associations::unverified::UnverifiedSignature; use xmtp_id::associations::AssociationError; use xmtp_id::scw_verifier::SmartContractSignatureVerifier; use xmtp_id::{ @@ -44,7 +40,6 @@ use xmtp_id::{ builder::{SignatureRequest, SignatureRequestBuilder, SignatureRequestError}, generate_inbox_id, sign_with_legacy_key, MemberIdentifier, }, - constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, InboxId, }; use xmtp_proto::xmtp::identity::MlsCredential; @@ -176,8 +171,6 @@ pub enum IdentityError { OpenMlsStorageError(#[from] SqlKeyStoreError), #[error(transparent)] KeyPackageGenerationError(#[from] openmls::key_packages::errors::KeyPackageNewError), - #[error(transparent)] - ED25519Error(#[from] ed25519_dalek::ed25519::Error), #[error("The InboxID {id}, associated does not match the stored InboxId {stored}.")] InboxIdMismatch { id: InboxId, stored: InboxId }, #[error("The address {0} has no associated InboxID")] @@ -190,6 +183,8 @@ pub enum IdentityError { DieselResult(#[from] diesel::result::Error), #[error(transparent)] Association(#[from] AssociationError), + #[error(transparent)] + Signer(#[from] xmtp_cryptography::SignerError), } impl RetryableError for IdentityError { @@ -208,7 +203,7 @@ impl RetryableError for IdentityError { #[derive(Debug)] pub struct Identity { pub(crate) inbox_id: InboxId, - pub(crate) installation_keys: SignatureKeyPair, + pub(crate) installation_keys: XmtpInstallationCredential, pub(crate) credential: OpenMlsCredential, pub(crate) signature_request: Option, pub(crate) is_ready: AtomicBool, @@ -249,8 +244,7 @@ impl Identity { let address = address.to_lowercase(); let inbox_ids = api_client.get_inbox_ids(vec![address.clone()]).await?; let associated_inbox_id = inbox_ids.get(&address); - let signature_keys = SignatureKeyPair::new(CIPHERSUITE.signature_algorithm())?; - let installation_public_key = signature_keys.public(); + let installation_keys = XmtpInstallationCredential::new(); let member_identifier: MemberIdentifier = address.clone().to_lowercase().into(); if let Some(associated_inbox_id) = associated_inbox_id { @@ -261,17 +255,19 @@ impl Identity { } let builder = SignatureRequestBuilder::new(associated_inbox_id.clone()); let mut signature_request = builder - .add_association(installation_public_key.to_vec().into(), member_identifier) + .add_association( + installation_keys.public_slice().to_vec().into(), + member_identifier, + ) .build(); + let signature = + installation_keys.credential_sign(signature_request.signature_text())?; signature_request .add_signature( - UnverifiedSignature::InstallationKey( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, + UnverifiedSignature::new_installation_key( + signature, + installation_keys.verifying_key(), ), scw_signature_verifier, ) @@ -279,7 +275,7 @@ impl Identity { let identity = Self { inbox_id: associated_inbox_id.clone(), - installation_keys: signature_keys, + installation_keys, credential: create_credential(associated_inbox_id.clone())?, signature_request: Some(signature_request), is_ready: AtomicBool::new(false), @@ -303,17 +299,19 @@ impl Identity { let mut builder = SignatureRequestBuilder::new(inbox_id.clone()); builder = builder.create_inbox(member_identifier.clone(), nonce); let mut signature_request = builder - .add_association(installation_public_key.to_vec().into(), member_identifier) + .add_association( + installation_keys.public_slice().to_vec().into(), + member_identifier, + ) .build(); + let sig = installation_keys.credential_sign(signature_request.signature_text())?; + signature_request .add_signature( - UnverifiedSignature::InstallationKey( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, + UnverifiedSignature::new_installation_key( + sig, + installation_keys.verifying_key(), ), &scw_signature_verifier, ) @@ -334,7 +332,7 @@ impl Identity { // Make sure to register the identity before applying the signature request let identity = Self { inbox_id: inbox_id.clone(), - installation_keys: signature_keys, + installation_keys, credential: create_credential(inbox_id)?, signature_request: None, is_ready: AtomicBool::new(true), @@ -357,18 +355,19 @@ impl Identity { builder = builder.create_inbox(member_identifier.clone(), nonce); let mut signature_request = builder - .add_association(installation_public_key.to_vec().into(), member_identifier) + .add_association( + installation_keys.public_slice().to_vec().into(), + member_identifier, + ) .build(); + let sig = installation_keys.credential_sign(signature_request.signature_text())?; // We can pre-sign the request with an installation key signature, since we have access to the key signature_request .add_signature( - UnverifiedSignature::InstallationKey( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, + UnverifiedSignature::new_installation_key( + sig, + installation_keys.verifying_key(), ), scw_signature_verifier, ) @@ -376,7 +375,7 @@ impl Identity { let identity = Self { inbox_id: inbox_id.clone(), - installation_keys: signature_keys, + installation_keys, credential: create_credential(inbox_id.clone())?, signature_request: Some(signature_request), is_ready: AtomicBool::new(false), @@ -411,12 +410,9 @@ impl Identity { * Sign the given text with the installation private key. */ pub(crate) fn sign>(&self, text: Text) -> Result, IdentityError> { - let mut prehashed = Sha512::new(); - prehashed.update(text.as_ref()); - let k = ed25519_dalek::SigningKey::try_from(self.installation_keys.private()) - .expect("signing key is invalid"); - let signature = k.sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT))?; - Ok(signature.to_vec()) + self.installation_keys + .credential_sign(text) + .map_err(Into::into) } /// Generate a new key package and store the associated keys in the database. @@ -455,7 +451,7 @@ impl Identity { &self.installation_keys, CredentialWithKey { credential: self.credential(), - signature_key: self.installation_keys.to_public_vec().into(), + signature_key: self.installation_keys.public_slice().into(), }, )?; // Store the hash reference, keyed with the public init key. @@ -550,27 +546,6 @@ fn deserialize_key_package_hash_ref(hash_ref: &[u8]) -> Result Result { - let signing_key: SigningKey = SigningKey::from_bytes(installation_private_key); - let verifying_key = signing_key.verifying_key(); - let mut prehashed: Sha512 = Sha512::new(); - prehashed.update(signature_text.clone()); - let sig = signing_key.sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT))?; - let unverified_sig = - UnverifiedInstallationKeySignature::new(sig.to_vec(), verifying_key.as_bytes().to_vec()); - - Ok(unverified_sig) -} - -fn sized_installation_key(installation_key: &[u8]) -> Result<&[u8; 32], IdentityError> { - installation_key - .try_into() - .map_err(|e: TryFromSliceError| IdentityError::InstallationKey(e.to_string())) -} - fn create_credential(inbox_id: InboxId) -> Result { let cred = MlsCredential { inbox_id }; let mut credential_bytes = Vec::new(); diff --git a/xmtp_mls/src/identity_updates.rs b/xmtp_mls/src/identity_updates.rs index 7183c31c7..b3feb7da6 100644 --- a/xmtp_mls/src/identity_updates.rs +++ b/xmtp_mls/src/identity_updates.rs @@ -248,13 +248,16 @@ where ) -> Result { let nonce = maybe_nonce.unwrap_or(0); let inbox_id = generate_inbox_id(&wallet_address, &nonce)?; - let installation_public_key = self.identity().installation_keys.public(); + let installation_public_key = self.identity().installation_keys.verifying_key(); let member_identifier: MemberIdentifier = wallet_address.to_lowercase().into(); let builder = SignatureRequestBuilder::new(inbox_id); let mut signature_request = builder .create_inbox(member_identifier.clone(), nonce) - .add_association(installation_public_key.to_vec().into(), member_identifier) + .add_association( + installation_public_key.as_bytes().to_vec().into(), + member_identifier, + ) .build(); let sig_bytes = self @@ -266,7 +269,7 @@ where .add_signature( UnverifiedSignature::InstallationKey(UnverifiedInstallationKeySignature::new( sig_bytes, - installation_public_key.to_vec(), + installation_public_key, )), &self.scw_verifier, ) diff --git a/xmtp_proto/src/api_client.rs b/xmtp_proto/src/api_client.rs index 9ae07b664..ab02a0443 100644 --- a/xmtp_proto/src/api_client.rs +++ b/xmtp_proto/src/api_client.rs @@ -55,9 +55,7 @@ pub mod trait_impls { #[cfg(all(not(feature = "test-utils"), target_arch = "wasm32"))] mod inner { - use crate::api_client::{ - ClientWithMetadata, XmtpIdentityClient, XmtpMlsClient, XmtpMlsStreams, - }; + use crate::api_client::{ClientWithMetadata, XmtpIdentityClient, XmtpMlsClient}; pub trait XmtpApi where Self: XmtpMlsClient + XmtpIdentityClient + ClientWithMetadata,