diff --git a/.gitignore b/.gitignore index 11c15e4..53e9f38 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,7 @@ artifacts/ .DS_Store .secrets/ **/.env.local + +#cli cli/quartz.toml +.cache/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 3eb109b..43b8d90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -317,7 +317,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "synstructure", ] @@ -329,7 +329,27 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", +] + +[[package]] +name = "async-priority-channel" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde96f444d31031f760c5c43dc786b97d3e1cb2ee49dd06898383fe9a999758" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", ] [[package]] @@ -351,7 +371,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -362,7 +382,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -375,7 +395,7 @@ dependencies = [ "futures-util", "log", "pin-project-lite", - "rustls-native-certs 0.7.2", + "rustls-native-certs 0.7.3", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -391,6 +411,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "atomic-take" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -403,7 +429,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51bd0e4592409df8631ca807716dc1e5caafae5d01ce0157c966c71c7e49c3c" dependencies = [ - "dirs", + "dirs 5.0.1", "git2", "terminal-prompt", ] @@ -616,9 +642,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" [[package]] name = "byteorder" @@ -635,6 +661,15 @@ dependencies = [ "serde", ] +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + [[package]] name = "cargo-generate" version = "0.21.3" @@ -650,7 +685,7 @@ dependencies = [ "env_logger", "fs-err", "git2", - "gix-config", + "gix-config 0.37.0", "heck", "home", "ignore", @@ -678,10 +713,33 @@ dependencies = [ ] [[package]] -name = "cc" -version = "1.1.13" +name = "cargo-platform" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "jobserver", "libc", @@ -694,6 +752,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "cfg_aliases" version = "0.2.1" @@ -752,7 +816,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -761,6 +825,19 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +[[package]] +name = "clearscreen" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8c93eb5f77c9050c7750e14f13ef1033a40a0aac70c6371535b6763a01438c" +dependencies = [ + "nix 0.28.0", + "terminfo", + "thiserror", + "which", + "winapi", +] + [[package]] name = "color-eyre" version = "0.6.3" @@ -780,6 +857,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console" version = "0.15.8" @@ -821,9 +907,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "contracts" @@ -919,7 +1005,7 @@ checksum = "029910b409398fdf81955d7301b906caf81f2c42b013ea074fbd89720229c424" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -943,7 +1029,7 @@ checksum = "edf5c8adac41bb7751c050d7c4c18675be19ee128714454454575e894424eeef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1049,6 +1135,16 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix 0.29.0", + "windows-sys 0.59.0", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1073,7 +1169,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1251,6 +1347,7 @@ dependencies = [ "displaydoc", "ecies", "hex", + "mtcs-enclave", "rand_core", "reqwest 0.12.7", "serde", @@ -1261,6 +1358,7 @@ dependencies = [ "tracing", "tracing-subscriber", "uuid", + "wasmd-client", ] [[package]] @@ -1284,7 +1382,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1295,7 +1393,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1339,7 +1437,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1370,7 +1468,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1390,7 +1488,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "unicode-xid", ] @@ -1428,13 +1526,33 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] @@ -1457,7 +1575,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1466,6 +1584,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1583,6 +1707,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "env_filter" version = "0.1.2" @@ -1622,6 +1752,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.12" @@ -1640,9 +1781,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1674,6 +1815,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1730,10 +1883,19 @@ dependencies = [ "cfg-if", "cvt", "libc", - "nix", + "nix 0.29.0", "windows-sys 0.52.0", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "futures" version = "0.3.30" @@ -1742,6 +1904,7 @@ checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1764,6 +1927,17 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -1778,7 +1952,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -1799,10 +1973,13 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1877,6 +2054,27 @@ dependencies = [ "winnow", ] +[[package]] +name = "gix-config" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7580e05996e893347ad04e1eaceb92e1c0e6a3ffe517171af99bf6b6df0ca6e5" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref 0.43.0", + "gix-sec", + "memchr", + "once_cell", + "smallvec", + "thiserror", + "unicode-bom", + "winnow", +] + [[package]] name = "gix-config" version = "0.37.0" @@ -1888,7 +2086,7 @@ dependencies = [ "gix-features", "gix-glob", "gix-path", - "gix-ref", + "gix-ref 0.44.1", "gix-sec", "memchr", "once_cell", @@ -1900,9 +2098,9 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.7" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b328997d74dd15dc71b2773b162cb4af9a25c424105e4876e6d0686ab41c383e" +checksum = "03f76169faa0dec598eac60f83d7fcdd739ec16596eca8fb144c88973dbe6f8c" dependencies = [ "bitflags 2.6.0", "bstr", @@ -1940,9 +2138,19 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.11.2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6adf99c27cdf17b1c4d77680c917e0d94d8783d4e1c73d3be0d1d63107163d7a" +checksum = "e2184c40e7910529677831c8b481acf788ffd92427ed21fad65b6aa637e631b8" +dependencies = [ + "gix-features", + "gix-utils", +] + +[[package]] +name = "gix-fs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bfe6249cfea6d0c0e0990d5226a4cb36f030444ba9e35e0639275db8f98575" dependencies = [ "fastrand", "gix-features", @@ -1951,9 +2159,9 @@ dependencies = [ [[package]] name = "gix-glob" -version = "0.16.4" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7df15afa265cc8abe92813cd354d522f1ac06b29ec6dfa163ad320575cb447" +checksum = "74908b4bbc0a0a40852737e5d7889f676f081e340d5451a16e5b4c50d592f111" dependencies = [ "bitflags 2.6.0", "bstr", @@ -1971,13 +2179,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gix-lock" +version = "13.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c359f81f01b8352063319bcb39789b7ea0887b406406381106e38c4a34d049" +dependencies = [ + "gix-tempfile 13.1.1", + "gix-utils", + "thiserror", +] + [[package]] name = "gix-lock" version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" dependencies = [ - "gix-tempfile", + "gix-tempfile 14.0.2", "gix-utils", "thiserror", ] @@ -2003,9 +2222,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.9" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d23d5bbda31344d8abc8de7c075b3cf26e5873feba7c4a15d916bce67382bd9" +checksum = "38d5b8722112fa2fa87135298780bc833b0e9f6c56cc82795d209804b3a03484" dependencies = [ "bstr", "gix-trace", @@ -2014,6 +2233,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gix-ref" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd4aba68b925101cb45d6df328979af0681364579db889098a0de75b36c77b65" +dependencies = [ + "gix-actor", + "gix-date", + "gix-features", + "gix-fs 0.10.2", + "gix-hash", + "gix-lock 13.1.1", + "gix-object", + "gix-path", + "gix-tempfile 13.1.1", + "gix-utils", + "gix-validate", + "memmap2", + "thiserror", + "winnow", +] + [[package]] name = "gix-ref" version = "0.44.1" @@ -2023,12 +2264,12 @@ dependencies = [ "gix-actor", "gix-date", "gix-features", - "gix-fs", + "gix-fs 0.11.3", "gix-hash", - "gix-lock", + "gix-lock 14.0.0", "gix-object", "gix-path", - "gix-tempfile", + "gix-tempfile 14.0.2", "gix-utils", "gix-validate", "memmap2", @@ -2038,9 +2279,9 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1547d26fa5693a7f34f05b4a3b59a90890972922172653bcb891ab3f09f436df" +checksum = "0fe4d52f30a737bbece5276fab5d3a8b276dc2650df963e293d0673be34e7a5f" dependencies = [ "bitflags 2.6.0", "gix-path", @@ -2050,11 +2291,24 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "14.0.1" +version = "13.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006acf5a613e0b5cf095d8e4b3f48c12a60d9062aa2b2dd105afaf8344a5600c" +checksum = "a761d76594f4443b675e85928e4902dec333273836bd386906f01e7e346a0d11" dependencies = [ - "gix-fs", + "gix-fs 0.10.2", + "libc", + "once_cell", + "parking_lot", + "tempfile", +] + +[[package]] +name = "gix-tempfile" +version = "14.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046b4927969fa816a150a0cda2e62c80016fe11fb3c3184e4dddf4e542f108aa" +dependencies = [ + "gix-fs 0.11.3", "libc", "once_cell", "parking_lot", @@ -2468,6 +2722,25 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "ignore-files" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f84e7f847462c582abc4c2aef6ede285ad6e8f66aeec83b47f5481706ddeba" +dependencies = [ + "dunce", + "futures", + "gix-config 0.36.1", + "ignore", + "miette", + "normalize-path", + "project-origins", + "radix_trie", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "indenter" version = "0.3.3" @@ -2514,6 +2787,26 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "inout" version = "0.1.3" @@ -2617,6 +2910,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "kstring" version = "2.0.2" @@ -2661,6 +2974,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", + "redox_syscall", ] [[package]] @@ -2724,9 +3038,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -2779,7 +3093,7 @@ checksum = "3b51f1d220e3fa869e24cfd75915efe3164bd09bb11b3165db3f37f57bf673e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -2928,6 +3242,29 @@ dependencies = [ "libc", ] +[[package]] +name = "miette" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" +dependencies = [ + "cfg-if", + "miette-derive", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + [[package]] name = "mime" version = "0.3.17" @@ -2949,6 +3286,18 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.0.2" @@ -3017,6 +3366,27 @@ dependencies = [ "rand", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", +] + [[package]] name = "nix" version = "0.29.0" @@ -3025,7 +3395,7 @@ checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", ] @@ -3039,6 +3409,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normalize-path" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d" + [[package]] name = "normpath" version = "1.3.0" @@ -3048,6 +3424,25 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio 0.8.11", + "walkdir", + "windows-sys 0.48.0", +] + [[package]] name = "num" version = "0.4.3" @@ -3153,9 +3548,9 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" dependencies = [ "asn1-rs", ] @@ -3214,6 +3609,12 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.3" @@ -3291,7 +3692,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3367,7 +3768,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3401,6 +3802,44 @@ dependencies = [ "indexmap 2.4.0", ] +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -3418,7 +3857,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3484,12 +3923,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3518,17 +3957,42 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "version_check", "yansi", ] +[[package]] +name = "process-wrap" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ee68ae331824036479c84060534b18254c864fa73366c58d86db3b7b811619" +dependencies = [ + "futures", + "indexmap 2.4.0", + "nix 0.28.0", + "tokio", + "tracing", + "windows", +] + [[package]] name = "prodash" version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" +[[package]] +name = "project-origins" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "735c6b4b1c67863c2211cac24badb0dca9fabfe1098209834fc5e0f92eda6c2c" +dependencies = [ + "futures", + "tokio", + "tokio-stream", +] + [[package]] name = "prost" version = "0.12.6" @@ -3566,7 +4030,7 @@ dependencies = [ "prost 0.13.1", "prost-types 0.13.1", "regex", - "syn 2.0.75", + "syn 2.0.76", "tempfile", ] @@ -3580,7 +4044,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3593,7 +4057,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -3622,17 +4086,20 @@ dependencies = [ "async-trait", "base64 0.22.1", "cargo-generate", + "cargo_metadata", "clap", + "clearscreen", "color-eyre", "cosmrs", "cosmwasm-std", - "cycles-sync", - "dirs", + "ctrlc", + "dirs 5.0.1", "displaydoc", "figment", "futures-util", "hex", "k256", + "miette", "mtcs-enclave", "once_cell", "prost 0.13.1", @@ -3644,6 +4111,7 @@ dependencies = [ "serde_json", "subtle-encoding", "target-lexicon", + "tempfile", "tendermint 0.38.1", "tendermint-light-client", "tendermint-rpc", @@ -3654,34 +4122,11 @@ dependencies = [ "tonic", "tracing", "tracing-subscriber", -] - -[[package]] -name = "quartz-app-transfers-enclave" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "color-eyre", - "cosmrs", - "cosmwasm-std", - "cw-multi-test", - "cycles-sync", - "ecies", - "hex", - "k256", - "prost 0.13.1", - "quartz-common", - "serde", - "serde_json", - "sha2 0.10.8", - "tendermint 0.38.1", - "tendermint-light-client", - "thiserror", - "tokio", - "tonic", - "tonic-build", - "transfers-contract", + "wasmd-client", + "watchexec", + "watchexec-events", + "watchexec-signals", + "xxhash-rust", ] [[package]] @@ -3819,13 +4264,23 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "rand" version = "0.8.5" @@ -4072,7 +4527,7 @@ checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -4113,9 +4568,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -4131,9 +4586,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags 2.6.0", "errno", @@ -4163,7 +4618,7 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.7", "subtle", "zeroize", ] @@ -4177,7 +4632,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki 0.102.7", "subtle", "zeroize", ] @@ -4196,9 +4651,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile 2.1.3", @@ -4244,9 +4699,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" dependencies = [ "ring", "rustls-pki-types", @@ -4314,7 +4769,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -4381,9 +4836,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -4418,13 +4873,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -4435,14 +4890,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", "memchr", @@ -4458,7 +4913,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -4507,7 +4962,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -4601,6 +5056,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -4705,9 +5166,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -4737,7 +5198,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5024,6 +5485,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "terminfo" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666cd3a6681775d22b200409aad3b089c5b99fb11ecdd8a204d9d62f8148498f" +dependencies = [ + "dirs 4.0.0", + "fnv", + "nom", + "phf", + "phf_codegen", +] + [[package]] name = "thin-vec" version = "0.2.13" @@ -5047,7 +5521,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5155,7 +5629,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio", + "mio 1.0.2", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5171,7 +5645,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5305,7 +5779,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5346,6 +5820,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5359,7 +5834,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5386,24 +5861,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "transfers-contract" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "cw-utils", - "cw2", - "cw20-base", - "getrandom", - "quartz-common", - "serde", - "serde_json", - "sha2 0.10.8", - "thiserror", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -5604,7 +6061,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "wasm-bindgen-shared", ] @@ -5638,7 +6095,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5649,6 +6106,81 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "wasmd-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "cosmrs", + "hex", + "reqwest 0.12.7", + "serde", + "serde_json", +] + +[[package]] +name = "watchexec" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c635816bdb583dcd1cf58935899df38b5c5ffb1b9d0cc89f8d3c7b33e2c005e3" +dependencies = [ + "async-priority-channel", + "async-recursion", + "atomic-take", + "futures", + "ignore-files", + "miette", + "nix 0.28.0", + "normalize-path", + "notify", + "once_cell", + "process-wrap", + "project-origins", + "thiserror", + "tokio", + "tracing", + "watchexec-events", + "watchexec-signals", + "watchexec-supervisor", +] + +[[package]] +name = "watchexec-events" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce015ba32ff91a7f796cea3798e7998d3645411f03fc373ef0e7c7e564291bc" +dependencies = [ + "nix 0.28.0", + "notify", + "watchexec-signals", +] + +[[package]] +name = "watchexec-signals" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7ccc54db7df8cbbe3251508321e46986ce179af4c4a03b4c70bda539d72755" +dependencies = [ + "miette", + "nix 0.28.0", + "thiserror", +] + +[[package]] +name = "watchexec-supervisor" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97efb9292bebdf72a777a0d6e400b69b32b4f3daee1ddd30214317a18ff20ab" +dependencies = [ + "futures", + "nix 0.28.0", + "process-wrap", + "tokio", + "tracing", + "watchexec-events", + "watchexec-signals", +] + [[package]] name = "web-sys" version = "0.3.70" @@ -5668,6 +6200,18 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5699,17 +6243,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-strings", "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -5725,7 +6322,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] @@ -5896,6 +6493,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "x509-cert" version = "0.2.5" @@ -5925,6 +6528,12 @@ dependencies = [ "time", ] +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + [[package]] name = "yansi" version = "1.0.1" @@ -5949,7 +6558,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -5969,5 +6578,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] diff --git a/Cargo.toml b/Cargo.toml index 8d646df..dbd4ca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ resolver = "2" members = [ "apps/mtcs/enclave", - "apps/transfers/enclave", "cli", "core/light-client-proofs/*", "core/quartz", @@ -10,7 +9,7 @@ members = [ "cosmwasm/packages/*", "utils/*", ] -exclude = ["apps/mtcs/contracts/cw-tee-mtcs", "apps/transfers/contracts", "apps/mtcs/scripts"] +exclude = ["apps/mtcs/contracts/cw-tee-mtcs", "apps/transfers/contracts", "apps/transfers/enclave"] [workspace.package] version = "0.1.0" @@ -54,7 +53,6 @@ tonic-build = { version = "=0.12.1", default-features = false, features = ["pros tracing = { version = "0.1.39", default-features = false } tracing-subscriber = { version = "0.3.17", default-features = false, features = ["fmt"] } uuid = { version = "1.4.1", default-features = false, features = ["serde"] } -walkdir = { version = "2.5.0", default-features = false } x509-cert = { version = "0.2.5", default-features = false } x509-parser = { version = "0.16.0", features = ["default", "verify"] } zeroize = { version = "1.7.0", default-features = false } @@ -79,20 +77,19 @@ mc-attestation-verifier = { git = "https://github.com/informalsystems/attestatio # quartz cw-proof = { path = "core/light-client-proofs/cw-proof", default-features = false } -cycles-sync = { path = "utils/cycles-sync", default-features = false } -quartz-common = { path = "core/quartz-common" } +quartz-common = { path = "core/quartz-common"} quartz-cw = { path = "cosmwasm/packages/quartz-cw", default-features = false } quartz-enclave = { path = "core/quartz", default-features = false } quartz-proto = { path = "core/quartz-proto", default-features = false } quartz-tee-ra = { path = "cosmwasm/packages/quartz-tee-ra", default-features = false } tm-prover = { path = "utils/tm-prover", default-features = false } tm-stateless-verifier = { path = "core/light-client-proofs/tm-stateless-verifier", default-features = false } +wasmd-client = { path = "cosmwasm/packages/wasmd-client", default-features = false } # quartz apps cw-tee-mtcs = { path = "apps/mtcs/contracts/cw-tee-mtcs", default-features = false } mtcs = { git = "ssh://git@github.com/informalsystems/mtcs.git", default-features = false } mtcs-enclave = { path = "apps/mtcs/enclave" } -transfers-contract = { path = "apps/transfers/contracts", default-features = false } [profile.release] opt-level = 3 diff --git a/apps/mtcs/.cargo/config.toml b/apps/mtcs/.cargo/config.toml new file mode 100644 index 0000000..a6b014e --- /dev/null +++ b/apps/mtcs/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target-dir = "target" diff --git a/apps/mtcs/enclave/proto/mtcs.proto b/apps/mtcs/enclave/proto/mtcs.proto index 99345a6..e12fc60 100644 --- a/apps/mtcs/enclave/proto/mtcs.proto +++ b/apps/mtcs/enclave/proto/mtcs.proto @@ -12,4 +12,4 @@ message RunClearingRequest { message RunClearingResponse { string message = 1; -} +} \ No newline at end of file diff --git a/apps/mtcs/enclave/quartz.manifest.template b/apps/mtcs/enclave/quartz.manifest.template index 1b49538..9e69220 100644 --- a/apps/mtcs/enclave/quartz.manifest.template +++ b/apps/mtcs/enclave/quartz.manifest.template @@ -1,7 +1,7 @@ # Quartz manifest file loader.entrypoint = "file:{{ gramine.libos }}" -libos.entrypoint = "{{ quartz_dir }}/target/release/enclave" +libos.entrypoint = "{{ quartz_dir }}/target/release/mtcs-enclave" loader.log_level = "{{ log_level }}" @@ -43,7 +43,7 @@ sgx.ra_client_linkable = {{ 'true' if ra_client_linkable == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.libos }}", - "file:{{ quartz_dir }}/target/release/enclave", + "file:{{ quartz_dir }}/target/release/mtcs-enclave", "file:{{ gramine.runtimedir() }}/", "file:{{ arch_libdir }}/", "file:/usr/{{ arch_libdir }}/", diff --git a/apps/mtcs/enclave/src/types.rs b/apps/mtcs/enclave/src/types.rs index 9c2f068..a8d7279 100644 --- a/apps/mtcs/enclave/src/types.rs +++ b/apps/mtcs/enclave/src/types.rs @@ -42,7 +42,7 @@ pub struct SubmitObligationsMsg { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SubmitObligationsMsgInner { pub obligations: Vec, - pub liquidity_sources: Vec, + pub liquidity_sources: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/apps/mtcs/quartz.toml b/apps/mtcs/quartz.toml index 04d73bb..bfa836b 100644 --- a/apps/mtcs/quartz.toml +++ b/apps/mtcs/quartz.toml @@ -1,8 +1,9 @@ mock_sgx = false tx_sender = "admin" chain_id = "testing" -node_url = "127.0.0.1:26657" +node_url = "127.0.0.1:25567" enclave_rpc_addr = "http://127.0.0.1" enclave_rpc_port = 11090 -trusted_hash = "0E01C103E05108B2981C202C5AE41024444E0638A7D8C734916C2797EB1EE447" -trusted_height = 8401 \ No newline at end of file +trusted_hash = "" +trusted_height = 0 +release = true diff --git a/apps/transfers/.cargo/config.toml b/apps/transfers/.cargo/config.toml new file mode 100644 index 0000000..a6b014e --- /dev/null +++ b/apps/transfers/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target-dir = "target" diff --git a/apps/transfers/cargo-generate.toml b/apps/transfers/cargo-generate.toml index 5d51011..76e525d 100644 --- a/apps/transfers/cargo-generate.toml +++ b/apps/transfers/cargo-generate.toml @@ -2,13 +2,12 @@ description = "An functioning example of a quartz app" ignore = [ + "target/", "contracts/Cargo.lock", "contracts/target", - "contracts/target/*", + "contracts/schema", + "enclave/Cargo.lock", "enclave/target", - "enclave/target/*", + "enclave/src/prost/*", "frontend/package-lock.json", - "frontend/public/images", - "trusted.hash", - "trusted.height" ] \ No newline at end of file diff --git a/apps/transfers/contracts/Cargo.lock b/apps/transfers/contracts/Cargo.lock index 460c96b..43ddb92 100644 --- a/apps/transfers/contracts/Cargo.lock +++ b/apps/transfers/contracts/Cargo.lock @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -165,13 +165,13 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "synstructure", ] @@ -183,7 +183,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -243,6 +243,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.7.1" @@ -251,9 +257,12 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.6" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -279,15 +288,15 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cosmwasm-core" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367fc87c43759098a476ef90f915aadc66c300480ad9c155b512081fbf327bc1" +checksum = "d905990ef3afb5753bb709dc7de88e9e370aa32bcc2f31731d4b533b63e82490" [[package]] name = "cosmwasm-crypto" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7c41f3e371ea457d3b98bb592c38858b46efcf614e0e988ec2ebbdb973954f" +checksum = "5b2a7bd9c1dd9a377a4dc0f4ad97d24b03c33798cd5a6d7ceb8869b41c5d2f2d" dependencies = [ "ark-bls12-381", "ark-ec", @@ -308,20 +317,20 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10510e8eb66cf7e109741b1e2c76ad18f30b5a1daa064f5f7115c1f733aaea0" +checksum = "029910b409398fdf81955d7301b906caf81f2c42b013ea074fbd89720229c424" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "cosmwasm-schema" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79879b6b7ef6a331b05030ce91ce46a7c4b0baf1ed6b382cce2e9a168109380" +checksum = "4bc0d4d85e83438ab9a0fea9348446f7268bc016aacfebce37e998559f151294" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -332,20 +341,20 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b53e33c0e97170c7ac9cb440f4bc599a07f9cbb9b7e87916cca37b1239d57b" +checksum = "edf5c8adac41bb7751c050d7c4c18675be19ee128714454454575e894424eeef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "cosmwasm-std" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92011c39570876f340d5f9defa68bf92797b1c44421f1b9ea9b04a31d6defd33" +checksum = "51dec99a2e478715c0a4277f0dbeadbb8466500eb7dec873d0924edd086e77f1" dependencies = [ "base64", "bech32", @@ -366,9 +375,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -444,14 +453,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "cw-multi-test" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0034bfb4c06dfc8b50f0b1a06c3fc0f2312a1bae568a97db65930de071288ba" +checksum = "b0ae276e7a06ad1b7e7da78a3d68aba80634cde30ee7fe8259a94e653603fef8" dependencies = [ "anyhow", "bech32", @@ -557,7 +566,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -568,7 +577,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -612,7 +621,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -637,22 +646,22 @@ dependencies = [ [[package]] name = "derive_more" -version = "1.0.0-beta.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "1.0.0-beta.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "unicode-xid", ] @@ -676,7 +685,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -886,9 +895,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -913,9 +922,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "log" @@ -1116,9 +1125,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "primeorder" @@ -1140,9 +1152,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" dependencies = [ "bytes", "prost-derive", @@ -1150,20 +1162,21 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "quartz-common" version = "0.1.0" +source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#302008c337b58fcad0373922a2787b9341eafd58" dependencies = [ "quartz-cw", ] @@ -1171,6 +1184,7 @@ dependencies = [ [[package]] name = "quartz-cw" version = "0.1.0" +source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#302008c337b58fcad0373922a2787b9341eafd58" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1187,6 +1201,7 @@ dependencies = [ [[package]] name = "quartz-tee-ra" version = "0.1.0" +source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#302008c337b58fcad0373922a2787b9341eafd58" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1335,7 +1350,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1360,9 +1375,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] @@ -1378,13 +1393,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1395,14 +1410,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -1435,7 +1450,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1449,6 +1464,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "2.2.0" @@ -1506,9 +1527,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1523,7 +1544,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1543,7 +1564,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1610,9 +1631,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "untrusted" @@ -1634,34 +1655,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1669,22 +1691,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "windows-sys" @@ -1794,6 +1816,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -1805,7 +1828,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] [[package]] @@ -1825,5 +1848,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.75", ] diff --git a/apps/transfers/contracts/Cargo.toml b/apps/transfers/contracts/Cargo.toml index a557e9b..4567e15 100644 --- a/apps/transfers/contracts/Cargo.toml +++ b/apps/transfers/contracts/Cargo.toml @@ -44,7 +44,7 @@ cw20-base = { version = "2.0.0", default-features = false, features = ["library" cw-utils = { version = "2.0.0", default-features = false } # quartz -quartz-common = { path = "../../../core/quartz-common", default-features = false, features = ["contract"] } +quartz-common = { git = "ssh://git@github.com/informalsystems/cycles-quartz.git", features=["contract"]} # patch indirect deps getrandom = { version = "0.2.15", default-features = false, features = ["js"] } diff --git a/apps/transfers/enclave/Cargo.toml b/apps/transfers/enclave/Cargo.toml index 5a2c580..1e5567b 100644 --- a/apps/transfers/enclave/Cargo.toml +++ b/apps/transfers/enclave/Cargo.toml @@ -15,33 +15,32 @@ default = [] [dependencies] # external -anyhow.workspace = true -clap.workspace = true -color-eyre.workspace = true -ecies.workspace = true -hex.workspace = true -k256.workspace = true -prost.workspace = true -serde.workspace = true -serde_json.workspace = true -sha2.workspace = true -thiserror.workspace = true -tokio.workspace = true -tonic.workspace = true +anyhow = { version = "1.0.86", default-features = false } +clap = { version = "4.1.8", default-features = false, features = ["derive", "std"] } +color-eyre = { version = "0.6.2", default-features = false } +ecies = { version = "0.2.3", default-features = false, features = ["pure"] } +hex = { version = "0.4.3", default-features = false } +k256 = { version = "0.13.2", default-features = false, features = ["ecdsa", "alloc"] } +prost = { version = "=0.13.1", default-features = false } +serde = { version = "1.0.203", default-features = false, features = ["derive"] } +serde_json = { version = "1.0.94", default-features = false, features = ["alloc"] } +sha2 = { version = "0.10.8", default-features = false } +thiserror = { version = "1.0.49", default-features = false } +tokio = { version = "=1.39.2", default-features = false, features = ["macros", "rt"] } +tonic = { version = "=0.12.1", default-features = false, features = ["codegen", "prost", "transport"] } # cosmos -cosmrs.workspace = true -cosmwasm-std.workspace = true -cycles-sync.workspace = true -tendermint.workspace = true -tendermint-light-client.workspace = true -transfers-contract.workspace = true +cosmrs = { version = "=0.17.0", default-features = false } +cosmwasm-std = { version = "2.1.1", default-features = false, features = ["std"] } +tendermint = { version = "=0.38.1", default-features = false } +tendermint-light-client = { version = "=0.38.1", default-features = false, features = ["rust-crypto"] } +transfers-contract = { path = "../contracts", default-features = false } # quartz -quartz-common = { workspace=true, features=["full"]} +quartz-common = { git = "ssh://git@github.com/informalsystems/cycles-quartz.git", features=["full"]} [dev-dependencies] cw-multi-test = "2.1.0" [build-dependencies] -tonic-build.workspace = true +tonic-build = { version = "=0.12.1", default-features = false, features = ["prost", "transport"] } diff --git a/apps/transfers/enclave/quartz.manifest.template b/apps/transfers/enclave/quartz.manifest.template index 2406a8a..6bf2328 100644 --- a/apps/transfers/enclave/quartz.manifest.template +++ b/apps/transfers/enclave/quartz.manifest.template @@ -1,7 +1,7 @@ # Quartz-based app manifest file loader.entrypoint = "file:{{ gramine.libos }}" -libos.entrypoint = "{{ enclave_executable }}" +libos.entrypoint = "{{ quartz_dir }}/target/release/quartz-app-transfers-enclave" loader.log_level = "{{ log_level }}" @@ -30,7 +30,7 @@ fs.mounts = [ { uri = "file:{{ gramine.runtimedir() }}", path = "/lib" }, { uri = "file:{{ arch_libdir }}", path = "{{ arch_libdir }}" }, { uri = "file:/usr/{{ arch_libdir }}", path = "/usr{{ arch_libdir }}" }, - { uri = "file:{{ enclave_dir }}", path = "{{ enclave_dir }}" }, + { uri = "file:{{ quartz_dir }}", path = "{{ quartz_dir }}" }, ] # sgx.debug = true @@ -44,15 +44,15 @@ sgx.ra_client_linkable = {{ 'true' if ra_client_linkable == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.libos }}", - "file:{{ enclave_executable }}", + "file:{{ quartz_dir }}/target/release/", "file:{{ gramine.runtimedir() }}/", "file:{{ arch_libdir }}/", "file:/usr/{{ arch_libdir }}/", ] sgx.allowed_files = [ - "file:{{ enclave_dir }}/exchange.sk", - "file:{{ enclave_dir }}/request.json", + "file:{{ quartz_dir }}/exchange.sk", + "file:{{ quartz_dir }}/request.json", ] sys.insecure__allow_eventfd = true diff --git a/apps/transfers/enclave/src/transfers_server.rs b/apps/transfers/enclave/src/transfers_server.rs index 4434b72..b4aef9e 100644 --- a/apps/transfers/enclave/src/transfers_server.rs +++ b/apps/transfers/enclave/src/transfers_server.rs @@ -84,6 +84,12 @@ impl HasUserData for QueryResponseMessage { } } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct StatusResponseMessage { + address: Addr, + encrypted_bal: HexBinary, +} + #[derive(Clone, Debug, Serialize, Deserialize)] struct AttestedMsg { msg: M, diff --git a/apps/transfers/quartz.toml b/apps/transfers/quartz.toml index 04d73bb..bfa836b 100644 --- a/apps/transfers/quartz.toml +++ b/apps/transfers/quartz.toml @@ -1,8 +1,9 @@ mock_sgx = false tx_sender = "admin" chain_id = "testing" -node_url = "127.0.0.1:26657" +node_url = "127.0.0.1:25567" enclave_rpc_addr = "http://127.0.0.1" enclave_rpc_port = 11090 -trusted_hash = "0E01C103E05108B2981C202C5AE41024444E0638A7D8C734916C2797EB1EE447" -trusted_height = 8401 \ No newline at end of file +trusted_hash = "" +trusted_height = 0 +release = true diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 8c15d27..4beca68 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -27,14 +27,23 @@ prost.workspace = true tokio = { workspace = true, features = ["process"] } tonic.workspace = true once_cell = "1.19.0" -reqwest = { version = "0.12.2", default-features = false, features = ["json", "rustls-tls"] } -anyhow = "1.0.86" +reqwest = { workspace = true, default-features = false, features = ["json", "rustls-tls"] } +anyhow.workspace = true base64 = "0.22.1" -subtle-encoding = "0.5.1" +subtle-encoding.workspace = true futures-util = "0.3.30" target-lexicon = "0.12.16" regex = "1.10.5" +watchexec = "4.1.0" +watchexec-events = "3.0.0" +watchexec-signals = "3.0.0" +miette = "7.2.0" +ctrlc = { version = "3.4.5", features=["termination"]} +xxhash-rust = { version = "0.8.12", features=["xxh3"] } toml = "0.8.19" +figment = { version = "0.10.19", features=["env", "toml"] } +clearscreen = "3.0.0" +cargo_metadata = "0.18.1" # cosmos cosmrs.workspace = true @@ -43,9 +52,9 @@ tendermint.workspace = true tendermint-light-client.workspace = true tendermint-rpc = { workspace = true, features=["websocket-client", "http-client"]} -cycles-sync = { workspace = true} tm-prover = { workspace = true} quartz-common = { workspace = true, features=["contract"]} quartz-tee-ra = { workspace = true} mtcs-enclave = { workspace = true, optional = false} -figment = { version = "0.10.19", features=["env", "toml"] } +wasmd-client.workspace = true +tempfile.workspace = true diff --git a/cli/src/cache.rs b/cli/src/cache.rs new file mode 100644 index 0000000..7148502 --- /dev/null +++ b/cli/src/cache.rs @@ -0,0 +1,151 @@ +use std::path::{Path, PathBuf}; + +use serde::{Deserialize, Serialize}; +use tokio::{ + fs::File, + io::{AsyncReadExt, BufReader}, +}; +use tracing::debug; +use xxhash_rust::xxh3::Xxh3; + +use crate::{config::Config, error::Error}; + +const BUFFER_SIZE: usize = 16384; // 16 KB buffer +type Hash = u64; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +struct DeployedContract { + code_id: u64, + contract_hash: Hash, +} + +// Porcelain + +impl Config { + pub async fn contract_has_changed(&self, file: &Path) -> Result { + let cur_hash: Hash = Self::gen_hash(file).await?; + debug!("current file hash: {}", cur_hash); + + let cached_file_path = Self::to_cache_path(self, file)?; + + if !cached_file_path.exists() { + return Ok(true); + } + + let cached_contract = Self::read_from_cache(cached_file_path.as_path()).await?; + debug!("cached file hash: {}", cached_contract.contract_hash); + + Ok(cur_hash != cached_contract.contract_hash) + } + + /// Return a hash of the given file's contents + pub async fn gen_hash(file: &Path) -> Result { + let file = File::open(file) + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + let mut reader = BufReader::new(file); + + let mut hasher = Xxh3::new(); + + let mut buffer = [0; BUFFER_SIZE]; + loop { + let bytes_read = reader + .read(&mut buffer) + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + if bytes_read == 0 { + break; + } + hasher.update(&buffer[..bytes_read]); + } + + // Finalize the hash + let hash = hasher.digest(); + + Ok(hash) + } + + pub async fn save_codeid_to_cache(&self, file: &Path, code_id: u64) -> Result<(), Error> { + let contract_hash = Self::gen_hash(file).await?; + let dest = Self::to_cache_path(self, file)?; + let deployed_contract = DeployedContract { + code_id, + contract_hash, + }; + + Self::write_to_cache(dest.as_path(), &deployed_contract).await + } + + pub async fn get_cached_codeid(&self, file: &Path) -> Result { + let cache_path = Self::to_cache_path(self, file)?; + let code_id = Self::read_from_cache(cache_path.as_path()).await?.code_id; + + Ok(code_id) + } + + // Plumbing + + fn to_cache_path(&self, file: &Path) -> Result { + // Get cache filepath (".quartz/cache/example.wasm.json") from "example.wasm" filepath + let mut filename = file + .file_name() + .ok_or(Error::PathNotFile(file.display().to_string()))? + .to_os_string(); + filename.push(".json"); + + let cached_file_path = Self::cache_dir(self)?.join::(filename.into()); + + Ok(cached_file_path) + } + + /// Retreive hash from cache file + async fn read_from_cache(cache_file: &Path) -> Result { + let content = tokio::fs::read_to_string(cache_file) + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + serde_json::from_str(&content).map_err(|e| Error::GenericErr(e.to_string())) + } + + /// Write a given file's contents hash to a file in cache directory + async fn write_to_cache(cache_file: &Path, data: &DeployedContract) -> Result<(), Error> { + let content = serde_json::to_string(data).map_err(|e| Error::GenericErr(e.to_string()))?; + tokio::fs::write(cache_file, content) + .await + .map_err(|e| Error::GenericErr(e.to_string())) + } + + pub fn cache_dir(&self) -> Result { + Ok(self.app_dir.join(".cache/")) + } + + pub fn build_log_dir(&self) -> Result { + Ok(self.app_dir.join(".cache/log/")) + } + + /// Creates the build log if it isn't created already, returns relative path from app_dir to log directory + pub async fn create_build_log(&self) -> Result { + let log_dir = Self::build_log_dir(self)?; + if !log_dir.exists() { + tokio::fs::create_dir_all(&log_dir) + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + } + + Ok(log_dir) + } + + pub async fn log_build(&self, is_enclave: bool) -> Result<(), Error> { + let log_dir = Self::create_build_log(self).await?; + + let filename = match is_enclave { + true => "enclave", + false => "contract", + }; + + tokio::fs::write(log_dir.join(filename), "test") + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + + Ok(()) + } +} diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 7787e01..efe93fa 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -35,8 +35,8 @@ pub struct Cli { /// Enable mock SGX mode for testing purposes. /// This flag disables the use of an Intel SGX processor and allows the system to run without remote attestations. #[arg(long)] - #[serde(skip_serializing_if = "Option::is_none")] - pub mock_sgx: Option, + #[serde(skip_serializing_if = "is_false")] + pub mock_sgx: bool, /// Path to Quartz app directory /// Defaults to current working dir @@ -50,6 +50,10 @@ pub struct Cli { pub command: Command, } +fn is_false(b: &bool) -> bool { + !(*b) +} + #[derive(Debug, Subcommand, Serialize, Clone)] pub enum Command { /// Create an empty Quartz app from a template @@ -69,6 +73,8 @@ pub enum Command { #[command(subcommand)] enclave_command: EnclaveCommand, }, + /// Build, deploy, perform handshake, and run quartz app while listening for changes + Dev(DevArgs), } #[derive(Debug, Clone, Subcommand, Serialize)] @@ -98,6 +104,10 @@ pub struct HandshakeArgs { #[arg(short, long, value_parser = wasmaddr_to_id)] pub contract: AccountId, + /// Fetch latest trusted hash and height from the chain instead of existing configuration + #[arg(long)] + pub use_latest_trusted: bool, + /// Name or address of private key with which to sign #[arg(long)] #[serde(skip_serializing_if = "Option::is_none")] @@ -126,8 +136,9 @@ pub struct HandshakeArgs { #[derive(Debug, Parser, Clone, Serialize, Deserialize)] pub struct ContractBuildArgs { + /// Path to Cargo manifest file for CosmWasm contract package #[arg(long)] - pub manifest_path: PathBuf, + pub contract_manifest: PathBuf, } #[derive(Debug, Parser, Clone, Serialize, Deserialize)] @@ -155,16 +166,17 @@ pub struct ContractDeployArgs { #[arg(long, default_value = "Quartz App Contract")] pub label: String, - /// Path to contract wasm binary for deployment + /// Path to Cargo manifest file for CosmWasm contract package #[arg(long)] - pub wasm_bin_path: PathBuf, + pub contract_manifest: PathBuf, } #[derive(Debug, Parser, Clone, Serialize, Deserialize)] pub struct EnclaveBuildArgs { - /// Path to Cargo.toml file of the Quartz app's enclave package, defaults to './enclave/Cargo.toml' if unspecified - #[arg(long, default_value = "./enclave/Cargo.toml")] - pub manifest_path: PathBuf, + /// Whether to target release or dev + #[arg(long)] + #[serde(skip_serializing_if = "is_false")] + pub release: bool, } #[derive(Debug, Parser, Clone, Serialize, Deserialize)] @@ -177,6 +189,28 @@ pub struct EnclaveStartArgs { /// Fetch latest trusted hash and height from the chain instead of existing configuration #[arg(long)] pub use_latest_trusted: bool, + + /// Whether to target release or dev + #[arg(long)] + #[serde(skip_serializing_if = "is_false")] + pub release: bool, +} + +#[derive(Debug, Parser, Clone, Serialize, Deserialize)] +pub struct DevArgs { + /// Automatically deploy and instantiate new cosmwasm contract instance upon changes to source + #[arg(long)] + pub watch: bool, + + /// Fetch latest trusted hash and height from the chain instead of existing configuration + #[arg(long)] + pub use_latest_trusted: bool, + + #[command(flatten)] + pub contract_deploy: ContractDeployArgs, + + #[command(flatten)] + pub enclave_build: EnclaveBuildArgs, } pub trait ToFigment { @@ -196,6 +230,9 @@ impl ToFigment for Command { EnclaveCommand::Build(args) => Figment::from(Serialized::defaults(args)), EnclaveCommand::Start(args) => Figment::from(Serialized::defaults(args)), }, + Command::Dev(args) => Figment::from(Serialized::defaults(args)) + .merge(Serialized::defaults(&args.contract_deploy)) + .merge(Serialized::defaults(&args.enclave_build)), } } } diff --git a/cli/src/config.rs b/cli/src/config.rs index ac7fa79..3286912 100644 --- a/cli/src/config.rs +++ b/cli/src/config.rs @@ -32,7 +32,7 @@ pub struct Config { /// Path to Quartz app directory /// Defaults to current working dir - #[serde(default = "default_app_dir")] + #[serde(default = "default_app_dir", skip_serializing)] pub app_dir: PathBuf, /// Trusted height for light client proofs @@ -42,6 +42,10 @@ pub struct Config { /// Trusted hash for block at trusted_height for light client proofs #[serde(default)] pub trusted_hash: String, + + /// Whether to build for release or debug + #[serde(default)] + pub release: bool, } fn default_rpc_addr() -> String { @@ -80,6 +84,7 @@ impl Default for Config { app_dir: default_app_dir(), trusted_height: u64::default(), trusted_hash: String::default(), + release: false, } } } @@ -89,3 +94,9 @@ impl AsRef for Config { self } } + +impl Config { + pub fn enclave_rpc(&self) -> String { + format!("{}:{}", self.enclave_rpc_addr, self.enclave_rpc_port) + } +} diff --git a/cli/src/error.rs b/cli/src/error.rs index 0edca56..2dbfa57 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -15,6 +15,8 @@ pub enum Error { TomlError(String), /// Tendermint error: {0} TendermintError(String), + /// Clearscreen error: {0} + ClearscreenError(String), } impl From for Error { @@ -40,3 +42,9 @@ impl From for Error { Error::TendermintError(err.to_string()) } } + +impl From for Error { + fn from(err: clearscreen::Error) -> Self { + Error::ClearscreenError(err.to_string()) + } +} diff --git a/cli/src/handler.rs b/cli/src/handler.rs index 3165da2..7d5d882 100644 --- a/cli/src/handler.rs +++ b/cli/src/handler.rs @@ -6,6 +6,7 @@ pub mod utils; // commands pub mod contract_build; pub mod contract_deploy; +pub mod dev; pub mod enclave_build; pub mod enclave_start; pub mod handshake; @@ -38,6 +39,7 @@ impl Handler for Request { Request::ContractDeploy(request) => request.handle(config).await, Request::EnclaveBuild(request) => request.handle(config).await, Request::EnclaveStart(request) => request.handle(config).await, + Request::Dev(request) => request.handle(config).await, } .map(Into::into) } diff --git a/cli/src/handler/contract_build.rs b/cli/src/handler/contract_build.rs index 6c82e7c..c059c9d 100644 --- a/cli/src/handler/contract_build.rs +++ b/cli/src/handler/contract_build.rs @@ -1,7 +1,8 @@ use std::process::Command; use async_trait::async_trait; -use tracing::{debug, trace}; +use color_eyre::owo_colors::OwoColorize; +use tracing::{debug, info}; use crate::{ config::Config, @@ -21,11 +22,22 @@ impl Handler for ContractBuildRequest { config: C, ) -> Result { let config = config.as_ref(); + info!("{}", "\nPeforming Contract Build".blue().bold()); let mut cargo = Command::new("cargo"); let command = cargo - .arg("wasm") - .args(["--manifest-path", &self.manifest_path.display().to_string()]) + .arg("build") + .arg("--release") + .args(["--target", "wasm32-unknown-unknown"]) + .arg("--lib") + .args([ + "--target-dir", + &config.app_dir.join("target").display().to_string(), + ]) + .args([ + "--manifest-path", + &self.contract_manifest.display().to_string(), + ]) .env("RUSTFLAGS", "-C link-arg=-s"); if config.mock_sgx { @@ -33,7 +45,7 @@ impl Handler for ContractBuildRequest { command.arg("--features=mock-sgx"); } - trace!("🚧 Building contract binary ..."); + info!("{}", "🚧 Building contract binary ...".green().bold()); let status = command .status() .map_err(|e| Error::GenericErr(e.to_string()))?; @@ -45,6 +57,8 @@ impl Handler for ContractBuildRequest { ))); } + config.log_build(false).await?; + Ok(ContractBuildResponse.into()) } } diff --git a/cli/src/handler/contract_deploy.rs b/cli/src/handler/contract_deploy.rs index 9aca804..89b670f 100644 --- a/cli/src/handler/contract_deploy.rs +++ b/cli/src/handler/contract_deploy.rs @@ -1,7 +1,8 @@ -use std::env::current_dir; +use std::path::Path; use async_trait::async_trait; -use cycles_sync::wasmd_client::{CliWasmdClient, WasmdClient}; +use cargo_metadata::MetadataCommand; +use color_eyre::owo_colors::OwoColorize; use quartz_common::contract::{ msg::execute::attested::{RawEpidAttestation, RawMockAttestation}, prelude::QuartzInstantiateMsg, @@ -10,16 +11,20 @@ use reqwest::Url; use serde::{de::DeserializeOwned, Serialize}; use serde_json::json; use tendermint_rpc::HttpClient; -use tracing::{debug, info, trace}; +use tracing::{debug, info}; +use wasmd_client::{CliWasmdClient, WasmdClient}; use super::utils::{ - helpers::{block_tx_commit, run_relay}, + helpers::block_tx_commit, types::{Log, WasmdTxResponse}, }; use crate::{ config::Config, error::Error, - handler::{utils::types::RelayMessage, Handler}, + handler::{ + utils::{helpers::run_relay_rust, types::RelayMessage}, + Handler, + }, request::contract_deploy::ContractDeployRequest, response::{contract_deploy::ContractDeployResponse, Response}, }; @@ -34,15 +39,32 @@ impl Handler for ContractDeployRequest { config: C, ) -> Result { let config = config.as_ref(); + info!("{}", "\nPeforming Contract Deploy".blue().bold()); - trace!("initializing directory structure..."); + // Get contract package name in snake_case + let package_name = MetadataCommand::new() + .manifest_path(&self.contract_manifest) + .exec() + .map_err(|e| Error::GenericErr(e.to_string()))? + .root_package() + .ok_or("No root package found in the metadata") + .map_err(|e| Error::GenericErr(e.to_string()))? + .name + .clone() + .replace('-', "_"); + + let wasm_bin_path = config + .app_dir + .join("target/wasm32-unknown-unknown/release") + .join(package_name) + .with_extension("wasm"); let (code_id, contract_addr) = if config.mock_sgx { - deploy::(self, config) + deploy::(wasm_bin_path.as_path(), self, config) .await .map_err(|e| Error::GenericErr(e.to_string()))? } else { - deploy::(self, config) + deploy::(wasm_bin_path.as_path(), self, config) .await .map_err(|e| Error::GenericErr(e.to_string()))? }; @@ -56,40 +78,41 @@ impl Handler for ContractDeployRequest { } async fn deploy( + wasm_bin_path: &Path, args: ContractDeployRequest, config: &Config, ) -> Result<(u64, String), anyhow::Error> { - // TODO: Replace with call to Rust package - let relay_path = current_dir()?.join("../"); - let httpurl = Url::parse(&format!("http://{}", config.node_url))?; let tmrpc_client = HttpClient::new(httpurl.as_str())?; let wasmd_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?); - info!("\n🚀 Deploying {} Contract\n", args.label); - let contract_path = args.wasm_bin_path; - // .join("contracts/cw-tee-mtcs/target/wasm32-unknown-unknown/release/cw_tee_mtcs.wasm"); + info!("🚀 Deploying {} Contract", args.label); + let code_id = if config.contract_has_changed(wasm_bin_path).await? { + let deploy_output: WasmdTxResponse = serde_json::from_str(&wasmd_client.deploy( + &config.chain_id, + &config.tx_sender, + wasm_bin_path.display().to_string(), + )?)?; + let res = block_tx_commit(&tmrpc_client, deploy_output.txhash).await?; - // TODO: uncertain about the path -> string conversion - let deploy_output: WasmdTxResponse = serde_json::from_str(&wasmd_client.deploy( - &config.chain_id, - &config.tx_sender, - contract_path.display().to_string(), - )?)?; - let res = block_tx_commit(&tmrpc_client, deploy_output.txhash).await?; + let log: Vec = serde_json::from_str(&res.tx_result.log)?; + let code_id: u64 = log[0].events[1].attributes[1].value.parse()?; + config.save_codeid_to_cache(wasm_bin_path, code_id).await?; - let log: Vec = serde_json::from_str(&res.tx_result.log)?; - let code_id: u64 = log[0].events[1].attributes[1].value.parse()?; + code_id + } else { + config.get_cached_codeid(wasm_bin_path).await? + }; - info!("\n🚀 Communicating with Relay to Instantiate...\n"); - let raw_init_msg = run_relay::>( - relay_path.as_path(), + info!("🚀 Communicating with Relay to Instantiate..."); + let raw_init_msg = run_relay_rust::>( + config.enclave_rpc(), config.mock_sgx, RelayMessage::Instantiate, ) .await?; - info!("\n🚀 Instantiating {} Contract\n", args.label); + info!("🚀 Instantiating {}", args.label); let mut init_msg = args.init_msg; init_msg["quartz"] = json!(raw_init_msg); @@ -105,9 +128,9 @@ async fn deploy( let log: Vec = serde_json::from_str(&res.tx_result.log)?; let contract_addr: &String = &log[0].events[1].attributes[0].value; - info!("\n🚀 Successfully deployed and instantiated contract!"); - info!("\n🆔 Code ID: {}", code_id); - info!("\n📌 Contract Address: {}", contract_addr); + info!("🚀 Successfully deployed and instantiated contract!"); + info!("🆔 Code ID: {}", code_id); + info!("📌 Contract Address: {}", contract_addr); debug!("{contract_addr}"); diff --git a/cli/src/handler/dev.rs b/cli/src/handler/dev.rs new file mode 100644 index 0000000..f35154f --- /dev/null +++ b/cli/src/handler/dev.rs @@ -0,0 +1,348 @@ +use std::{path::PathBuf, process::exit, time::Duration}; + +use async_trait::async_trait; +use color_eyre::owo_colors::OwoColorize; +// todo get rid of this? +use miette::{IntoDiagnostic, Result}; +use quartz_common::proto::core_client::CoreClient; +use tokio::{ + sync::{mpsc, watch}, + time::sleep, +}; +use tracing::{debug, info}; +use watchexec::Watchexec; +use watchexec_signals::Signal; + +use crate::{ + error::Error, + handler::{utils::helpers::wasmaddr_to_id, Handler}, + request::{ + contract_build::ContractBuildRequest, contract_deploy::ContractDeployRequest, + dev::DevRequest, enclave_build::EnclaveBuildRequest, enclave_start::EnclaveStartRequest, + handshake::HandshakeRequest, + }, + response::{dev::DevResponse, Response}, + Config, BANNER, +}; + +#[async_trait] +impl Handler for DevRequest { + type Error = Error; + type Response = Response; + + async fn handle + Send>( + self, + config: C, + ) -> Result { + let config = config.as_ref(); + info!("\nPeforming Dev"); + + let (tx, rx) = mpsc::channel::(32); + let _res = tx.send(DevRebuild::Init).await; + + if self.watch { + tokio::spawn(watcher(tx, config.build_log_dir()?)); + } + + dev_driver(rx, &self, config.clone()).await?; + + Ok(DevResponse.into()) + } +} + +#[derive(Debug, Clone)] +enum DevRebuild { + Init, + Enclave, + Contract, +} + +async fn dev_driver( + mut rx: mpsc::Receiver, + args: &DevRequest, + config: Config, +) -> Result<(), Error> { + // State + let mut shutdown_tx: Option> = None; + let mut first_enclave_message = true; + let mut first_contract_message = true; + let mut contract = String::from(""); + + // Shutdown enclave upon interruption + let shutdown_tx_cpy = shutdown_tx.clone(); + ctrlc::set_handler(move || { + if let Some(tx) = &shutdown_tx_cpy { + let _res = tx.send(()); + } + + exit(130) + }) + .expect("Error setting Ctrl-C handler"); + + // Drive + while let Some(dev) = rx.recv().await { + match dev { + DevRebuild::Init => { + clearscreen::clear()?; + println!("{}", BANNER.yellow().bold()); + info!("{}", "Launching quartz app...".green().bold()); + + // Build enclave + let enclave_build = EnclaveBuildRequest { + release: args.release, + }; + enclave_build.handle(&config).await?; + + // Build contract + let contract_build = ContractBuildRequest { + contract_manifest: args.contract_manifest.clone(), + }; + contract_build.handle(&config).await?; + + // Start enclave in background + let new_shutdown_tx = spawn_enclave_start(args, &config).await?; + + // Deploy new contract and perform handshake + let res = deploy_and_handshake(None, args, &config).await; + + // Save resulting contract address or shutdown and return error + match res { + Ok(res_contract) => { + // Set state + contract = res_contract; + shutdown_tx = Some(new_shutdown_tx); + + info!("{}", "Enclave is listening for requests...".green().bold()); + } + Err(e) => { + eprintln!("Error launching quartz app"); + + new_shutdown_tx + .send(()) + .expect("Could not send signal on channel"); + + return Err(e); + } + } + } + DevRebuild::Enclave => { + if first_enclave_message { + first_enclave_message = false; + + continue; + } + clearscreen::clear()?; + println!("{}", BANNER.yellow().bold()); + info!("{}", "Rebuilding Enclave...".green().bold()); + + if let Some(shutdown_tx) = shutdown_tx.clone() { + let _res = shutdown_tx.send(()); + } + + info!("Waiting 1 second for the enclave to shut down"); + sleep(Duration::from_secs(1)).await; + + let new_shutdown_tx = spawn_enclave_start(args, &config).await?; + + // todo: should not unconditionally deploy here + let res = deploy_and_handshake(Some(&contract), args, &config).await; + + match res { + Ok(res_contract) => { + // Set state + contract = res_contract; + shutdown_tx = Some(new_shutdown_tx); + + info!("{}", "Enclave is listening for requests...".green().bold()); + } + Err(e) => { + eprintln!("Error restarting enclave and handshake"); + + new_shutdown_tx + .send(()) + .expect("Could not send signal on channel"); + + return Err(e); + } + } + } + DevRebuild::Contract => { + if first_contract_message { + first_contract_message = false; + continue; + } + clearscreen::clear()?; + println!("{}", BANNER.yellow().bold()); + info!("{}", "Rebuilding Contract...".green().bold()); + + if let Some(shutdown_tx) = shutdown_tx.clone() { + let res = deploy_and_handshake(None, args, &config).await; + + match res { + Ok(res_contract) => contract = res_contract, + Err(e) => { + eprintln!("Error deploying contract and handshake:"); + + shutdown_tx + .send(()) + .expect("Could not send signal on channel"); + + return Err(e); + } + } + } else { + return Err(Error::GenericErr( + "Attempting to redeploy contract, but enclave isn't running".to_string(), + )); + } + + info!("{}", "Enclave is listening for requests...".green().bold()); + } + } + } + + Ok(()) +} + +// Spawns enclve start in a separate task which runs in the background +async fn spawn_enclave_start( + args: &DevRequest, + config: &Config, +) -> Result, Error> { + // In separate process, launch the enclave + let (shutdown_tx, shutdown_rx) = watch::channel(()); + let enclave_start = EnclaveStartRequest { + shutdown_rx: Some(shutdown_rx), + use_latest_trusted: args.use_latest_trusted, + }; + + let config_cpy = config.clone(); + + tokio::spawn(async move { + let res = enclave_start.handle(config_cpy).await?; + + Ok::(res) + }); + + Ok(shutdown_tx) +} + +// TODO: do not shutdown if cli calls fail, just print +async fn deploy_and_handshake( + contract: Option<&str>, + args: &DevRequest, + config: &Config, +) -> Result { + info!("Waiting for enclave start to deploy contract and handshake"); + + // Wait at most 30 seconds to connect to enclave + let mut i = 30; + while CoreClient::connect(format!( + "{}:{}", + config.enclave_rpc_addr, config.enclave_rpc_port + )) + .await + .is_err() + { + sleep(Duration::from_secs(1)).await; + i -= 1; + + if i == 0 { + return Err(Error::GenericErr( + "Could not connect to enclave".to_string(), + )); + } + } + // Calls which interact with enclave + info!("Successfully pinged enclave, enclave is running"); + + // Deploy contract IF existing contract wasn't pass into the function + let contract = if let Some(contract) = contract { + info!("Contract already deployed, reusing"); + contract.to_string() + } else { + info!("Deploying contract"); + // Deploy Contract request + let contract_deploy = ContractDeployRequest { + init_msg: args.init_msg.clone(), + label: args.label.clone(), + contract_manifest: args.contract_manifest.clone(), + }; + // Call handler + let cd_res = contract_deploy.handle(config).await; + + // Return contract address or shutdown enclave & error + match cd_res { + Ok(Response::ContractDeploy(res)) => res.contract_addr, + Err(e) => return Err(e), + _ => unreachable!("Unexpected response variant"), + } + }; + + // Run handshake + info!("Running handshake on contract `{}`", contract); + let handshake = HandshakeRequest { + contract: wasmaddr_to_id(&contract).map_err(|_| Error::GenericErr(String::default()))?, + use_latest_trusted: args.use_latest_trusted, + }; + + let h_res = handshake.handle(config).await; + + match h_res { + Ok(Response::Handshake(res)) => { + info!("Handshake complete: {}", res.pub_key); + } + Err(e) => { + return Err(e); + } + _ => unreachable!("Unexpected response variant"), + }; + + Ok(contract) +} + +async fn watcher(tx: mpsc::Sender, log_dir: PathBuf) -> Result<()> { + let wx = Watchexec::new_async(move |mut action| { + let tx = tx.clone(); + + Box::new(async move { + if action.signals().any(|sig| sig == Signal::Interrupt) { + eprintln!("[Quitting...]"); + action.quit(); + return action; + } + + // Look for updates to filepaths + if let Some((path, _)) = action.paths().next() { + debug!("event triggered on path:\n {:?}", path); + if path + .file_name() + .expect("events can't trigger on nonexistent files") + .eq("enclave") + { + let _res = tx.send(DevRebuild::Enclave).await; + } else if path + .file_name() + .expect("events can't trigger on nonexistent files") + .eq("contract") + { + let _res = tx.send(DevRebuild::Contract).await; + } + } + + action + }) + })?; + + // Start the engine + let main = wx.main(); + + // Watch all files in quartz app directory + // TODO: should create_log_dir be called instead? Just enforce building log in all cases? + wx.config.pathset([log_dir]); + + // Keep running until Watchexec quits + let _ = main.await.into_diagnostic()?; + + Ok(()) +} diff --git a/cli/src/handler/enclave_build.rs b/cli/src/handler/enclave_build.rs index b6875a3..2173404 100644 --- a/cli/src/handler/enclave_build.rs +++ b/cli/src/handler/enclave_build.rs @@ -1,6 +1,6 @@ -use std::process::Command; - use async_trait::async_trait; +use color_eyre::owo_colors::OwoColorize; +use tokio::process::Command; use tracing::{debug, info}; use crate::{ @@ -21,20 +21,31 @@ impl Handler for EnclaveBuildRequest { config: C, ) -> Result { let config = config.as_ref(); + info!("{}", "\nPeforming Enclave Build".blue().bold()); + + let enclave_dir = config.app_dir.join("enclave"); let mut cargo = Command::new("cargo"); let command = cargo - .args(["build", "--release"]) - .args(["--manifest-path", &self.manifest_path.display().to_string()]); + .arg("build") + .args(["--target-dir", &config.app_dir.join("target").display().to_string()]) // TODO: Where should this be set to? + .args(["--manifest-path", &enclave_dir.join("Cargo.toml").display().to_string(), + ]); if config.mock_sgx { debug!("Building with mock-sgx enabled"); command.arg("--features=mock-sgx"); } - info!("🚧 Building enclave ..."); + if self.release { + debug!("Targetting release"); + command.arg("--release"); + } + + info!("{}", "🚧 Running build command ...".green().bold()); let status = command .status() + .await .map_err(|e| Error::GenericErr(e.to_string()))?; if !status.success() { @@ -44,6 +55,8 @@ impl Handler for EnclaveBuildRequest { ))); } + config.log_build(true).await?; + Ok(EnclaveBuildResponse.into()) } } diff --git a/cli/src/handler/enclave_start.rs b/cli/src/handler/enclave_start.rs index 36fa8b1..4399a1f 100644 --- a/cli/src/handler/enclave_start.rs +++ b/cli/src/handler/enclave_start.rs @@ -1,13 +1,18 @@ -use std::env; +use std::{fs, path::Path}; use async_trait::async_trait; -use tokio::process::Command; +use cargo_metadata::MetadataCommand; +use color_eyre::owo_colors::OwoColorize; +use tokio::{ + process::{Child, Command}, + sync::watch, +}; use tracing::{debug, info}; use crate::{ config::Config, error::Error, - handler::{utils::helpers::get_hash_height, Handler}, + handler::{utils::helpers::write_cache_hash_height, Handler}, request::enclave_start::EnclaveStartRequest, response::{enclave_start::EnclaveStartResponse, Response}, }; @@ -21,11 +26,13 @@ impl Handler for EnclaveStartRequest { self, config: C, ) -> Result { - let mut config = config.as_ref().clone(); - // Get trusted height and hash - let (trusted_height, trusted_hash) = get_hash_height(self.use_latest_trusted, &mut config)?; + let config = config.as_ref().clone(); + info!("{}", "\nPeforming Enclave Start".blue().bold()); - let enclave_dir = config.app_dir.join("enclave"); + // Get trusted height and hash + let (trusted_height, trusted_hash) = self.get_hash_height(&config)?; + println!("trusted height: {} hash: {}", trusted_height, trusted_hash); + write_cache_hash_height(trusted_height, trusted_hash, &config).await?; if config.mock_sgx { let enclave_args: Vec = vec![ @@ -38,65 +45,121 @@ impl Handler for EnclaveStartRequest { ]; // Run quartz enclave and block - let _res = run_enclave( - enclave_dir.join("Cargo.toml").display().to_string(), - config.mock_sgx, - enclave_args, + let enclave_child = + create_mock_enclave_child(config.app_dir.as_path(), config.release, enclave_args) + .await?; + handle_process(self.shutdown_rx, enclave_child).await?; + } else { + let enclave_dir = fs::canonicalize(config.app_dir.join("enclave"))?; + + // gramine private key + gramine_sgx_gen_private_key(&enclave_dir).await?; + + // gramine manifest + let quartz_dir_canon = &enclave_dir.join(".."); + gramine_manifest( + &trusted_height.to_string(), + &trusted_hash.to_string(), + quartz_dir_canon, + &enclave_dir, ) .await?; - } else { - // set cwd to enclave app - env::set_current_dir(enclave_dir).map_err(|e| Error::GenericErr(e.to_string()))?; - // gramine private key - gramine_sgx_gen_private_key().await?; - // gramine manifest - gramine_manifest(&trusted_height.to_string(), &trusted_hash.to_string()).await?; + // gramine sign - gramine_sgx_sign().await?; + gramine_sgx_sign(&enclave_dir).await?; + // Run quartz enclave and block - gramine_sgx().await?; + let enclave_child = create_gramine_sgx_child(&enclave_dir).await?; + handle_process(self.shutdown_rx, enclave_child).await?; } + Ok(EnclaveStartResponse.into()) } } -async fn run_enclave( - manifest_path: String, - mock_sgx: bool, - enclave_args: Vec, +async fn handle_process( + shutdown_rx: Option>, + mut child: Child, ) -> Result<(), Error> { - let mut cargo = Command::new("cargo"); - let command = cargo.args(["run", "--release", "--manifest-path", &manifest_path]); - - if mock_sgx { - debug!("Running with mock-sgx enabled"); - command.arg("--features=mock-sgx"); + info!("{}", "Running enclave ...".green().bold()); + match shutdown_rx { + Some(mut rx) => { + tokio::select! { + status = child.wait() => { + handle_child_status(status.map_err(|e| Error::GenericErr(e.to_string()))?)?; + } + _ = rx.changed() => { + info!("Enclave shutdown signal received."); + let _ = child.kill().await; + } + } + } + None => { + // If no shutdown receiver is provided, just wait for the child process + let status = child + .wait() + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + handle_child_status(status)?; + } } - command.arg("--"); + Ok(()) +} + +async fn create_mock_enclave_child( + app_dir: &Path, + release: bool, + enclave_args: Vec, +) -> Result { + let enclave_dir = app_dir.join("enclave"); + let target_dir = app_dir.join("target"); + + // Use the enclave package metadata to get the path to the program binary + let package_name = MetadataCommand::new() + .manifest_path(&enclave_dir.join("Cargo.toml")) + .exec() + .map_err(|e| Error::GenericErr(e.to_string()))? + .root_package() + .ok_or("No root package found in the metadata") + .map_err(|e| Error::GenericErr(e.to_string()))? + .name + .clone(); + + let executable = if release { + target_dir.join("release").join(package_name) + } else { + target_dir.join("debug").join(package_name) + }; + + let mut command = Command::new(executable.display().to_string()); + command.args(enclave_args); - println!("command: {:?}", command); + debug!("Enclave Start Command: {:?}", command); - info!("🚧 Running enclave ..."); - let status = command - .status() - .await + info!("{}", "🚧 Spawning enclave process ...".green().bold()); + let child = command + .spawn() .map_err(|e| Error::GenericErr(e.to_string()))?; + Ok(child) +} + +fn handle_child_status(status: std::process::ExitStatus) -> Result<(), Error> { if !status.success() { return Err(Error::GenericErr(format!( "Couldn't build enclave. {:?}", status ))); } - Ok(()) } -async fn gramine_sgx_gen_private_key() -> Result<(), Error> { +async fn gramine_sgx_gen_private_key(enclave_dir: &Path) -> Result<(), Error> { // Launch the gramine-sgx-gen-private-key command Command::new("gramine-sgx-gen-private-key") + .current_dir(enclave_dir) .output() .await .map_err(|e| { @@ -111,9 +174,12 @@ async fn gramine_sgx_gen_private_key() -> Result<(), Error> { Ok(()) } -async fn gramine_manifest(trusted_height: &str, trusted_hash: &str) -> Result<(), Error> { - let current_dir = env::current_dir().map_err(|e| Error::GenericErr(e.to_string()))?; - +async fn gramine_manifest( + trusted_height: &str, + trusted_hash: &str, + quartz_dir: &Path, + enclave_dir: &Path, +) -> Result<(), Error> { let host = target_lexicon::HOST; let arch_libdir = format!( "/lib/{}-{}-{}", @@ -133,11 +199,12 @@ async fn gramine_manifest(trusted_height: &str, trusted_hash: &str) -> Result<() .arg("-Dra_type=epid") .arg(format!("-Dra_client_spid={}", ra_client_spid)) .arg("-Dra_client_linkable=1") - .arg(format!("-Dquartz_dir={}", current_dir.display())) + .arg(format!("-Dquartz_dir={}", quartz_dir.display().to_string())) .arg(format!("-Dtrusted_height={}", trusted_height)) .arg(format!("-Dtrusted_hash={}", trusted_hash)) .arg("quartz.manifest.template") .arg("quartz.manifest") + .current_dir(enclave_dir) .status() .await .map_err(|e| Error::GenericErr(e.to_string()))?; @@ -152,12 +219,13 @@ async fn gramine_manifest(trusted_height: &str, trusted_hash: &str) -> Result<() Ok(()) } -async fn gramine_sgx_sign() -> Result<(), Error> { +async fn gramine_sgx_sign(enclave_dir: &Path) -> Result<(), Error> { let status = Command::new("gramine-sgx-sign") .arg("--manifest") .arg("quartz.manifest") .arg("--output") .arg("quartz.manifest.sgx") + .current_dir(enclave_dir) .status() .await .map_err(|e| Error::GenericErr(e.to_string()))?; @@ -172,19 +240,13 @@ async fn gramine_sgx_sign() -> Result<(), Error> { Ok(()) } -async fn gramine_sgx() -> Result<(), Error> { - let status = Command::new("gramine-sgx") +async fn create_gramine_sgx_child(enclave_dir: &Path) -> Result { + info!("🚧 Spawning enclave process ..."); + + let child = Command::new("gramine-sgx") .arg("./quartz") - .status() - .await - .map_err(|e| Error::GenericErr(e.to_string()))?; + .current_dir(enclave_dir) + .spawn()?; - if !status.success() { - return Err(Error::GenericErr(format!( - "gramine-sgx-sign command failed. {:?}", - status - ))); - } - - Ok(()) + Ok(child) } diff --git a/cli/src/handler/handshake.rs b/cli/src/handler/handshake.rs index c5c1706..e731035 100644 --- a/cli/src/handler/handshake.rs +++ b/cli/src/handler/handshake.rs @@ -1,26 +1,26 @@ -use std::{env::current_dir, fs, str::FromStr}; +use std::{fs, str::FromStr}; use anyhow::anyhow; use async_trait::async_trait; +use color_eyre::owo_colors::OwoColorize; use cosmrs::tendermint::chain::Id as ChainId; // TODO see if this redundancy in dependencies can be decreased -use cycles_sync::wasmd_client::{CliWasmdClient, WasmdClient}; use futures_util::stream::StreamExt; use reqwest::Url; -use serde::Serialize; use serde_json::json; use tendermint_rpc::{query::EventType, HttpClient, SubscriptionClient, WebSocketClient}; use tm_prover::{config::Config as TmProverConfig, prover::prove}; -use tracing::{debug, info, trace}; +use tracing::{debug, info}; +use wasmd_client::{CliWasmdClient, WasmdClient}; -use super::utils::{ - helpers::{block_tx_commit, run_relay}, - types::WasmdTxResponse, -}; +use super::utils::{helpers::block_tx_commit, types::WasmdTxResponse}; use crate::{ config::Config, error::Error, handler::{ - utils::{helpers::get_hash_height, types::RelayMessage}, + utils::{ + helpers::{read_cached_hash_height, run_relay_rust}, + types::RelayMessage, + }, Handler, }, request::handshake::HandshakeRequest, @@ -38,7 +38,7 @@ impl Handler for HandshakeRequest { ) -> Result { let config = config.as_ref().clone(); - trace!("starting handshake..."); + info!("{}", "\nPeforming Handshake".blue().bold()); // TODO: may need to import verbosity here let pub_key = handshake(self, config) @@ -49,25 +49,19 @@ impl Handler for HandshakeRequest { } } -#[derive(Serialize)] -struct Message<'a> { - message: &'a str, -} - -async fn handshake(args: HandshakeRequest, mut config: Config) -> Result { +async fn handshake(args: HandshakeRequest, config: Config) -> Result { let httpurl = Url::parse(&format!("http://{}", config.node_url))?; let wsurl = format!("ws://{}/websocket", config.node_url); let tmrpc_client = HttpClient::new(httpurl.as_str())?; let wasmd_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?); - let (trusted_height, trusted_hash) = get_hash_height(false, &mut config)?; - // TODO: dir logic issue #125 - let base_path = current_dir()?.join("../"); + let (trusted_height, trusted_hash) = read_cached_hash_height(&config).await?; info!("Running SessionCreate"); - let res: serde_json::Value = run_relay( - base_path.as_path(), + + let res: serde_json::Value = run_relay_rust( + config.enclave_rpc(), config.mock_sgx, RelayMessage::SessionCreate, ) @@ -94,8 +88,7 @@ async fn handshake(args: HandshakeRequest, mut config: Config) -> Result Result + Send>( self, config: C, ) -> Result { let config = config.as_ref(); - - trace!("initializing directory structure..."); + info!("{}", "\nPeforming Init".blue().bold()); let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(".."); @@ -61,6 +62,7 @@ impl Handler for InitRequest { .display() .to_string(); + info!("\n{}", "It's TEE time.".green().bold()); Ok(InitResponse { result_dir }.into()) } } diff --git a/cli/src/handler/utils/helpers.rs b/cli/src/handler/utils/helpers.rs index 0a1cb44..d5994cf 100644 --- a/cli/src/handler/utils/helpers.rs +++ b/cli/src/handler/utils/helpers.rs @@ -1,21 +1,38 @@ -use std::{path::Path, time::Duration}; +use std::time::Duration; use anyhow::anyhow; use cosmrs::{AccountId, ErrorReport}; -use cycles_sync::wasmd_client::{CliWasmdClient, WasmdClient}; +use cosmwasm_std::Binary; +use hex::decode; +use quartz_common::{ + contract::msg::{ + execute::{session_create::RawSessionCreate, session_set_pub_key::RawSessionSetPubKey}, + instantiate::RawCoreInstantiate, + }, + proto::{ + core_client::CoreClient, InstantiateRequest, SessionCreateRequest, SessionSetPubKeyRequest, + }, +}; +use quartz_tee_ra::{intel_sgx::epid::types::ReportBody, IASReport}; use regex::Regex; use reqwest::Url; use serde::de::DeserializeOwned; +use serde_json::json; use subtle_encoding::bech32::decode as bech32_decode; use tendermint::{block::Height, Hash}; use tendermint_rpc::{ endpoint::tx::Response as TmTxResponse, error::ErrorDetail, Client, HttpClient, }; -use tokio::{fs, process::Command}; +use tokio::{ + fs::{self, File}, + io::AsyncWriteExt, + process::Command, +}; use tracing::debug; +use wasmd_client::{CliWasmdClient, WasmdClient}; use super::types::RelayMessage; -use crate::{config::Config, error}; +use crate::{config::Config, error::Error}; pub fn wasmaddr_to_id(address_str: &str) -> Result { let (hr, _) = bech32_decode(address_str).map_err(|e| anyhow!(e))?; @@ -26,36 +43,6 @@ pub fn wasmaddr_to_id(address_str: &str) -> Result { address_str.parse().map_err(|e: ErrorReport| anyhow!(e)) } -// TODO: move wrapping result with "quartz:" struct into here -pub async fn run_relay( - base_path: &Path, - mock_sgx: bool, - msg: RelayMessage, -) -> Result { - let relayer_path = base_path.join("cli/scripts/relay.sh"); - - let mut bash = Command::new("bash"); - let command = bash - .arg(relayer_path) - .arg(msg.to_string()) - .env("MOCK_SGX", mock_sgx.to_string()); - - if let RelayMessage::SessionSetPubKey(proof) = msg { - command.arg(proof); - } - - let output = command.output().await?; - - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - let query_result: R = serde_json::from_slice(&output.stdout) - .map_err(|e| anyhow!("Error deserializing: {}", e))?; - - Ok(query_result) -} - // Note: time until tx commit is empiraclly 800ms on DO wasmd chain. pub async fn block_tx_commit(client: &HttpClient, tx: Hash) -> Result { let re = Regex::new(r"tx \([A-F0-9]{64}\) not found")?; @@ -90,37 +77,15 @@ pub async fn block_tx_commit(client: &HttpClient, tx: Hash) -> Result Result<(Height, Hash), error::Error> { - if use_latest || config.trusted_height == 0 || config.trusted_hash.is_empty() { - let (trusted_height, trusted_hash) = latest_height_hash(&config.node_url)?; - config.trusted_hash = trusted_hash.to_string(); - config.trusted_height = trusted_height.into(); - - Ok((trusted_height, trusted_hash)) - } else { - Ok(( - config.trusted_height.try_into()?, - config - .trusted_hash - .parse() - .map_err(|_| error::Error::GenericErr("invalid hash".to_string()))?, - )) - } -} - // Queries the chain for the latested height and hash -pub fn latest_height_hash(node_url: &String) -> Result<(Height, Hash), error::Error> { +pub fn query_latest_height_hash(node_url: &String) -> Result<(Height, Hash), Error> { let httpurl = Url::parse(&format!("http://{}", node_url)) - .map_err(|e| error::Error::GenericErr(e.to_string()))?; + .map_err(|e| Error::GenericErr(e.to_string()))?; let wasmd_client = CliWasmdClient::new(httpurl); let (trusted_height, trusted_hash) = wasmd_client .trusted_height_hash() - .map_err(|e| error::Error::GenericErr(e.to_string()))?; + .map_err(|e| Error::GenericErr(e.to_string()))?; Ok(( trusted_height.try_into()?, @@ -128,17 +93,223 @@ pub fn latest_height_hash(node_url: &String) -> Result<(Height, Hash), error::Er )) } -pub async fn persist_config_hash_height(config: &Config) -> Result<(), error::Error> { - let config_path = config.app_dir.join("quartz.toml"); +pub async fn write_cache_hash_height( + trusted_height: Height, + trusted_hash: Hash, + config: &Config, +) -> Result<(), Error> { + let height_path = config.cache_dir()?.join("trusted.height"); + fs::write(height_path.as_path(), trusted_height.to_string()).await?; - let toml_content = fs::read_to_string(&config_path).await?; - let mut written_config: Config = toml::from_str(&toml_content)?; - - written_config.trusted_hash.clone_from(&config.trusted_hash); - written_config.trusted_height = config.trusted_height; - - let toml_string = toml::to_string(config)?; - fs::write(&config_path, toml_string).await?; + let hash_path = config.cache_dir()?.join("trusted.hash"); + fs::write(hash_path.as_path(), trusted_hash.to_string()).await?; Ok(()) } + +pub async fn read_cached_hash_height(config: &Config) -> Result<(Height, Hash), Error> { + let height_path = config.cache_dir()?.join("trusted.height"); + let hash_path = config.cache_dir()?.join("trusted.hash"); + + if !height_path.exists() { + return Err(Error::PathNotFile(height_path.display().to_string())); + } + if !hash_path.exists() { + return Err(Error::PathNotFile(hash_path.display().to_string())); + } + + let trusted_height: Height = fs::read_to_string(height_path.as_path()).await?.parse()?; + let trusted_hash: Hash = fs::read_to_string(hash_path.as_path()).await?.parse()?; + + Ok((trusted_height, trusted_hash)) +} + +async fn run_docker_command(quote: &[u8]) -> Result<(String, String), Error> { + let dir = tempfile::tempdir()?; + let ias_api_key: &str = "669244b3e6364b5888289a11d2a1726d"; + let ra_client_spid: &str = "51CAF5A48B450D624AEFE3286D314894"; + let quote_file_path = dir.path().join("test.quote"); + let datareport_file_path = dir.path().join("datareport"); + let datareportsig_file_path = dir.path().join("datareportsig"); + + let mut quote_file = File::create(quote_file_path.clone()).await?; + quote_file.write_all(quote).await?; + + let status = Command::new("docker") + .arg("run") + .arg("--rm") + .arg("-it") + .arg("-v") + .arg("/tmp:/tmp:rw") + .arg("gramineproject/gramine:1.7-jammy") + .arg(format!( + "gramine-sgx-ias-request report -g \"{}\" -k \"{}\" -q \"{}\" -r \"{}\" -s \"{}\" > /dev/null 2>&1", + ra_client_spid, ias_api_key, quote_file_path.display().to_string(), datareport_file_path.display().to_string(), datareportsig_file_path.display().to_string() + )) + .status() + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + + if !status.success() { + return Err(Error::GenericErr( + "Failed to run docker command".to_string(), + )); + } + + let report = fs::read_to_string(datareport_file_path) + .await + .map_err(|e| Error::GenericErr(e.to_string()))?; + + let reportsig = fs::read_to_string(datareportsig_file_path) + .await + .map_err(|e| Error::GenericErr(e.to_string()))? + .replace("\r", ""); + + Ok((report, reportsig)) +} + +// TODO: move wrapping result with "quartz:" struct into here +pub async fn run_relay_rust( + enclave_rpc: String, + mock_sgx: bool, + relay_msg: RelayMessage, +) -> Result { + // Query the gRPC quartz enclave service + let mut qc_client = CoreClient::connect(enclave_rpc).await?; + + let attested_msg = match &relay_msg { + RelayMessage::Instantiate => &qc_client + .instantiate(tonic::Request::new(InstantiateRequest {})) + .await? + .get_ref() + .message + .clone(), + RelayMessage::SessionCreate => &qc_client + .session_create(tonic::Request::new(SessionCreateRequest {})) + .await? + .get_ref() + .message + .clone(), + RelayMessage::SessionSetPubKey(proof) => &qc_client + .session_set_pub_key(SessionSetPubKeyRequest { + message: proof.to_string(), + }) + .await? + .get_ref() + .message + .clone(), + }; + let mut attested_msg_json: serde_json::Value = serde_json::from_str(attested_msg)?; + let quote = attested_msg_json["quote"].take(); + + if mock_sgx { + match relay_msg { + RelayMessage::Instantiate => { + // Construct CoreInstantiate + let msg: RawCoreInstantiate = serde_json::from_value(attested_msg_json)?; + + let query_result: R = serde_json::from_value(json!({ + "msg": RawCoreInstantiate::from(msg), + "attestation": quote + }))?; + + return Ok(query_result); + } + RelayMessage::SessionCreate => { + // Convert RelayMessage to a snake_case string + let request_key = relay_msg.to_string(); + + let msg: RawSessionCreate = serde_json::from_value(attested_msg_json)?; + // Build the nested JSON structures + let jsonify = json!({ + "quartz": { + request_key: { + "msg": msg, + "attestation": quote + } + } + }); + + let query_result: R = serde_json::from_value(jsonify)?; + + return Ok(query_result); + } + RelayMessage::SessionSetPubKey(_) => { + // Convert RelayMessage to a snake_case string + let request_key = relay_msg.to_string(); + + let msg: RawSessionSetPubKey = serde_json::from_value(attested_msg_json)?; + // Build the nested JSON structures + let jsonify = json!({ + "quartz": { + request_key: { + "msg": msg, + "attestation": quote + } + } + }); + + let query_result: R = serde_json::from_value(jsonify)?; + + return Ok(query_result); + } + } + } + // else + // docker + let quote_str = quote + .as_str() + .ok_or_else(|| Error::GenericErr("quote is not a string".to_string()))?; + + let quote = decode(quote_str).map_err(|e| Error::GenericErr(e.to_string()))?; + println!("quote: {:?}", quote_str); + let (report, report_sig) = run_docker_command("e).await?; + + match relay_msg { + RelayMessage::Instantiate => { + let msg: RawCoreInstantiate = serde_json::from_value(attested_msg_json)?; + let report_json: ReportBody = serde_json::from_str(&report)?; + let report_sig = report_sig.replace('\n', ""); + + let ias_report = IASReport { + report: report_json, + report_sig: Binary::from_base64(&report_sig)?, + }; + + // Nest the report inside another "report" field + let jsonify = json!({ + "msg": msg, + "attestation": { + "report": { + "report": json!(ias_report.report), + "reportsig": ias_report.report_sig + } + } + }); + + let query_result: R = serde_json::from_value(jsonify)?; + + return Ok(query_result); + } + RelayMessage::SessionCreate | RelayMessage::SessionSetPubKey(_) => { + // Convert request to snake_case + let request_key = relay_msg.to_string(); + + // Construct the JSON structure for SessionCreate or SessionSetPubKey + let jsonify = json!({ + "quartz": { + request_key: { + "msg": attested_msg_json, + "attestation": { + "report": report, + "reportsig": report_sig + } + } + } + }); + + let query_result: R = serde_json::from_value(jsonify)?; + return Ok(query_result); + } + } +} diff --git a/cli/src/handler/utils/types.rs b/cli/src/handler/utils/types.rs index 14e2104..306bf74 100644 --- a/cli/src/handler/utils/types.rs +++ b/cli/src/handler/utils/types.rs @@ -49,9 +49,9 @@ pub enum RelayMessage { impl std::fmt::Display for RelayMessage { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RelayMessage::Instantiate => write!(f, "Instantiate"), - RelayMessage::SessionCreate => write!(f, "SessionCreate"), - RelayMessage::SessionSetPubKey(_) => write!(f, "SessionSetPubKey"), + RelayMessage::Instantiate => write!(f, "instantiate"), + RelayMessage::SessionCreate => write!(f, "session_create"), + RelayMessage::SessionSetPubKey(_) => write!(f, "session_set_pub_key"), } } } diff --git a/cli/src/main.rs b/cli/src/main.rs index 31825da..e98f307 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -13,6 +13,7 @@ unused_qualifications )] +pub mod cache; pub mod cli; pub mod config; pub mod error; @@ -24,7 +25,7 @@ use std::path::PathBuf; use clap::Parser; use cli::ToFigment; -use color_eyre::eyre::Result; +use color_eyre::{eyre::Result, owo_colors::OwoColorize}; use config::Config; use figment::{ providers::{Env, Format, Serialized, Toml}, @@ -50,7 +51,7 @@ const BANNER: &str = r" async fn main() -> Result<()> { color_eyre::install()?; - println!("{BANNER}"); + println!("{}", BANNER.yellow().bold()); let args: Cli = Cli::parse(); check_path(&args.app_dir)?; diff --git a/cli/src/request.rs b/cli/src/request.rs index c421ed9..65a3979 100644 --- a/cli/src/request.rs +++ b/cli/src/request.rs @@ -3,13 +3,14 @@ use crate::{ error::Error, request::{ contract_build::ContractBuildRequest, contract_deploy::ContractDeployRequest, - enclave_build::EnclaveBuildRequest, enclave_start::EnclaveStartRequest, + dev::DevRequest, enclave_build::EnclaveBuildRequest, enclave_start::EnclaveStartRequest, handshake::HandshakeRequest, init::InitRequest, }, }; pub mod contract_build; pub mod contract_deploy; +pub mod dev; pub mod enclave_build; pub mod enclave_start; pub mod handshake; @@ -23,6 +24,7 @@ pub enum Request { ContractDeploy(ContractDeployRequest), EnclaveBuild(EnclaveBuildRequest), EnclaveStart(EnclaveStartRequest), + Dev(DevRequest), } impl TryFrom for Request { @@ -33,10 +35,21 @@ impl TryFrom for Request { Command::Init(args) => Ok(InitRequest { name: args.name }.try_into()?), Command::Handshake(args) => Ok(HandshakeRequest { contract: args.contract, + use_latest_trusted: args.use_latest_trusted, } .into()), Command::Contract { contract_command } => contract_command.try_into(), Command::Enclave { enclave_command } => enclave_command.try_into(), + Command::Dev(args) => Ok(DevRequest { + watch: args.watch, + use_latest_trusted: args.use_latest_trusted, + init_msg: serde_json::from_str(&args.contract_deploy.init_msg) + .map_err(|e| Error::GenericErr(e.to_string()))?, + label: args.contract_deploy.label, + contract_manifest: args.contract_deploy.contract_manifest, + release: args.enclave_build.release, + } + .into()), } } } @@ -47,25 +60,29 @@ impl TryFrom for Request { fn try_from(cmd: ContractCommand) -> Result { match cmd { ContractCommand::Deploy(args) => { - if !args.wasm_bin_path.exists() { - return Err(Error::PathNotFile(args.wasm_bin_path.display().to_string())); + if !args.contract_manifest.exists() { + return Err(Error::PathNotFile( + args.contract_manifest.display().to_string(), + )); } Ok(ContractDeployRequest { init_msg: serde_json::from_str(&args.init_msg) .map_err(|e| Error::GenericErr(e.to_string()))?, label: args.label, - wasm_bin_path: args.wasm_bin_path, + contract_manifest: args.contract_manifest, } .into()) } ContractCommand::Build(args) => { - if !args.manifest_path.exists() { - return Err(Error::PathNotFile(args.manifest_path.display().to_string())); + if !args.contract_manifest.exists() { + return Err(Error::PathNotFile( + args.contract_manifest.display().to_string(), + )); } Ok(ContractBuildRequest { - manifest_path: args.manifest_path, + contract_manifest: args.contract_manifest, } .into()) } @@ -79,10 +96,11 @@ impl TryFrom for Request { fn try_from(cmd: EnclaveCommand) -> Result { match cmd { EnclaveCommand::Build(args) => Ok(EnclaveBuildRequest { - manifest_path: args.manifest_path, + release: args.release, } .into()), EnclaveCommand::Start(args) => Ok(EnclaveStartRequest { + shutdown_rx: None, use_latest_trusted: args.use_latest_trusted, } .into()), diff --git a/cli/src/request/contract_build.rs b/cli/src/request/contract_build.rs index 23917be..7ef8a00 100644 --- a/cli/src/request/contract_build.rs +++ b/cli/src/request/contract_build.rs @@ -4,7 +4,7 @@ use crate::request::Request; #[derive(Clone, Debug)] pub struct ContractBuildRequest { - pub manifest_path: PathBuf, + pub contract_manifest: PathBuf, } impl From for Request { diff --git a/cli/src/request/contract_deploy.rs b/cli/src/request/contract_deploy.rs index 0db66e9..c727e67 100644 --- a/cli/src/request/contract_deploy.rs +++ b/cli/src/request/contract_deploy.rs @@ -8,7 +8,7 @@ use crate::{error::Error, request::Request}; pub struct ContractDeployRequest { pub init_msg: serde_json::Value, pub label: String, - pub wasm_bin_path: PathBuf, + pub contract_manifest: PathBuf, } impl From for Request { diff --git a/cli/src/request/dev.rs b/cli/src/request/dev.rs new file mode 100644 index 0000000..9a18a06 --- /dev/null +++ b/cli/src/request/dev.rs @@ -0,0 +1,19 @@ +use std::path::PathBuf; + +use crate::request::Request; + +#[derive(Clone, Debug)] +pub struct DevRequest { + pub watch: bool, + pub use_latest_trusted: bool, + pub init_msg: serde_json::Value, + pub label: String, + pub contract_manifest: PathBuf, + pub release: bool, +} + +impl From for Request { + fn from(request: DevRequest) -> Self { + Self::Dev(request) + } +} diff --git a/cli/src/request/enclave_build.rs b/cli/src/request/enclave_build.rs index f7e9629..3bf2a79 100644 --- a/cli/src/request/enclave_build.rs +++ b/cli/src/request/enclave_build.rs @@ -1,10 +1,8 @@ -use std::path::PathBuf; - use crate::request::Request; #[derive(Clone, Debug)] pub struct EnclaveBuildRequest { - pub manifest_path: PathBuf, + pub release: bool, } impl From for Request { diff --git a/cli/src/request/enclave_start.rs b/cli/src/request/enclave_start.rs index c5ab5bd..e8f6260 100644 --- a/cli/src/request/enclave_start.rs +++ b/cli/src/request/enclave_start.rs @@ -1,7 +1,15 @@ -use crate::request::Request; +use tendermint::{block::Height, Hash}; +use tokio::sync::watch; +use tracing::debug; + +use crate::{ + config::Config, error::Error, handler::utils::helpers::query_latest_height_hash, + request::Request, +}; #[derive(Clone, Debug)] pub struct EnclaveStartRequest { + pub shutdown_rx: Option>, pub use_latest_trusted: bool, } @@ -10,3 +18,24 @@ impl From for Request { Self::EnclaveStart(request) } } + +impl EnclaveStartRequest { + /// Returns the trusted hash and height + pub fn get_hash_height(&self, config: &Config) -> Result<(Height, Hash), Error> { + if self.use_latest_trusted || config.trusted_height == 0 || config.trusted_hash.is_empty() { + debug!("querying latest trusted hash & height from node"); + let (trusted_height, trusted_hash) = query_latest_height_hash(&config.node_url)?; + + Ok((trusted_height, trusted_hash)) + } else { + debug!("reusing config trusted hash & height"); + Ok(( + config.trusted_height.try_into()?, + config + .trusted_hash + .parse() + .map_err(|_| Error::GenericErr("invalid hash".to_string()))?, + )) + } + } +} diff --git a/cli/src/request/handshake.rs b/cli/src/request/handshake.rs index 9f57bf8..2056c93 100644 --- a/cli/src/request/handshake.rs +++ b/cli/src/request/handshake.rs @@ -5,6 +5,7 @@ use crate::request::Request; #[derive(Clone, Debug)] pub struct HandshakeRequest { pub contract: AccountId, + pub use_latest_trusted: bool, } impl From for Request { diff --git a/cli/src/response.rs b/cli/src/response.rs index aaa272d..2839c17 100644 --- a/cli/src/response.rs +++ b/cli/src/response.rs @@ -2,12 +2,13 @@ use serde::Serialize; use crate::response::{ contract_build::ContractBuildResponse, contract_deploy::ContractDeployResponse, - enclave_build::EnclaveBuildResponse, enclave_start::EnclaveStartResponse, + dev::DevResponse, enclave_build::EnclaveBuildResponse, enclave_start::EnclaveStartResponse, handshake::HandshakeResponse, init::InitResponse, }; pub mod contract_build; pub mod contract_deploy; +pub mod dev; pub mod enclave_build; pub mod enclave_start; pub mod handshake; @@ -21,4 +22,5 @@ pub enum Response { ContractDeploy(ContractDeployResponse), EnclaveBuild(EnclaveBuildResponse), EnclaveStart(EnclaveStartResponse), + Dev(DevResponse), } diff --git a/cli/src/response/dev.rs b/cli/src/response/dev.rs new file mode 100644 index 0000000..962581b --- /dev/null +++ b/cli/src/response/dev.rs @@ -0,0 +1,12 @@ +use serde::Serialize; + +use crate::response::Response; + +#[derive(Clone, Debug, Serialize)] +pub struct DevResponse; + +impl From for Response { + fn from(response: DevResponse) -> Self { + Self::Dev(response) + } +} diff --git a/cosmwasm/packages/wasmd-client/Cargo.toml b/cosmwasm/packages/wasmd-client/Cargo.toml new file mode 100644 index 0000000..49755a2 --- /dev/null +++ b/cosmwasm/packages/wasmd-client/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "wasmd-client" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +authors.workspace = true + +[lib] +path="src/lib.rs" + +[dependencies] +anyhow.workspace = true +cosmrs.workspace = true +hex.workspace = true +reqwest.workspace = true +serde.workspace = true +serde_json.workspace = true \ No newline at end of file diff --git a/utils/cycles-sync/src/wasmd_client.rs b/cosmwasm/packages/wasmd-client/src/lib.rs similarity index 98% rename from utils/cycles-sync/src/wasmd_client.rs rename to cosmwasm/packages/wasmd-client/src/lib.rs index 4010ee0..54d4184 100644 --- a/utils/cycles-sync/src/wasmd_client.rs +++ b/cosmwasm/packages/wasmd-client/src/lib.rs @@ -244,9 +244,11 @@ impl WasmdClient for CliWasmdClient { serde_json::from_slice(&output.stdout).unwrap_or_default(); let trusted_height = query_result["SyncInfo"]["latest_block_height"] - .as_u64() + .as_str() .ok_or(anyhow!("Could not query height"))?; + let trusted_height = trusted_height.parse::()?; + let trusted_hash = query_result["SyncInfo"]["latest_block_hash"] .as_str() .ok_or(anyhow!("Could not query height"))? diff --git a/utils/cycles-sync/Cargo.toml b/utils/cycles-sync/Cargo.toml index 1e9e5f3..7d93b3b 100644 --- a/utils/cycles-sync/Cargo.toml +++ b/utils/cycles-sync/Cargo.toml @@ -9,13 +9,6 @@ repository.workspace = true keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"] readme = "README.md" -[lib] -path = "src/lib.rs" - -[[bin]] -name = "submit" -path = "src/bin/submit.rs" - [dependencies] # external async-trait.workspace = true @@ -41,6 +34,8 @@ cosmwasm-std.workspace = true # quartz cw-tee-mtcs = { path = "../../apps/mtcs/contracts/cw-tee-mtcs/" } +wasmd-client.workspace = true +mtcs-enclave.workspace = true [dev-dependencies] rand_core.workspace = true diff --git a/utils/cycles-sync/src/bin/submit.rs b/utils/cycles-sync/src/bin/submit.rs deleted file mode 100644 index a5f3d85..0000000 --- a/utils/cycles-sync/src/bin/submit.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::str::FromStr; - -use anyhow::anyhow; -use bip32::secp256k1::{ - ecdsa::VerifyingKey, - sha2::{Digest, Sha256}, -}; -use clap::Parser; -use cosmrs::{tendermint::chain::Id as TmChainId, AccountId}; -use cosmwasm_std::{Addr, HexBinary}; -use cw_tee_mtcs::state::{LiquiditySource, LiquiditySourceType}; -use cycles_sync::{ - types::{ - ContractObligation, RawEncryptedObligation, RawSetOff, SubmitObligationsMsg, - SubmitObligationsMsgInner, - }, - wasmd_client::{CliWasmdClient, WasmdClient}, -}; -use reqwest::Url; -use serde::{Deserialize, Serialize}; -use subtle_encoding::bech32::decode as bech32_decode; - -// const MNEMONIC_PHRASE: &str = "clutch debate vintage foster barely primary clown leader sell manual leopard ladder wet must embody story oyster imitate cable alien six square rice wedding"; - -const ADDRESS_PREFIX: &str = "wasm"; - -type Sha256Digest = [u8; 32]; - -#[derive(Clone, Debug, Serialize, Deserialize)] -struct QueryAllSetoffsResponse { - setoffs: Vec<(HexBinary, RawSetOff)>, -} - -#[derive(Clone, Debug, Parser)] -#[command(version, about, long_about = None)] -struct Cli { - #[arg(short, long, value_parser = wasmaddr_to_id)] - mtcs: AccountId, - - #[arg(short, long)] - epoch_pk: String, - - #[arg(short, long)] - overdraft: String, - - #[clap(long)] - flip: bool, - - #[arg( - short, - long, - default_value = "wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70" - )] - admin: String, -} - -#[tokio::main] -async fn main() -> Result<(), anyhow::Error> { - let cli = Cli::parse(); - let mut alice = Addr::unchecked("wasm124tuy67a9dcvfgcr4gjmz60syd8ddaugl33v0n"); - let mut bob = Addr::unchecked("wasm1ctkqmg45u85jnf5ur9796h7ze4hj6ep5y7m7l6"); - let overdraft = Addr::unchecked(cli.overdraft); - - if cli.flip { - let temp = alice.clone(); - alice = bob; - bob = temp; - } - - let alice_to_bob: ContractObligation = ContractObligation { - debtor: alice.clone(), - creditor: bob.clone(), - amount: 10, - salt: HexBinary::from([0; 64]), - }; - - let bob_acceptance: ContractObligation = ContractObligation { - debtor: bob.clone(), - creditor: overdraft.clone(), - amount: 10, - salt: HexBinary::from([0; 64]), - }; - - let alice_tender: ContractObligation = ContractObligation { - debtor: overdraft.clone(), - creditor: alice.clone(), - amount: 10, - salt: HexBinary::from([0; 64]), - }; - - let intents = vec![alice_to_bob, bob_acceptance, alice_tender]; - let epoch_pk = VerifyingKey::from_sec1_bytes(&hex::decode(cli.epoch_pk).unwrap()).unwrap(); - - let intents_enc = encrypt_overdraft_intents(intents, &epoch_pk); - - let liquidity_sources: Vec = vec![LiquiditySource { - address: overdraft, - source_type: LiquiditySourceType::Overdraft, - }]; - - let msg = create_wasm_msg(intents_enc, liquidity_sources)?; - - let node_url = Url::parse("http://143.244.186.205:26657")?; - let chain_id = TmChainId::from_str("testing")?; - - let wasmd_client = CliWasmdClient::new(node_url); - - wasmd_client.tx_execute(&cli.mtcs, &chain_id, 3000000, &cli.admin.to_string(), msg)?; - - Ok(()) -} - -pub struct OverdraftObligation { - pub debtor: Addr, - pub creditor: Addr, - pub amount: u64, -} - -fn encrypt_overdraft_intents( - intents: Vec, - epoch_pk: &VerifyingKey, -) -> Vec<(Sha256Digest, Vec)> { - let mut intents_enc = vec![]; - - for i in intents { - // serialize intent - let i_ser = serde_json::to_string(&i).unwrap(); - - // encrypt intent - let i_cipher = ecies::encrypt(&epoch_pk.to_sec1_bytes(), i_ser.as_bytes()).unwrap(); - - // hash intent - let i_digest: Sha256Digest = { - let mut hasher = Sha256::new(); - hasher.update(i_ser); - hasher.finalize().into() - }; - - intents_enc.push((i_digest, i_cipher)); - } - - intents_enc -} - -fn create_wasm_msg( - obligations_enc: Vec<(Sha256Digest, Vec)>, - liquidity_sources: Vec, -) -> anyhow::Result { - let obligations_enc: Vec<_> = obligations_enc - .into_iter() - .map(|(digest, ciphertext)| { - let digest = HexBinary::from(digest); - let ciphertext = HexBinary::from(ciphertext); - RawEncryptedObligation { digest, ciphertext } - }) - .collect(); - - let msg = SubmitObligationsMsg { - submit_obligations: SubmitObligationsMsgInner { - obligations: obligations_enc, - liquidity_sources, - }, - }; - serde_json::to_value(msg).map_err(Into::into) -} - -fn wasmaddr_to_id(address_str: &str) -> anyhow::Result { - let (hr, _) = bech32_decode(address_str).map_err(|e| anyhow!(e))?; - if hr != ADDRESS_PREFIX { - return Err(anyhow!(hr)); - } - - Ok(address_str.parse().unwrap()) -} diff --git a/utils/cycles-sync/src/cli.rs b/utils/cycles-sync/src/cli.rs deleted file mode 100644 index e30d607..0000000 --- a/utils/cycles-sync/src/cli.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::path::PathBuf; - -use clap::{Parser, Subcommand}; -use cosmrs::{tendermint::chain::Id, AccountId}; -use displaydoc::Display; -use reqwest::Url; -use subtle_encoding::{bech32::decode as bech32_decode, Error as Bech32DecodeError}; -use thiserror::Error; -use uuid::Uuid; - -const ADDRESS_PREFIX: &str = "wasm"; - -#[derive(Clone, Debug, Parser)] -#[command(author, version, about)] -pub struct Cli { - /// Increase output logging verbosity to debug level. - #[arg(short, long)] - pub verbose: bool, - - /// The host to which to bind the API server. - #[arg(short = 'N', long, default_value = "http://127.0.0.1:26657")] - pub node: Url, - - /// Obligato API server. - #[arg(long, default_value = "https://bisenzone.obligato.network")] - pub obligato_url: Url, - - /// Obligato key. - #[arg( - long, - default_value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNhZXNzdGpjdG16bXVqaW55cGJlIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcwMzAxOTE0OSwiZXhwIjoyMDE4NTk1MTQ5fQ.EV6v5J3dz8WHAdTK4_IEisKzF-n1Gqyn4wCce_Zrqf4" - )] - pub obligato_key: String, - - /// Path to output CSV file - #[arg(short, long)] - pub keys_file: PathBuf, - - /// Path to obligation-user map - #[arg(short, long)] - pub obligation_user_map_file: PathBuf, - - /// Chain-id of MTCS chain - #[arg(long, default_value = "testing")] - pub chain_id: Id, - - /// Smart contract address - #[arg(short, long, value_parser = wasm_address)] - pub contract: AccountId, - - /// tx sender address - #[arg(short, long)] - pub user: String, - - /// Main command - #[command(subcommand)] - pub command: CliCommand, -} - -#[derive(Clone, Debug, Subcommand)] -pub enum CliCommand { - /// Sync obligations - SyncObligations { - /// epoch pk - #[arg(short, long)] - epoch_pk: String, - /// liquidity sources' UUIDs - #[arg(short, long, num_args = 1.., value_parser = parse_uuid)] - liquidity_sources: Vec, - }, - /// Sync set-offs - SyncSetOffs, - /// Get address for Uuid - GetAddress { - #[arg(long, value_parser = parse_uuid)] - uuid: Uuid, - }, -} - -#[derive(Display, Error, Debug)] -pub enum AddressError { - /// Address is not bech32 encoded - NotBech32Encoded(#[source] Bech32DecodeError), - /// Human readable part mismatch (expected `wasm`, found {0}) - HumanReadableMismatch(String), -} - -fn wasm_address(address_str: &str) -> Result { - let (hr, _) = bech32_decode(address_str).map_err(AddressError::NotBech32Encoded)?; - if hr != ADDRESS_PREFIX { - return Err(AddressError::HumanReadableMismatch(hr)); - } - - Ok(address_str.parse().unwrap()) -} - -fn parse_uuid(uuid_str: &str) -> Result { - Uuid::parse_str(uuid_str).map_err(|e| e.to_string()) -} diff --git a/utils/cycles-sync/src/lib.rs b/utils/cycles-sync/src/lib.rs deleted file mode 100644 index 2c52633..0000000 --- a/utils/cycles-sync/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod cli; -pub mod obligato_client; -pub mod types; -pub mod wasmd_client; diff --git a/utils/cycles-sync/src/main.rs b/utils/cycles-sync/src/main.rs index d886a25..77e2ce7 100644 --- a/utils/cycles-sync/src/main.rs +++ b/utils/cycles-sync/src/main.rs @@ -1,237 +1,129 @@ -use std::{ - collections::{HashMap, HashSet}, - error::Error, - fs::File, - io::{BufReader, BufWriter, Write}, - path::PathBuf, - str::FromStr, -}; +use std::str::FromStr; -use bip32::{ - secp256k1::{ - ecdsa::VerifyingKey, - sha2::{Digest, Sha256}, - }, - Error as Bip32Error, Language, Mnemonic, Prefix, PrivateKey, Seed, XPrv, +use anyhow::anyhow; +use bip32::secp256k1::{ + ecdsa::VerifyingKey, + sha2::{Digest, Sha256}, }; use clap::Parser; -use cosmrs::{tendermint::account::Id as TmAccountId, AccountId}; -use cosmwasm_std::HexBinary; -use serde::{Deserialize, Serialize}; -use serde_json::json; -use tracing::{debug, Level}; -use uuid::Uuid; - -use crate::{ - cli::{Cli, CliCommand}, - obligato_client::{http::HttpClient, Client}, - types::{ - Obligation, ObligatoObligation, ObligatoSetOff, RawEncryptedObligation, RawObligation, - RawOffset, RawSetOff, SubmitObligatioMsg, SubmitObligatoObligationsMsgInner, - }, - wasmd_client::{CliWasmdClient, QueryResult, WasmdClient}, +use cosmrs::{tendermint::chain::Id as TmChainId, AccountId}; +use cosmwasm_std::{Addr, HexBinary}; +use cw_tee_mtcs::state::{LiquiditySource, LiquiditySourceType}; +use mtcs_enclave::types::{ + ContractObligation, RawEncryptedObligation, RawSetOff, SubmitObligationsMsg, + SubmitObligationsMsgInner, }; +use reqwest::Url; +use serde::{Deserialize, Serialize}; +use subtle_encoding::bech32::decode as bech32_decode; +use wasmd_client::{CliWasmdClient, WasmdClient}; -mod cli; -mod obligato_client; -mod types; -mod wasmd_client; - -const MNEMONIC_PHRASE: &str = "clutch debate vintage foster barely primary clown leader sell manual leopard ladder wet must embody story oyster imitate cable alien six square rice wedding"; +// const MNEMONIC_PHRASE: &str = "clutch debate vintage foster barely primary clown leader sell manual leopard ladder wet must embody story oyster imitate cable alien six square rice wedding"; const ADDRESS_PREFIX: &str = "wasm"; type Sha256Digest = [u8; 32]; -type DynError = Box; - #[derive(Clone, Debug, Serialize, Deserialize)] struct QueryAllSetoffsResponse { setoffs: Vec<(HexBinary, RawSetOff)>, } +#[derive(Clone, Debug, Parser)] +#[command(version, about, long_about = None)] +struct Cli { + #[arg(short, long, value_parser = wasmaddr_to_id)] + mtcs: AccountId, + + #[arg(short, long)] + epoch_pk: String, + + #[arg(short, long)] + overdraft: String, + + #[clap(long)] + flip: bool, + + #[arg( + short, + long, + default_value = "wasm14qdftsfk6fwn40l0xmruga08xlczl4g05npy70" + )] + admin: String, +} + #[tokio::main] -async fn main() -> Result<(), DynError> { +async fn main() -> Result<(), anyhow::Error> { let cli = Cli::parse(); - tracing_subscriber::fmt() - .with_max_level(if cli.verbose { - Level::DEBUG - } else { - Level::ERROR - }) - .with_level(true) - .with_writer(std::io::stderr) - .init(); + let mut alice = Addr::unchecked("wasm124tuy67a9dcvfgcr4gjmz60syd8ddaugl33v0n"); + let mut bob = Addr::unchecked("wasm1ctkqmg45u85jnf5ur9796h7ze4hj6ep5y7m7l6"); + let overdraft = Addr::unchecked(cli.overdraft); - match cli.command { - CliCommand::SyncObligations { - ref epoch_pk, - ref liquidity_sources, - } => sync_obligations(cli.clone(), epoch_pk, liquidity_sources).await?, - CliCommand::SyncSetOffs => sync_setoffs(cli).await?, - CliCommand::GetAddress { uuid } => address_from_uuid(uuid)?, + if cli.flip { + let temp = alice.clone(); + alice = bob; + bob = temp; } - Ok(()) -} - -fn address_from_uuid(uuid: Uuid) -> Result<(), DynError> { - let seed = global_seed()?; - let sk = derive_child_xprv(&seed, uuid); - let pk_b = sk.public_key().public_key().to_sec1_bytes(); - let pk = VerifyingKey::from_sec1_bytes(&pk_b)?; - println!("{}", wasm_address(pk)); - Ok(()) -} - -fn wasm_address(pk: VerifyingKey) -> String { - let tm_pk = TmAccountId::from(pk); - AccountId::new(ADDRESS_PREFIX, tm_pk.as_bytes()) - .unwrap() - .to_string() -} - -fn global_seed() -> Result { - let mnemonic = Mnemonic::new(MNEMONIC_PHRASE, Language::English)?; - Ok(mnemonic.to_seed("password")) -} - -async fn sync_setoffs(cli: Cli) -> Result<(), DynError> { - let wasmd_client = CliWasmdClient::new(cli.node); - let query_result: QueryResult = - wasmd_client.query_smart(&cli.contract, json!("get_all_setoffs"))?; - let setoffs = query_result.data.setoffs; - - // read keys - let keys = read_keys_file(cli.keys_file)?; - let obligation_user_map = read_obligation_user_map_file(cli.obligation_user_map_file)?; - - let setoffs: Vec = setoffs - .iter() - .flat_map(|(obligation_digest, so)| match so { - RawSetOff::SetOff(sos_enc) => { - let so_enc = sos_enc.first().unwrap(); - let (debtor_id, creditor_id) = - obligation_user_map.get(obligation_digest).copied().unwrap(); - - let sk = |id| keys[&id].private_key().to_bytes(); - let so_ser = if let Ok(so) = ecies::decrypt(&sk(debtor_id), so_enc.as_slice()) { - so - } else if let Ok(so) = ecies::decrypt(&sk(creditor_id), so_enc.as_slice()) { - so - } else { - unreachable!() - }; - - let so: RawOffset = serde_json::from_slice(&so_ser).unwrap(); - Some(ObligatoSetOff { - debtor_id, - creditor_id, - amount: so.set_off, - }) - } - RawSetOff::Transfer(_) => None, - }) - .collect(); - - debug!("setoffs: {setoffs:?}"); - - // send to Obligato - let client = HttpClient::new(cli.obligato_url, cli.obligato_key); - client.set_setoffs(setoffs).await?; - - Ok(()) -} - -async fn sync_obligations( - cli: Cli, - epoch_pk: &str, - liquidity_sources: &[Uuid], -) -> Result<(), DynError> { - let mut intents = { - let client = HttpClient::new(cli.obligato_url.clone(), cli.obligato_key); - client - .get_obligations() - .await - .map_err(|_| cli.obligato_url.to_string())? + let alice_to_bob: ContractObligation = ContractObligation { + debtor: alice.clone(), + creditor: bob.clone(), + amount: 10, + salt: HexBinary::from([0; 64]), }; - let keys = derive_keys(&mut intents, liquidity_sources)?; - write_keys_to_file(cli.keys_file, &keys); - - add_default_acceptances(&mut intents, liquidity_sources); - - debug!("intents: {intents:?}"); - - let intents_enc = { - let epoch_pk = VerifyingKey::from_sec1_bytes(&hex::decode(epoch_pk).unwrap()).unwrap(); - encrypt_intents(intents, &keys, &epoch_pk, cli.obligation_user_map_file) + let bob_acceptance: ContractObligation = ContractObligation { + debtor: bob.clone(), + creditor: overdraft.clone(), + amount: 10, + salt: HexBinary::from([0; 64]), }; - debug!("Encrypted {} intents", intents_enc.len()); - let liquidity_sources = liquidity_sources - .iter() - .map(|id| keys[id].private_key().public_key()) - .collect(); + let alice_tender: ContractObligation = ContractObligation { + debtor: overdraft.clone(), + creditor: alice.clone(), + amount: 10, + salt: HexBinary::from([0; 64]), + }; + + let intents = vec![alice_to_bob, bob_acceptance, alice_tender]; + let epoch_pk = VerifyingKey::from_sec1_bytes(&hex::decode(cli.epoch_pk).unwrap()).unwrap(); + + let intents_enc = encrypt_overdraft_intents(intents, &epoch_pk); + + let liquidity_sources: Vec = vec![LiquiditySource { + address: overdraft, + source_type: LiquiditySourceType::Overdraft, + }]; let msg = create_wasm_msg(intents_enc, liquidity_sources)?; - let wasmd_client = CliWasmdClient::new(cli.node); - wasmd_client.tx_execute(&cli.contract, &cli.chain_id, 3000000, &cli.user, msg)?; + + let node_url = Url::parse("http://143.244.186.205:26657")?; + let chain_id = TmChainId::from_str("testing")?; + + let wasmd_client = CliWasmdClient::new(node_url); + + wasmd_client.tx_execute(&cli.mtcs, &chain_id, 3000000, &cli.admin.to_string(), msg)?; Ok(()) } -fn create_wasm_msg( - obligations_enc: Vec<(Sha256Digest, Vec)>, - liquidity_sources: Vec, -) -> Result { - let obligations_enc: Vec<_> = obligations_enc - .into_iter() - .map(|(digest, ciphertext)| { - let digest = HexBinary::from(digest); - let ciphertext = HexBinary::from(ciphertext); - RawEncryptedObligation { digest, ciphertext } - }) - .collect(); - - let liquidity_sources = liquidity_sources - .into_iter() - .map(|pk| HexBinary::from(pk.to_sec1_bytes().as_ref())) - .collect(); - - let msg = SubmitObligatioMsg { - submit_obligations: SubmitObligatoObligationsMsgInner { - obligations: obligations_enc, - liquidity_sources, - }, - }; - serde_json::to_value(msg).map_err(Into::into) +pub struct OverdraftObligation { + pub debtor: Addr, + pub creditor: Addr, + pub amount: u64, } -fn encrypt_intents( - intents: Vec, - keys: &HashMap, +fn encrypt_overdraft_intents( + intents: Vec, epoch_pk: &VerifyingKey, - obligation_user_map_file: PathBuf, ) -> Vec<(Sha256Digest, Vec)> { let mut intents_enc = vec![]; - let mut intent_user_map = HashMap::new(); for i in intents { - // create an intent - let ro = { - let o = Obligation { - debtor: keys[&i.debtor_id].private_key().public_key(), - creditor: keys[&i.creditor_id].private_key().public_key(), - amount: i.amount, - salt: [0; 64], - }; - RawObligation::from(o) - }; - // serialize intent - let i_ser = serde_json::to_string(&ro).unwrap(); + let i_ser = serde_json::to_string(&i).unwrap(); // encrypt intent let i_cipher = ecies::encrypt(&epoch_pk.to_sec1_bytes(), i_ser.as_bytes()).unwrap(); @@ -244,167 +136,38 @@ fn encrypt_intents( }; intents_enc.push((i_digest, i_cipher)); - intent_user_map.insert(HexBinary::from(i_digest), (i.debtor_id, i.creditor_id)); } - write_obligation_user_map_to_file(obligation_user_map_file, &intent_user_map); - intents_enc } -fn add_default_acceptances(obligations: &mut Vec, liquidity_sources: &[Uuid]) { - let acceptances = obligations.iter().fold(HashSet::new(), |mut acc, o| { - if !liquidity_sources.contains(&o.debtor_id) { - for ls in liquidity_sources { - let acceptance = ObligatoObligation { - id: Default::default(), - debtor_id: o.creditor_id, - creditor_id: *ls, - amount: u32::MAX as u64, - }; - acc.insert(acceptance); - } - } - acc - }); - - obligations.extend(acceptances.into_iter().collect::>()); -} - -fn read_keys_file(keys_file: PathBuf) -> Result, DynError> { - let keys_file = File::open(keys_file)?; - let keys_reader = BufReader::new(keys_file); - let keys: HashMap = serde_json::from_reader(keys_reader)?; - Ok(keys +fn create_wasm_msg( + obligations_enc: Vec<(Sha256Digest, Vec)>, + liquidity_sources: Vec, +) -> anyhow::Result { + let obligations_enc: Vec<_> = obligations_enc .into_iter() - .map(|(id, key_str)| (id, XPrv::from_str(&key_str).unwrap())) - .collect()) -} - -fn write_keys_to_file(output_file: PathBuf, keys: &HashMap) { - let keys_str: HashMap<_, _> = keys - .iter() - .map(|(id, k)| (id, k.to_string(Prefix::XPRV).to_string())) + .map(|(digest, ciphertext)| { + let digest = HexBinary::from(digest); + let ciphertext = HexBinary::from(ciphertext); + RawEncryptedObligation { digest, ciphertext } + }) .collect(); - let output_file = File::create(output_file).expect("create file"); - let mut output_reader = BufWriter::new(output_file); - output_reader - .write_all(serde_json::to_string(&keys_str).unwrap().as_bytes()) - .expect("write file"); + let msg = SubmitObligationsMsg { + submit_obligations: SubmitObligationsMsgInner { + obligations: obligations_enc, + liquidity_sources, + }, + }; + serde_json::to_value(msg).map_err(Into::into) } -fn read_obligation_user_map_file( - file: PathBuf, -) -> Result, DynError> { - let map_file = File::open(file)?; - let map_reader = BufReader::new(map_file); - serde_json::from_reader(map_reader).map_err(Into::into) -} - -fn write_obligation_user_map_to_file( - output_file: PathBuf, - obligation_user_map: &HashMap, -) { - let output_file = File::create(output_file).expect("create file"); - let mut output_reader = BufWriter::new(output_file); - output_reader - .write_all( - serde_json::to_string(&obligation_user_map) - .unwrap() - .as_bytes(), - ) - .expect("write file"); -} - -fn derive_keys( - obligations: &mut Vec, - liquidity_sources: &[Uuid], -) -> Result, DynError> { - // Derive a BIP39 seed value using the given password - let seed = global_seed()?; - - obligations.sort_by_key(|o| o.debtor_id); - - let mut keys = HashMap::new(); - - for ls in liquidity_sources { - keys.entry(*ls) - .or_insert_with(|| derive_child_xprv(&seed, *ls)); +fn wasmaddr_to_id(address_str: &str) -> anyhow::Result { + let (hr, _) = bech32_decode(address_str).map_err(|e| anyhow!(e))?; + if hr != ADDRESS_PREFIX { + return Err(anyhow!(hr)); } - for o in obligations { - keys.entry(o.debtor_id) - .or_insert_with(|| derive_child_xprv(&seed, o.debtor_id)); - keys.entry(o.creditor_id) - .or_insert_with(|| derive_child_xprv(&seed, o.creditor_id)); - } - - Ok(keys) -} - -fn derive_child_xprv(seed: &Seed, uuid: Uuid) -> XPrv { - // Hash the UUID using SHA-256 - let mut hasher = Sha256::new(); - hasher.update(uuid.as_bytes()); - let uuid_digest = hasher.finalize(); - - // Convert the hash bytes to a number - let uuid_digest_num = u128::from_be_bytes(uuid_digest[..16].try_into().unwrap()); - - // Take modulo (2^31 - 1) - let address_index = uuid_digest_num % ((1u128 << 31) - 1); - - let child_path = format!("m/0/44'/118'/0'/0/{address_index}") - .parse() - .unwrap(); - let child_xprv = XPrv::derive_from_path(seed, &child_path); - child_xprv.unwrap() -} - -#[cfg(test)] -mod tests { - use std::{error::Error, str::FromStr}; - - use bip32::{Mnemonic, Prefix, PrivateKey, XPrv}; - use rand_core::OsRng; - use uuid::Uuid; - - use crate::{derive_child_xprv, global_seed}; - - #[test] - fn test_create_mnemonic() { - // Generate random Mnemonic using the default language (English) - let mnemonic = Mnemonic::random(OsRng, Default::default()); - println!("{}", mnemonic.phrase()); - } - - #[test] - fn test_enc_dec_for_derived() -> Result<(), Box> { - let seed = global_seed()?; - - let alice_uuid = Uuid::from_u128(1); - let alice_sk = derive_child_xprv(&seed, alice_uuid); - let alice_pk = alice_sk.private_key().public_key(); - - assert_eq!( - alice_pk.to_sec1_bytes(), - hex::decode("0219b0b8ee5fe9b317b69119fd15170d79737380c4f020e251b7839096f5513ccf") - .unwrap() - .into() - ); - - let alice_sk_str = alice_sk.to_string(Prefix::XPRV).to_string(); - assert_eq!(XPrv::from_str(&alice_sk_str).unwrap(), alice_sk); - - let msg = r#"{"debtor":"02027e3510f66f1f6c1ea5e3600062255928e518220f7883810cac3fc7fc092057","creditor":"0216254f4636c4e68ae22d98538851a46810b65162fe37bf57cba6d563617c913e","amount":10,"salt":"65c188bcc133add598f7eecc449112f4bf61024345316cff0eb5ce61291991b141073dcd3c543ea142e66fffa8f483dc382043d37e490ef9b8069c489ce94a0b"}"#; - let ciphertext = ecies::encrypt(&alice_pk.to_sec1_bytes(), msg.as_bytes()).unwrap(); - // println!("{}", hex::encode(&ciphertext)); - - let msg_dec = - ecies::decrypt(&alice_sk.private_key().to_bytes(), ciphertext.as_slice()).unwrap(); - assert_eq!(msg, String::from_utf8(msg_dec).unwrap().as_str()); - - Ok(()) - } + Ok(address_str.parse().unwrap()) } diff --git a/utils/cycles-sync/src/obligato_client/http.rs b/utils/cycles-sync/src/obligato_client/http.rs deleted file mode 100644 index b997c8d..0000000 --- a/utils/cycles-sync/src/obligato_client/http.rs +++ /dev/null @@ -1,73 +0,0 @@ -use async_trait::async_trait; -use reqwest::Url; -use serde::{Deserialize, Serialize}; -use serde_json::json; -use tracing::debug; - -use crate::{ - obligato_client::Client, - types::{ObligatoObligation, ObligatoSetOff}, -}; - -pub struct HttpClient { - client: reqwest::Client, - url: Url, - key: String, -} - -impl HttpClient { - pub fn new(url: Url, key: String) -> Self { - Self { - client: reqwest::Client::new(), - url, - key, - } - } - - fn url_with_path(&self, path: &str) -> Url { - let mut url = self.url.clone(); - url.set_path(path); - url - } -} - -#[async_trait] -impl Client for HttpClient { - type Error = reqwest::Error; - - async fn get_obligations(&self) -> Result, Self::Error> { - let response = self - .client - .post(self.url_with_path("api/sync/obligations2contract")) - .json(&json!({"denom_id": "1", "key": self.key })) - .send() - .await? - .json::() - .await?; - - Ok(response.all_obligations.obligations) - } - - async fn set_setoffs(&self, setoffs: Vec) -> Result<(), Self::Error> { - let response = self - .client - .post(self.url_with_path("api/set-offs")) - .json(&setoffs) - .send() - .await?; - debug!("{}", response.text().await.unwrap()); - - Ok(()) - } -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -pub struct GetObligationsInnerResponse { - obligations: Vec, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -pub struct GetObligationsResponse { - #[serde(rename = "allObligations")] - all_obligations: GetObligationsInnerResponse, -} diff --git a/utils/cycles-sync/src/obligato_client/mock.rs b/utils/cycles-sync/src/obligato_client/mock.rs deleted file mode 100644 index ce4354e..0000000 --- a/utils/cycles-sync/src/obligato_client/mock.rs +++ /dev/null @@ -1,40 +0,0 @@ -use async_trait::async_trait; -use uuid::Uuid; - -use crate::{ - obligato_client::Client, - types::{ObligatoObligation, ObligatoSetOff}, -}; - -pub struct MockClient { - pub bank: Uuid, -} - -#[async_trait] -impl Client for MockClient { - type Error = (); - - async fn get_obligations(&self) -> Result, Self::Error> { - Ok(vec![ - // obligation: 1 --10--> 2 - ObligatoObligation { - id: Uuid::from_u128(1), - debtor_id: Uuid::from_u128(1), - creditor_id: Uuid::from_u128(2), - amount: 10, - }, - // tender: $ --10--> 1 - ObligatoObligation { - id: Uuid::from_u128(2), - debtor_id: self.bank, - creditor_id: Uuid::from_u128(1), - amount: 10, - }, - ]) - } - - async fn set_setoffs(&self, setoffs: Vec) -> Result<(), Self::Error> { - println!("{:?}", setoffs); - Ok(()) - } -} diff --git a/utils/cycles-sync/src/obligato_client/mod.rs b/utils/cycles-sync/src/obligato_client/mod.rs deleted file mode 100644 index f31bc4b..0000000 --- a/utils/cycles-sync/src/obligato_client/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -use async_trait::async_trait; - -use crate::types::{ObligatoObligation, ObligatoSetOff}; - -pub mod http; -pub mod mock; - -#[async_trait] -pub trait Client { - type Error; - - async fn get_obligations(&self) -> Result, Self::Error>; - - async fn set_setoffs(&self, setoffs: Vec) -> Result<(), Self::Error>; -} diff --git a/utils/cycles-sync/src/types.rs b/utils/cycles-sync/src/types.rs deleted file mode 100644 index acb352b..0000000 --- a/utils/cycles-sync/src/types.rs +++ /dev/null @@ -1,107 +0,0 @@ -use bip32::secp256k1::ecdsa::VerifyingKey; -use cosmwasm_std::{Addr, HexBinary}; -use cw_tee_mtcs::state::LiquiditySource; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Eq, Hash)] -pub struct ObligatoObligation { - pub id: Uuid, - pub debtor_id: Uuid, - pub creditor_id: Uuid, - pub amount: u64, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ContractObligation { - pub debtor: Addr, - pub creditor: Addr, - pub amount: u64, - #[serde(default)] - pub salt: HexBinary, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RawObligation { - pub debtor: HexBinary, - pub creditor: HexBinary, - pub amount: u64, - #[serde(default)] - pub salt: HexBinary, -} - -#[derive(Clone, Debug)] -pub struct Obligation { - pub debtor: VerifyingKey, - pub creditor: VerifyingKey, - pub amount: u64, - pub salt: [u8; 64], -} - -impl From for RawObligation { - fn from(obligation: Obligation) -> Self { - Self { - debtor: obligation.debtor.to_sec1_bytes().into_vec().into(), - creditor: obligation.creditor.to_sec1_bytes().into_vec().into(), - amount: obligation.amount, - salt: obligation.salt.into(), - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RawEncryptedObligation { - pub digest: HexBinary, - pub ciphertext: HexBinary, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SubmitObligationsMsg { - pub submit_obligations: SubmitObligationsMsgInner, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SubmitObligationsMsgInner { - pub obligations: Vec, - pub liquidity_sources: Vec, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SubmitObligatioMsg { - pub submit_obligations: SubmitObligatoObligationsMsgInner, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SubmitObligatoObligationsMsgInner { - pub obligations: Vec, - pub liquidity_sources: Vec, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -pub struct ObligatoSetOff { - pub debtor_id: Uuid, - pub creditor_id: Uuid, - pub amount: u64, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(untagged)] -pub enum RawSetOff { - SetOff(Vec), - Transfer(RawSetOffTransfer), -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RawSetOffTransfer { - pub payer: String, - pub payee: String, - pub amount: u64, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RawOffset { - pub debtor: HexBinary, - pub creditor: HexBinary, - pub amount: u64, - pub set_off: u64, -} diff --git a/utils/tm-prover/src/prover.rs b/utils/tm-prover/src/prover.rs index f3baec1..422030f 100644 --- a/utils/tm-prover/src/prover.rs +++ b/utils/tm-prover/src/prover.rs @@ -76,6 +76,7 @@ pub async fn prove( .latest_trusted() .ok_or_else(|| eyre!("No trusted state found for primary"))?; + info!("Getting status of node"); let status = client.status().await?; let latest_height = status.sync_info.latest_block_height; let latest_app_hash = status.sync_info.latest_app_hash;