diff --git a/Cargo.lock b/Cargo.lock index dac2f0a..c2692ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -43,9 +78,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "flate2", "futures-core", @@ -62,7 +97,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -148,10 +183,10 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -198,6 +233,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -316,14 +363,14 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] name = "cc" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" @@ -358,6 +405,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -380,6 +437,16 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "coset" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8cc80f631f8307b887faca24dcc3abc427cd0367f6eb6188f6e8f5b7ad8fb" +dependencies = [ + "ciborium", + "ciborium-io", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -429,9 +496,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -456,7 +533,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -475,6 +552,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.10.7" @@ -602,7 +688,7 @@ name = "eth-canister" version = "0.1.0" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", "bytes", "candid", "ciborium", @@ -620,7 +706,7 @@ name = "eth-canister-lite" version = "0.1.0" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", "bytes", "candid", "ciborium", @@ -757,7 +843,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -812,6 +898,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.29.0" @@ -870,6 +966,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -881,6 +983,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-conservative" @@ -977,7 +1082,7 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -1046,7 +1151,7 @@ dependencies = [ "quote", "serde", "serde_tokenstream", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1078,6 +1183,32 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de254dd67bbd58073e23dc1c8553ba12fa1dc610a19de94ad2bbcd0460c067f" +[[package]] +name = "ic_cose_types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a97f295eea4a1fc5cf82eba99688b02cd566ed888ac89841c820ac321cf55a1" +dependencies = [ + "aes-gcm", + "base64 0.21.7", + "candid", + "ciborium", + "coset", + "crc32fast", + "ed25519-dalek", + "hex", + "hmac", + "icrc-ledger-types", + "k256", + "num-traits", + "serde", + "serde_bytes", + "sha2", + "sha3", + "url", + "x25519-dalek", +] + [[package]] name = "ic_principal" version = "0.1.1" @@ -1091,19 +1222,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "icrc-ledger-types" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f7f6b54df25295dd0ce2722d583c15e2ee7eec9cef58c10b424feb54561b2" +dependencies = [ + "base32", + "candid", + "crc32fast", + "hex", + "itertools", + "num-bigint", + "num-traits", + "serde", + "serde_bytes", + "sha2", + "strum", + "time", +] + [[package]] name = "idempotent-proxy-canister" version = "1.1.6" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "candid", "ciborium", "futures", + "getrandom", "http", "ic-cdk", "ic-cdk-timers", "ic-stable-structures", + "ic_cose_types", "serde", "serde_bytes", "serde_json", @@ -1118,7 +1271,7 @@ dependencies = [ "async-trait", "axum", "axum-server", - "base64", + "base64 0.22.1", "bb8", "ciborium", "dotenvy", @@ -1143,7 +1296,7 @@ dependencies = [ name = "idempotent-proxy-types" version = "1.1.6" dependencies = [ - "base64", + "base64 0.22.1", "ciborium", "ed25519-dalek", "hex-conservative", @@ -1176,12 +1329,30 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1238,6 +1409,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1293,13 +1470,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1330,6 +1508,12 @@ dependencies = [ "serde", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -1346,23 +1530,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", + "libm", ] [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -1373,11 +1548,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -1396,7 +1577,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1407,9 +1588,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -1469,7 +1650,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1500,6 +1681,24 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1546,7 +1745,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "thiserror", "tokio", "tracing", @@ -1562,7 +1761,7 @@ dependencies = [ "rand", "ring", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "slab", "thiserror", "tinyvec", @@ -1571,14 +1770,13 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", "socket2", - "tracing", "windows-sys 0.52.0", ] @@ -1637,7 +1835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "async-compression", - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -1659,7 +1857,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", @@ -1781,14 +1979,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.5", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] @@ -1812,7 +2010,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -1834,9 +2032,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ "ring", "rustls-pki-types", @@ -1949,7 +2147,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1991,7 +2189,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2125,6 +2323,28 @@ dependencies = [ "tokio", ] +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.72", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2222,9 +2442,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -2293,7 +2513,38 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", ] [[package]] @@ -2313,32 +2564,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2367,7 +2617,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] @@ -2433,7 +2683,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2496,6 +2746,16 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2557,9 +2817,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -2597,7 +2857,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -2631,7 +2891,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2845,8 +3105,34 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] diff --git a/src/idempotent-proxy-canister/Cargo.toml b/src/idempotent-proxy-canister/Cargo.toml index 7ddb5f3..3ebbac5 100644 --- a/src/idempotent-proxy-canister/Cargo.toml +++ b/src/idempotent-proxy-canister/Cargo.toml @@ -16,11 +16,6 @@ license.workspace = true crate-type = ["cdylib"] [dependencies] -bytes = "1.6" -candid = "0.10" -ic-cdk = "0.14" -ic-cdk-timers = "0.8" -ic-stable-structures = "0.6" http = { workspace = true } base64 = { workspace = true } ciborium = { workspace = true } @@ -29,3 +24,10 @@ serde = { workspace = true } serde_json = { workspace = true } serde_bytes = { workspace = true } sha3 = { workspace = true } +bytes = "1.6" +candid = "0.10" +ic-cdk = "0.14" +ic-cdk-timers = "0.8" +ic-stable-structures = "0.6" +ic_cose_types = "0.1" +getrandom = { version = "0.2", features = ["custom"] } diff --git a/src/idempotent-proxy-canister/idempotent-proxy-canister.did b/src/idempotent-proxy-canister/idempotent-proxy-canister.did index 1c3c092..61a137c 100644 --- a/src/idempotent-proxy-canister/idempotent-proxy-canister.did +++ b/src/idempotent-proxy-canister/idempotent-proxy-canister.did @@ -13,6 +13,7 @@ type CanisterHttpRequestArgument = record { headers : vec HttpHeader; }; type ChainArgs = variant { Upgrade : UpgradeArgs; Init : InitArgs }; +type CoseClient = record { id : principal; namespace : text }; type HttpHeader = record { value : text; name : text }; type HttpMethod = variant { get; head; post }; type HttpResponse = record { @@ -23,18 +24,19 @@ type HttpResponse = record { type InitArgs = record { service_fee : nat64; ecdsa_key_name : text; + cose : opt CoseClient; proxy_token_refresh_interval : nat64; subnet_size : nat64; }; type Result = variant { Ok : bool; Err : text }; type Result_1 = variant { Ok; Err : text }; -type Result_2 = variant { Ok : State; Err }; -type State = record { +type Result_2 = variant { Ok : StateInfo; Err }; +type StateInfo = record { proxy_token_public_key : text; service_fee : nat64; ecdsa_key_name : text; managers : vec principal; - allowed_callers : vec principal; + cose : opt CoseClient; uncollectible_cycles : nat; agents : vec Agent; incoming_cycles : nat; @@ -48,6 +50,7 @@ type TransformContext = record { }; type UpgradeArgs = record { service_fee : opt nat64; + cose : opt CoseClient; proxy_token_refresh_interval : opt nat64; subnet_size : opt nat64; }; diff --git a/src/idempotent-proxy-canister/src/cose.rs b/src/idempotent-proxy-canister/src/cose.rs new file mode 100644 index 0000000..ac88c8f --- /dev/null +++ b/src/idempotent-proxy-canister/src/cose.rs @@ -0,0 +1,62 @@ +use candid::{utils::ArgumentEncoder, CandidType, Principal}; +use ic_cose_types::types::{PublicKeyInput, PublicKeyOutput, SignInput}; +use serde::{Deserialize, Serialize}; +use serde_bytes::ByteBuf; + +#[derive(CandidType, Clone, Debug, Deserialize, Serialize)] +pub struct CoseClient { + pub id: Principal, + pub namespace: String, +} + +impl CoseClient { + pub async fn ecdsa_public_key(&self, derivation_path: Vec) -> Result { + let output: Result = call( + self.id, + "ecdsa_public_key", + (Some(PublicKeyInput { + ns: self.namespace.clone(), + derivation_path, + }),), + 0, + ) + .await?; + let output = output?; + Ok(output.public_key) + } + + pub async fn ecdsa_sign( + &self, + derivation_path: Vec, + message: ByteBuf, + ) -> Result { + let output: Result = call( + self.id, + "ecdsa_sign", + (SignInput { + ns: self.namespace.clone(), + derivation_path, + message, + },), + 0, + ) + .await?; + output + } +} + +async fn call(id: Principal, method: &str, args: In, cycles: u128) -> Result +where + In: ArgumentEncoder + Send, + Out: candid::CandidType + for<'a> candid::Deserialize<'a>, +{ + let (res,): (Out,) = ic_cdk::api::call::call_with_payment128(id, method, args, cycles) + .await + .map_err(|(code, msg)| { + format!( + "failed to call {} on {:?}, code: {}, message: {}", + method, &id, code as u32, msg + ) + })?; + Ok(res) +} diff --git a/src/idempotent-proxy-canister/src/ecdsa.rs b/src/idempotent-proxy-canister/src/ecdsa.rs index e092897..67ebeef 100644 --- a/src/idempotent-proxy-canister/src/ecdsa.rs +++ b/src/idempotent-proxy-canister/src/ecdsa.rs @@ -1,31 +1,4 @@ -use base64::{engine::general_purpose::URL_SAFE_NO_PAD as base64_url, Engine}; -use ciborium::into_writer; use ic_cdk::api::management_canister::ecdsa; -use serde_bytes::ByteBuf; -use sha3::{Digest, Sha3_256}; - -// use Idempotent Proxy's Token: Token(pub u64, pub String, pub ByteBuf); -// https://github.com/ldclabs/idempotent-proxy/blob/main/src/idempotent-proxy-types/src/auth.rs#L15 -pub async fn sign_proxy_token( - key_name: &str, - expire_at: u64, // UNIX timestamp, in seconds - message: &str, // use RPCAgent.name as message -) -> Result { - let mut buf: Vec = Vec::new(); - into_writer(&(expire_at, message), &mut buf).expect("failed to encode Token in CBOR format"); - let digest = sha3_256(&buf); - let sig = sign_with(key_name, vec![b"sign_proxy_token".to_vec()], digest) - .await - .map_err(err_string)?; - buf.clear(); - into_writer(&(expire_at, message, ByteBuf::from(sig)), &mut buf).map_err(err_string)?; - Ok(base64_url.encode(buf)) -} - -pub async fn get_proxy_token_public_key(key_name: &str) -> Result { - let pk = public_key_with(key_name, vec![b"sign_proxy_token".to_vec()]).await?; - Ok(base64_url.encode(pk.public_key)) -} pub async fn sign_with( key_name: &str, @@ -67,13 +40,3 @@ pub async fn public_key_with( Ok(response) } - -pub fn err_string(err: impl std::fmt::Display) -> String { - err.to_string() -} - -pub fn sha3_256(data: &[u8]) -> [u8; 32] { - let mut hasher = Sha3_256::new(); - hasher.update(data); - hasher.finalize().into() -} diff --git a/src/idempotent-proxy-canister/src/init.rs b/src/idempotent-proxy-canister/src/init.rs index f4cf7a9..13d9b8d 100644 --- a/src/idempotent-proxy-canister/src/init.rs +++ b/src/idempotent-proxy-canister/src/init.rs @@ -2,7 +2,7 @@ use candid::CandidType; use serde::Deserialize; use std::time::Duration; -use crate::{store, tasks}; +use crate::{cose::CoseClient, store, tasks}; #[derive(Clone, Debug, CandidType, Deserialize)] pub enum ChainArgs { @@ -16,6 +16,7 @@ pub struct InitArgs { proxy_token_refresh_interval: u64, // seconds subnet_size: u64, // set to 0 to disable receiving cycles service_fee: u64, // in cycles + cose: Option, } #[derive(Clone, Debug, CandidType, Deserialize)] @@ -23,6 +24,7 @@ pub struct UpgradeArgs { proxy_token_refresh_interval: Option, // seconds subnet_size: Option, service_fee: Option, // in cycles + cose: Option, } #[ic_cdk::init] @@ -42,6 +44,7 @@ fn init(args: Option) { } else { 100_000_000 }; + s.cose = args.cose; }); } ChainArgs::Upgrade(_) => { @@ -89,6 +92,9 @@ fn post_upgrade(args: Option) { if let Some(service_fee) = args.service_fee { s.service_fee = service_fee; } + if let Some(cose) = args.cose { + s.cose = Some(cose); + } }); } Some(ChainArgs::Init(_)) => { @@ -101,6 +107,7 @@ fn post_upgrade(args: Option) { ic_cdk_timers::set_timer(Duration::from_secs(0), || { ic_cdk::spawn(async { + store::state::init_ecdsa_public_key().await; tasks::refresh_proxy_token().await; }) }); diff --git a/src/idempotent-proxy-canister/src/lib.rs b/src/idempotent-proxy-canister/src/lib.rs index 1f01aae..eef0132 100644 --- a/src/idempotent-proxy-canister/src/lib.rs +++ b/src/idempotent-proxy-canister/src/lib.rs @@ -1,17 +1,19 @@ -use candid::{Nat, Principal}; +use candid::{CandidType, Nat, Principal}; use ciborium::into_writer; use futures::FutureExt; use ic_cdk::api::management_canister::http_request::{CanisterHttpRequestArgument, HttpResponse}; +use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; mod agent; +mod cose; mod cycles; mod ecdsa; mod init; mod store; mod tasks; -use crate::init::ChainArgs; +use crate::{agent::Agent, cose::CoseClient, init::ChainArgs}; static ANONYMOUS: Principal = Principal::anonymous(); @@ -39,9 +41,9 @@ fn validate_admin_set_managers(args: BTreeSet) -> Result<(), String> async fn admin_set_agents(agents: Vec) -> Result<(), String> { validate_admin_set_agents(agents.clone())?; - let (ecdsa_key_name, proxy_token_refresh_interval) = - store::state::with(|s| (s.ecdsa_key_name.clone(), s.proxy_token_refresh_interval)); - tasks::update_proxy_token(ecdsa_key_name, proxy_token_refresh_interval, agents).await; + let (signer, proxy_token_refresh_interval) = + store::state::with(|s| (s.signer(), s.proxy_token_refresh_interval)); + tasks::update_proxy_token(signer, proxy_token_refresh_interval, agents).await; Ok(()) } @@ -64,14 +66,43 @@ fn admin_remove_caller(id: Principal) -> Result { store::state::with_mut(|r| Ok(r.allowed_callers.remove(&id))) } +#[derive(CandidType, Deserialize, Serialize)] +pub struct StateInfo { + pub ecdsa_key_name: String, + pub proxy_token_public_key: String, + pub proxy_token_refresh_interval: u64, // seconds + pub agents: Vec, + pub managers: BTreeSet, + pub subnet_size: u64, + pub service_fee: u64, // in cycles + pub incoming_cycles: u128, + pub uncollectible_cycles: u128, + pub cose: Option, +} + #[ic_cdk::query] -fn get_state() -> Result { - let mut s = store::state::with(|s| s.clone()); - if is_controller_or_manager().is_err() { - s.agents.iter_mut().for_each(|a| { - a.proxy_token = None; - }) - } +fn get_state() -> Result { + let s = store::state::with(|s| StateInfo { + ecdsa_key_name: s.ecdsa_key_name.clone(), + proxy_token_public_key: s.proxy_token_public_key.clone(), + proxy_token_refresh_interval: s.proxy_token_refresh_interval, + agents: s + .agents + .iter() + .map(|a| Agent { + name: a.name.clone(), + endpoint: a.endpoint.clone(), + max_cycles: a.max_cycles, + proxy_token: a.proxy_token.clone(), + }) + .collect(), + managers: s.managers.clone(), + subnet_size: s.subnet_size, + service_fee: s.service_fee, + incoming_cycles: s.incoming_cycles, + uncollectible_cycles: s.uncollectible_cycles, + cose: s.cose.clone(), + }); Ok(s) } @@ -256,4 +287,21 @@ fn is_controller_or_manager() -> Result<(), String> { } } +#[cfg(all( + target_arch = "wasm32", + target_vendor = "unknown", + target_os = "unknown" +))] +/// A getrandom implementation that always fails +pub fn always_fail(_buf: &mut [u8]) -> Result<(), getrandom::Error> { + Err(getrandom::Error::UNSUPPORTED) +} + +#[cfg(all( + target_arch = "wasm32", + target_vendor = "unknown", + target_os = "unknown" +))] +getrandom::register_custom_getrandom!(always_fail); + ic_cdk::export_candid!(); diff --git a/src/idempotent-proxy-canister/src/store.rs b/src/idempotent-proxy-canister/src/store.rs index 8100e6a..7adc1e9 100644 --- a/src/idempotent-proxy-canister/src/store.rs +++ b/src/idempotent-proxy-canister/src/store.rs @@ -1,18 +1,26 @@ -use candid::{CandidType, Principal}; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD as base64_url, Engine}; +use candid::Principal; use ciborium::{from_reader, into_writer}; +use ic_cose_types::cose::{format_error, sha3_256}; use ic_stable_structures::{ memory_manager::{MemoryId, MemoryManager, VirtualMemory}, storable::Bound, DefaultMemoryImpl, StableCell, Storable, }; use serde::{Deserialize, Serialize}; +use serde_bytes::ByteBuf; use std::{borrow::Cow, cell::RefCell, collections::BTreeSet}; -use crate::{agent::Agent, cycles::Calculator, ecdsa::get_proxy_token_public_key}; +use crate::{ + agent::Agent, + cose::CoseClient, + cycles::Calculator, + ecdsa::{public_key_with, sign_with}, +}; type Memory = VirtualMemory; -#[derive(CandidType, Clone, Default, Deserialize, Serialize)] +#[derive(Clone, Default, Deserialize, Serialize)] pub struct State { pub ecdsa_key_name: String, pub proxy_token_public_key: String, @@ -28,6 +36,18 @@ pub struct State { pub incoming_cycles: u128, #[serde(default)] pub uncollectible_cycles: u128, + + #[serde(default)] + pub cose: Option, +} + +impl State { + pub fn signer(&self) -> Signer { + Signer { + key_name: self.ecdsa_key_name.clone(), + cose: self.cose.clone(), + } + } } impl Storable for State { @@ -44,6 +64,57 @@ impl Storable for State { } } +pub struct Signer { + pub key_name: String, + pub cose: Option, +} + +static SIGN_PROXY_TOKEN_PATH: &[u8] = b"sign_proxy_token"; + +impl Signer { + pub async fn ecdsa_public_key(&self) -> Result { + match self.cose { + Some(ref cose) => cose + .ecdsa_public_key(vec![ByteBuf::from(SIGN_PROXY_TOKEN_PATH)]) + .await + .map(|v| base64_url.encode(v)), + None => public_key_with(&self.key_name, vec![SIGN_PROXY_TOKEN_PATH.to_vec()]) + .await + .map(|v| base64_url.encode(v.public_key)), + } + } + + // use Idempotent Proxy's Token: Token(pub u64, pub String, pub ByteBuf); + // https://github.com/ldclabs/idempotent-proxy/blob/main/src/idempotent-proxy-types/src/auth.rs#L15 + pub async fn sign_proxy_token( + &self, + expire_at: u64, // UNIX timestamp, in seconds + message: &str, // use RPCAgent.name as message + ) -> Result { + let mut buf: Vec = Vec::new(); + into_writer(&(expire_at, message), &mut buf) + .expect("failed to encode Token in CBOR format"); + let digest = sha3_256(&buf); + + let sig = match self.cose { + Some(ref cose) => { + cose.ecdsa_sign( + vec![ByteBuf::from(SIGN_PROXY_TOKEN_PATH)], + ByteBuf::from(digest), + ) + .await + } + None => sign_with(&self.key_name, vec![SIGN_PROXY_TOKEN_PATH.to_vec()], digest) + .await + .map(ByteBuf::from), + }; + + buf.clear(); + into_writer(&(expire_at, message, sig?), &mut buf).map_err(format_error)?; + Ok(base64_url.encode(buf)) + } +} + const STATE_MEMORY_ID: MemoryId = MemoryId::new(0); thread_local! { @@ -112,27 +183,6 @@ pub mod state { }); } - pub async fn init_ecdsa_public_key() { - let ecdsa_key_name = with(|r| { - if r.proxy_token_public_key.is_empty() && !r.ecdsa_key_name.is_empty() { - Some(r.ecdsa_key_name.clone()) - } else { - None - } - }); - - if let Some(ecdsa_key_name) = ecdsa_key_name { - let pk = get_proxy_token_public_key(&ecdsa_key_name) - .await - .unwrap_or_else(|err| { - ic_cdk::trap(&format!("failed to retrieve ECDSA public key: {err}")) - }); - with_mut(|r| { - r.proxy_token_public_key = pk; - }); - } - } - pub fn load() { STATE_STORE.with(|r| { let s = r.borrow_mut().get().clone(); @@ -151,4 +201,20 @@ pub mod state { }); }); } + + pub async fn init_ecdsa_public_key() { + let signer = with(|r| r.signer()); + + match signer.ecdsa_public_key().await { + Ok(public_key) => { + ic_cdk::print("successfully retrieved ECDSA public key"); + with_mut(|r| { + r.proxy_token_public_key = public_key; + }); + } + Err(err) => { + ic_cdk::print(&format!("failed to retrieve ECDSA public key: {err}")); + } + } + } } diff --git a/src/idempotent-proxy-canister/src/tasks.rs b/src/idempotent-proxy-canister/src/tasks.rs index 5372682..2663a2a 100644 --- a/src/idempotent-proxy-canister/src/tasks.rs +++ b/src/idempotent-proxy-canister/src/tasks.rs @@ -1,22 +1,17 @@ use std::collections::BTreeMap; -use crate::{agent::Agent, ecdsa, store}; +use crate::{agent::Agent, store}; const SECONDS: u64 = 1_000_000_000; pub async fn refresh_proxy_token() { - let (ecdsa_key_name, proxy_token_refresh_interval, agents) = store::state::with(|s| { - ( - s.ecdsa_key_name.clone(), - s.proxy_token_refresh_interval, - s.agents.clone(), - ) - }); - update_proxy_token(ecdsa_key_name, proxy_token_refresh_interval, agents).await; + let (signer, proxy_token_refresh_interval, agents) = + store::state::with(|s| (s.signer(), s.proxy_token_refresh_interval, s.agents.clone())); + update_proxy_token(signer, proxy_token_refresh_interval, agents).await; } pub async fn update_proxy_token( - ecdsa_key_name: String, + signer: store::Signer, proxy_token_refresh_interval: u64, mut agents: Vec, ) { @@ -31,13 +26,13 @@ pub async fn update_proxy_token( continue; } - let token = ecdsa::sign_proxy_token( - &ecdsa_key_name, - (ic_cdk::api::time() / SECONDS) + proxy_token_refresh_interval + 120, - &agent.name, - ) - .await - .expect("failed to sign proxy token"); + let token = signer + .sign_proxy_token( + (ic_cdk::api::time() / SECONDS) + proxy_token_refresh_interval + 120, + &agent.name, + ) + .await + .expect("failed to sign proxy token"); tokens.insert(agent.name.clone(), token.clone()); agent.proxy_token = Some(token); } diff --git a/src/idempotent-proxy-server/src/cache/memory.rs b/src/idempotent-proxy-server/src/cache/memory.rs index b661bf0..92ba1f5 100644 --- a/src/idempotent-proxy-server/src/cache/memory.rs +++ b/src/idempotent-proxy-server/src/cache/memory.rs @@ -17,10 +17,12 @@ use super::Cacher; #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)] struct PriorityKey(u64, String); +type KV = HashMap)>; + #[derive(Clone, Default)] pub struct MemoryCacher { priority_queue: Arc>>, - kv: Arc)>>>, + kv: Arc>, } impl MemoryCacher { @@ -91,7 +93,7 @@ impl Cacher for MemoryCacher { self.clean_expired_values(); } - if value.len() > 0 { + if !value.is_empty() { return Ok(value.clone()); } }