diff --git a/.gitignore b/.gitignore index ba5527bf..f66271c0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ artifacts/ **/.env.local #cli -cli/quartz.toml +crates/cli/quartz.toml .cache/ # Build results diff --git a/Cargo.lock b/Cargo.lock index 24d424bc..9f20c7a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.15" @@ -363,9 +378,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -374,9 +389,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", @@ -766,9 +781,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.23" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "jobserver", "libc", @@ -808,8 +823,11 @@ version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", "serde", + "windows-targets 0.52.6", ] [[package]] @@ -862,9 +880,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" dependencies = [ "clap_builder", "clap_derive", @@ -872,9 +890,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" dependencies = [ "anstream", "anstyle", @@ -1016,20 +1034,21 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cosmos-sdk-proto" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d1a42d9ef55bb4e84b48ce29860f55859e52e0088ebdb1371cedd62f2b78cc" +checksum = "8b2f63ab112b8c8e7b8a29c891adc48f43145beb21c0bfbf562957072c1e0beb" dependencies = [ - "prost 0.12.6", - "prost-types 0.12.6", - "tendermint-proto 0.37.0", + "prost", + "prost-types", + "tendermint-proto", + "tonic", ] [[package]] name = "cosmrs" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85efbd5a3487e52ccd77897ef8f97b077a015953b46623fabc939f39d9c501fc" +checksum = "9f21bb63ec6a903510a3d01f44735dd4914724e5eccbe409e6da6833d17c7829" dependencies = [ "cosmos-sdk-proto", "ecdsa", @@ -1040,7 +1059,7 @@ dependencies = [ "serde_json", "signature", "subtle-encoding", - "tendermint 0.37.0", + "tendermint", "thiserror", ] @@ -1265,11 +1284,17 @@ name = "cw-client" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", + "cosmos-sdk-proto", "cosmrs", "hex", "reqwest 0.12.8", "serde", "serde_json", + "tendermint", + "tokio", + "tonic", + "transfers-contract", ] [[package]] @@ -1285,7 +1310,7 @@ dependencies = [ "cw-utils", "derivative", "itertools 0.13.0", - "prost 0.13.3", + "prost", "schemars", "serde", "sha2 0.10.8", @@ -1446,6 +1471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -2759,6 +2785,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ics23" version = "0.12.0" @@ -2770,7 +2819,7 @@ dependencies = [ "blake3", "bytes", "hex", - "prost 0.13.3", + "prost", "ripemd", "sha2 0.10.8", "sha3", @@ -2862,6 +2911,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -2965,15 +3015,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -4110,16 +4151,6 @@ dependencies = [ "tokio-stream", ] -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive 0.12.6", -] - [[package]] name = "prost" version = "0.13.3" @@ -4127,7 +4158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.13.3", + "prost-derive", ] [[package]] @@ -4144,26 +4175,13 @@ dependencies = [ "once_cell", "petgraph", "prettyplease", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", "regex", "syn 2.0.79", "tempfile", ] -[[package]] -name = "prost-derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" -dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "prost-derive" version = "0.13.3" @@ -4177,22 +4195,13 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "prost-types" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" -dependencies = [ - "prost 0.12.6", -] - [[package]] name = "prost-types" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost 0.13.3", + "prost", ] [[package]] @@ -4233,10 +4242,10 @@ dependencies = [ "displaydoc", "hex", "ics23", - "prost 0.13.3", + "prost", "serde", "serde_with", - "tendermint 0.38.1", + "tendermint", "tendermint-rpc", ] @@ -4249,7 +4258,7 @@ dependencies = [ "hex", "quartz-cw-proof", "serde_json", - "tendermint 0.38.1", + "tendermint", "tendermint-rpc", "tokio", ] @@ -4299,7 +4308,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", "tendermint-rpc", "thiserror", @@ -4323,7 +4332,7 @@ dependencies = [ name = "quartz-proto" version = "0.1.0" dependencies = [ - "prost 0.13.3", + "prost", "tonic", "tonic-build", ] @@ -4351,7 +4360,7 @@ dependencies = [ "k256", "miette", "once_cell", - "prost 0.13.3", + "prost", "quartz-common", "quartz-tee-ra", "quartz-tm-prover", @@ -4359,10 +4368,11 @@ dependencies = [ "reqwest 0.12.8", "serde", "serde_json", + "serde_with", "subtle-encoding", "target-lexicon", "tempfile", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", "tendermint-rpc", "thiserror", @@ -4440,7 +4450,7 @@ dependencies = [ "quartz-cw-proof", "serde", "serde_json", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", "tendermint-light-client-detector", "tendermint-rpc", @@ -4454,7 +4464,7 @@ name = "quartz-tm-stateless-verifier" version = "0.1.0" dependencies = [ "displaydoc", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", ] @@ -5254,13 +5264,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "9720086b3357bcb44fce40117d769a4d068c70ecfa190850a980a71755f66fcc" dependencies = [ "base64 0.22.1", "chrono", "hex", + "indexmap 1.9.3", + "indexmap 2.5.0", "serde", "serde_derive", "serde_json", @@ -5270,9 +5282,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "5f1abbfe725f27678f4663bcacb75a83e829fd464c25d78dd038a3a29e307cec" dependencies = [ "darling", "proc-macro2", @@ -5567,37 +5579,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tendermint" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954496fbc9716eb4446cdd6d00c071a3e2f22578d62aa03b40c7e5b4fda3ed42" -dependencies = [ - "bytes", - "digest 0.10.7", - "ed25519", - "ed25519-consensus", - "flex-error", - "futures", - "k256", - "num-traits", - "once_cell", - "prost 0.12.6", - "prost-types 0.12.6", - "ripemd", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.10.8", - "signature", - "subtle", - "subtle-encoding", - "tendermint-proto 0.37.0", - "time", - "zeroize", -] - [[package]] name = "tendermint" version = "0.38.1" @@ -5610,10 +5591,12 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", + "k256", "num-traits", "once_cell", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", + "ripemd", "serde", "serde_bytes", "serde_json", @@ -5622,7 +5605,7 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.38.1", + "tendermint-proto", "time", "zeroize", ] @@ -5636,7 +5619,7 @@ dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.38.1", + "tendermint", "toml", "url", ] @@ -5658,7 +5641,7 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client-verifier", "tendermint-rpc", "time", @@ -5681,9 +5664,9 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", - "tendermint-proto 0.38.1", + "tendermint-proto", "tendermint-rpc", "time", "tracing", @@ -5698,23 +5681,7 @@ dependencies = [ "derive_more 0.99.18", "flex-error", "serde", - "tendermint 0.38.1", - "time", -] - -[[package]] -name = "tendermint-proto" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" -dependencies = [ - "bytes", - "flex-error", - "prost 0.12.6", - "prost-types 0.12.6", - "serde", - "serde_bytes", - "subtle-encoding", + "tendermint", "time", ] @@ -5726,8 +5693,8 @@ checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" dependencies = [ "bytes", "flex-error", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", "serde", "serde_bytes", "subtle-encoding", @@ -5756,9 +5723,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.38.1", + "tendermint", "tendermint-config", - "tendermint-proto 0.38.1", + "tendermint-proto", "thiserror", "time", "tokio", @@ -5780,12 +5747,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -6033,7 +6000,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.3", + "prost", "socket2", "tokio", "tokio-stream", @@ -6052,7 +6019,7 @@ dependencies = [ "prettyplease", "proc-macro2", "prost-build", - "prost-types 0.13.3", + "prost-types", "quote", "syn 2.0.79", ] @@ -6150,6 +6117,21 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "transfers-contract" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "getrandom", + "quartz-common", + "serde_json", + "sha2 0.10.8", + "thiserror", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -6559,7 +6541,16 @@ version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ - "windows-core", + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ "windows-targets 0.52.6", ] diff --git a/Cargo.toml b/Cargo.toml index 67c182ae..c80be272 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,8 +96,8 @@ x509-parser = { version = "0.16.0", default-features = false, features = [ zeroize = { version = "1.7.0", default-features = false } # cosmos -cosmos-sdk-proto = { version = "0.22.0", default-features = false } -cosmrs = { version = "0.17.0", default-features = false } +cosmos-sdk-proto = { version = "0.23.0", default-features = false } +cosmrs = { version = "0.18.0", default-features = false } cosmwasm-schema = { version = "2.1.1", default-features = false } cosmwasm-std = { version = "2.1.1", default-features = false, features = [ "std", diff --git a/README.md b/README.md index 5ff7d4e4..5c4bccfb 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ The current code contains known bugs and security vulnerabilities and APIs are s Quartz provides developers three main tools: -- a smart contract library (`quartz-cw`) for building SGX-aware CosmWasm contracts -- a rust library (`quartz-enclave`) for building blockchain constrained SGX enclaves +- a smart contract library (`quartz-contract-core`) for building SGX-aware CosmWasm contracts +- a rust library (`quartz-enclave-core`) for building blockchain constrained SGX enclaves - a cli tool (`quartz`) for connecting the contract and the enclave. This repo contains an example, [`transfers`](/apps/transfers), which combines these @@ -60,7 +60,7 @@ frontend. ### Smart Contract Lib -`quartz-cw` does two main things: +`quartz-contract-core` does two main things: - secure session management between contract and enclave - verify remote attestations of authorized SGX enclaves @@ -68,28 +68,28 @@ frontend. It contains the core types for session management and for interfacing with attestations and is the only crate the smart contract dev should have to interact with. -App devs add the `quartz-cw` message types to their contract's messages, +App devs add the `quartz-contract-core` message types to their contract's messages, and call the verify handler on attested messages. While Quartz enables securely attested private compute off-chain, app devs are still responsible for the on-chain data model. See [Building Apps](/docs/building_apps.md) for more. Under the hood, attestation verification itself is performed via two separate contracts: -- `dcap-verifier` - standalone implementation of dcap verification as a contract using +- `quartz-dcap-verifier` - standalone implementation of dcap verification as a contract using mobilecoin's Rust libs -- `tcbinfo` - public registry contract of secure sgx processor/firmware versions to +- `quartz-tcbinfo` - public registry contract of secure sgx processor/firmware versions to ensure attestations are only verified from up-to-date devices The actual types and verification logic for attestation is further encapsulated in `quartz-tee-ra`. ### Enclave Lib -`quartz-enclave` mirrors `quartz-cw`, in that its the enclave side of what happens -on chain. Both have to manage a secure session. Where `quartz-cw` verifies -attestionations, `quartz-enclave` produces them. But additionally, `quartz-enclave` must +`quartz-enclave-core` mirrors `quartz-contract-core`, in that its the enclave side of what happens +on chain. Both have to manage a secure session. Where `quartz-contract-core` verifies +attestations, `quartz-enclave-core` produces them. But additionally, `quartz-enclave-core` must verify the state of the blockchain so that the enclave binary is restricted to only operate authorized commands. It does this via light-client verification. -`quartz-enclave` does the following: +`quartz-enclave-core` does the following: - secure session management between contract and enclave - collect and verify light client proofs of smart contract state @@ -97,9 +97,8 @@ only operate authorized commands. It does this via light-client verification. The underlying implementation includes the following crates: -* light-client-proofs: Light client and merkle proofs for CosmWasm storage -* quartz-proto: protobuf message types for quartz handshake between enclave and - contract +* Light client proofs: Light client and merkle proofs for CosmWasm storage (see utils section below) +* `quartz-proto`: protobuf message types for quartz handshake between enclave and contract ### CLI Tool @@ -123,20 +122,22 @@ And for running everything in one go (build, deploy/start, handshake): ### Utils -The repo contains some additional utilities for supporting Quartz development and - +The repo contains some additional utilities for supporting Quartz development: -* [cw-prover](utils/cw-prover) - Retrieve a merkle-proof for CosmWasm state -* [cycles-sync](utils/cycles-sync) - Sync obligations and setoffs - with [Obligato](https://github.com/informalsystems/obligato) -* [tm-prover](utils/tm-prover) - Generate light client and merkle proofs for CosmWasm storage in a format that Quartz +* [quartz-cw-prover](crates/utils/cw-prover) - Retrieve a merkle-proof for CosmWasm state +* [quartz-tm-prover](crates/utils/tm-prover) - Generate light client and merkle proofs for CosmWasm storage in a format that Quartz understands +* [quartz-cw-client](crates/utils/quartz-cw-client) - Rust client for wasmd + style blockchains +* [quartz-print-fmspc](crates/utils/quartz-print-fmspc) - Print the FMSPC, a + description of the SGX processor family/model etc. + ## Contributing If you're interested in contributing, please comment on a relevant issue (if there is one) or open a new one! See [CONTRIBUTING.md](CONTRIBUTING.md). - ## License TBD diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 3d7d4efd..a85b1d63 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -47,6 +47,7 @@ toml = "0.8.19" figment = { version = "0.10.19", features = ["env", "toml"] } clearscreen = "3.0.0" cargo_metadata = "0.18.1" +serde_with = "3.10.0" # cosmos cosmrs.workspace = true diff --git a/crates/cli/README.md b/crates/cli/README.md index b1385c57..3dab7a9f 100644 --- a/crates/cli/README.md +++ b/crates/cli/README.md @@ -32,43 +32,18 @@ SUBCOMMANDS: To install Quartz, ensure you have Rust and Cargo installed. Then run: ```shell -cargo install quartz +cargo install quartz-rs ``` -## Usage of subcommands +## Usage -### Init +See the [getting started](/docs/getting_started.md). -Initialize a new Quartz app directory structure with optional name and path arguments. - -#### Usage - -```shell -$ quartz init --help -quartz-init -Create base Quartz app directory from template - -USAGE: - quartz init [OPTIONS] - -OPTIONS: - -n, --name Set the name of the Quartz app [default: ] - -p, --path Set the path where the Quartz app will be created [default: .] - -h, --help Print help information -``` - -#### Example - -```shell -quartz init --name --path -``` - -This command will create the following directory structure at the specified path (or the current directory if no path is -provided): +Run `quartz init` to copy the example app into a new directory. Quartz apps are +organized like: ```shell -$ tree // -L 1 -apps/transfers/ +myapp/ ├── contracts/ ├── enclave/ ├── frontend/ diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index b95e789f..8f29c92a 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -4,7 +4,9 @@ use clap::{Parser, Subcommand}; use cosmrs::{tendermint::chain::Id as ChainId, AccountId}; use figment::{providers::Serialized, Figment}; use quartz_common::enclave::types::Fmspc; +use reqwest::Url; use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; use tracing::metadata::LevelFilter; use crate::handler::utils::helpers::wasmaddr_to_id; @@ -79,6 +81,7 @@ pub enum Command { Dev(DevArgs), } +#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, Subcommand, Serialize)] pub enum ContractCommand { Build(ContractBuildArgs), @@ -100,6 +103,7 @@ pub struct InitArgs { pub name: PathBuf, } +#[serde_as] #[derive(Debug, Parser, Clone, Serialize, Deserialize)] pub struct HandshakeArgs { /// Path to create & init a Quartz app, defaults to current path if unspecified @@ -123,7 +127,20 @@ pub struct HandshakeArgs { /// : to tendermint rpc interface for this chain #[arg(long)] #[serde(skip_serializing_if = "Option::is_none")] - pub node_url: Option, + #[serde_as(as = "Option")] + pub node_url: Option, + + /// websocket URL + #[arg(long)] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde_as(as = "Option")] + pub ws_url: Option, + + /// gRPC URL + #[arg(long)] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde_as(as = "Option")] + pub grpc_url: Option, /// RPC interface for the Quartz enclave #[arg(long)] @@ -143,6 +160,7 @@ pub struct ContractBuildArgs { pub contract_manifest: PathBuf, } +#[serde_as] #[derive(Debug, Parser, Clone, Serialize, Deserialize)] pub struct ContractDeployArgs { /// Json-formatted cosmwasm contract initialization message @@ -152,7 +170,20 @@ pub struct ContractDeployArgs { /// : to tendermint rpc interface for this chain #[arg(long)] #[serde(skip_serializing_if = "Option::is_none")] - pub node_url: Option, + #[serde_as(as = "Option")] + pub node_url: Option, + + /// websocket URL + #[arg(long)] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde_as(as = "Option")] + pub ws_url: Option, + + /// gRPC URL + #[arg(long)] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde_as(as = "Option")] + pub grpc_url: Option, /// Name or address of private key with which to sign #[arg(long)] @@ -192,6 +223,10 @@ pub struct EnclaveStartArgs { #[arg(long)] pub unsafe_trust_latest: bool, + /// file containing the secret key of the tx-sender for the enclave + #[arg(long)] + pub sk_file: PathBuf, + /// FMSPC (Family-Model-Stepping-Platform-Custom SKU); required if `MOCK_SGX` is not set #[arg(long)] #[serde(skip_serializing_if = "Option::is_none")] @@ -229,6 +264,10 @@ pub struct DevArgs { #[command(flatten)] pub enclave_build: EnclaveBuildArgs, + /// file containing the secret key of the tx-sender for the enclave + #[arg(long)] + pub sk_file: PathBuf, + /// FMSPC (Family-Model-Stepping-Platform-Custom SKU); required if `MOCK_SGX` is not set #[arg(long)] #[serde(skip_serializing_if = "Option::is_none")] diff --git a/crates/cli/src/config.rs b/crates/cli/src/config.rs index 36144f70..e43c108a 100644 --- a/crates/cli/src/config.rs +++ b/crates/cli/src/config.rs @@ -1,8 +1,11 @@ use std::path::PathBuf; use cosmrs::tendermint::chain::Id as ChainId; +use reqwest::Url; use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; +#[serde_as] #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Config { /// Enable mock SGX mode for testing purposes. @@ -20,7 +23,18 @@ pub struct Config { /// : to tendermint rpc interface for this chain #[serde(default = "default_node_url")] - pub node_url: String, + #[serde_as(as = "DisplayFromStr")] + pub node_url: Url, + + /// websocket URL + #[serde(default = "default_ws_url")] + #[serde_as(as = "DisplayFromStr")] + pub ws_url: Url, + + /// gRPC URL + #[serde(default = "default_grpc_url")] + #[serde_as(as = "DisplayFromStr")] + pub grpc_url: Url, /// RPC interface for the Quartz enclave #[serde(default = "default_rpc_addr")] @@ -52,8 +66,22 @@ fn default_rpc_addr() -> String { "http://127.0.0.1".to_string() } -fn default_node_url() -> String { - "127.0.0.1:26657".to_string() +fn default_node_url() -> Url { + "http://127.0.0.1:26657" + .parse() + .expect("valid hardcoded URL") +} + +fn default_ws_url() -> Url { + "ws://127.0.0.1/websocket" + .parse() + .expect("valid hardcoded URL") +} + +fn default_grpc_url() -> Url { + "http://127.0.0.1:9090," + .parse() + .expect("valid hardcoded URL") } fn default_tx_sender() -> String { @@ -79,6 +107,8 @@ impl Default for Config { tx_sender: default_tx_sender(), chain_id: default_chain_id(), node_url: default_node_url(), + ws_url: default_ws_url(), + grpc_url: default_grpc_url(), enclave_rpc_addr: default_rpc_addr(), enclave_rpc_port: default_port(), app_dir: default_app_dir(), diff --git a/crates/cli/src/handler/contract_deploy.rs b/crates/cli/src/handler/contract_deploy.rs index ae71d3ae..35bcdf26 100644 --- a/crates/cli/src/handler/contract_deploy.rs +++ b/crates/cli/src/handler/contract_deploy.rs @@ -3,16 +3,12 @@ use std::path::Path; use async_trait::async_trait; use cargo_metadata::MetadataCommand; use color_eyre::owo_colors::OwoColorize; -use cw_client::{CliWasmdClient, WasmdClient}; -use reqwest::Url; +use cw_client::{CliClient, CwClient}; use serde_json::json; use tendermint_rpc::HttpClient; use tracing::{debug, info}; -use super::utils::{ - helpers::block_tx_commit, - types::{Log, WasmdTxResponse}, -}; +use super::utils::{helpers::block_tx_commit, types::WasmdTxResponse}; use crate::{ config::Config, error::Error, @@ -68,9 +64,8 @@ async fn deploy( args: ContractDeployRequest, config: &Config, ) -> Result<(u64, String), anyhow::Error> { - let httpurl = Url::parse(&format!("http://{}", config.node_url))?; - let tmrpc_client = HttpClient::new(httpurl.as_str())?; - let cw_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?); + let tmrpc_client = HttpClient::new(config.node_url.as_str())?; + let cw_client = CliClient::neutrond(config.node_url.clone()); info!("🚀 Deploying {} Contract", args.label); let code_id = if config.contract_has_changed(wasm_bin_path).await? { @@ -81,8 +76,23 @@ async fn deploy( )?)?; 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()?; + // Find the 'code_id' attribute + let code_id = res + .tx_result + .events + .iter() + .find(|event| event.kind == "store_code") + .and_then(|event| { + event + .attributes + .iter() + .find(|attr| attr.key_str().unwrap_or("") == "code_id") + }) + .and_then(|attr| attr.value_str().ok().and_then(|v| v.parse().ok())) + .ok_or_else(|| anyhow::anyhow!("Failed to find code_id in the transaction result"))?; + + info!("Code ID: {}", code_id); + config.save_codeid_to_cache(wasm_bin_path, code_id).await?; code_id @@ -108,8 +118,22 @@ async fn deploy( )?)?; let res = block_tx_commit(&tmrpc_client, init_output.txhash).await?; - let log: Vec = serde_json::from_str(&res.tx_result.log)?; - let contract_addr: &String = &log[0].events[1].attributes[0].value; + // Find the '_contract_address' attribute + let contract_addr: String = res + .tx_result + .events + .iter() + .find(|event| event.kind == "instantiate") + .and_then(|event| { + event + .attributes + .iter() + .find(|attr| attr.key_str().unwrap_or("") == "_contract_address") + }) + .and_then(|attr| attr.value_str().ok().and_then(|v| v.parse().ok())) + .ok_or_else(|| { + anyhow::anyhow!("Failed to find contract_address in the transaction result") + })?; info!("🚀 Successfully deployed and instantiated contract!"); info!("🆔 Code ID: {}", code_id); diff --git a/crates/cli/src/handler/dev.rs b/crates/cli/src/handler/dev.rs index 196b7da4..5c80a758 100644 --- a/crates/cli/src/handler/dev.rs +++ b/crates/cli/src/handler/dev.rs @@ -170,6 +170,7 @@ async fn dev_driver( fn spawn_enclave_start(args: &DevRequest, config: &Config) -> Result<(), Error> { // In separate process, launch the enclave let enclave_start = EnclaveStartRequest { + sk_file: args.sk_file.clone(), unsafe_trust_latest: args.unsafe_trust_latest, fmspc: args.fmspc.clone(), tcbinfo_contract: args.tcbinfo_contract.clone(), diff --git a/crates/cli/src/handler/enclave_start.rs b/crates/cli/src/handler/enclave_start.rs index 4afd9160..3a1e365c 100644 --- a/crates/cli/src/handler/enclave_start.rs +++ b/crates/cli/src/handler/enclave_start.rs @@ -5,6 +5,8 @@ use cargo_metadata::MetadataCommand; use color_eyre::owo_colors::OwoColorize; use cosmrs::AccountId; use quartz_common::enclave::types::Fmspc; +use reqwest::Url; +use tendermint::chain::Id; use tokio::process::{Child, Command}; use tracing::{debug, info}; @@ -41,7 +43,11 @@ impl Handler for EnclaveStartRequest { "--trusted-hash".to_string(), trusted_hash.to_string(), "--node-url".to_string(), - config.node_url, + config.node_url.to_string(), + "--ws-url".to_string(), + config.ws_url.to_string(), + "--grpc-url".to_string(), + config.grpc_url.to_string(), "--tx-sender".to_string(), config.tx_sender, ]; @@ -77,15 +83,22 @@ impl Handler for EnclaveStartRequest { // gramine manifest let quartz_dir_canon = &enclave_dir.join(".."); + + debug!("quartz_dir_canon: {:?}", quartz_dir_canon); + gramine_manifest( &trusted_height.to_string(), &trusted_hash.to_string(), + &config.chain_id, quartz_dir_canon, &enclave_dir, + &self.sk_file, fmspc, tcbinfo_contract, dcap_verifier_contract, &config.node_url, + &config.ws_url, + &config.grpc_url, ) .await?; @@ -174,15 +187,20 @@ async fn gramine_sgx_gen_private_key(enclave_dir: &Path) -> Result<(), Error> { Ok(()) } +#[allow(clippy::too_many_arguments)] async fn gramine_manifest( trusted_height: &str, trusted_hash: &str, + chain_id: &Id, quartz_dir: &Path, enclave_dir: &Path, + sk_file: &Path, fmspc: Fmspc, tcbinfo_contract: AccountId, dcap_verifier_contract: AccountId, - node_url: &str, + node_url: &Url, + ws_url: &Url, + grpc_url: &Url, ) -> Result<(), Error> { let host = target_lexicon::HOST; let arch_libdir = format!( @@ -203,11 +221,15 @@ async fn gramine_manifest( .arg("-Dra_type=dcap") .arg(format!("-Dra_client_spid={}", ra_client_spid)) .arg("-Dra_client_linkable=1") + .arg(format!("-Dchain_id={}", chain_id)) .arg(format!("-Dquartz_dir={}", quartz_dir.display())) .arg(format!("-Dtrusted_height={}", trusted_height)) .arg(format!("-Dtrusted_hash={}", trusted_hash)) + .arg(format!("-Dsk_file={}", sk_file.display())) .arg(format!("-Dfmspc={}", hex::encode(fmspc))) .arg(format!("-Dnode_url={}", node_url)) + .arg(format!("-Dws_url={}", ws_url)) + .arg(format!("-Dgrpc_url={}", grpc_url)) .arg(format!("-Dtcbinfo_contract={}", tcbinfo_contract)) .arg(format!( "-Ddcap_verifier_contract={}", diff --git a/crates/cli/src/handler/handshake.rs b/crates/cli/src/handler/handshake.rs index 319b534f..5ea4bfc1 100644 --- a/crates/cli/src/handler/handshake.rs +++ b/crates/cli/src/handler/handshake.rs @@ -1,13 +1,9 @@ -use std::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 cw_client::{CliWasmdClient, WasmdClient}; +use cw_client::{CliClient, CwClient}; use futures_util::stream::StreamExt; use quartz_tm_prover::{config::Config as TmProverConfig, prover::prove}; -use reqwest::Url; use serde_json::json; use tendermint_rpc::{query::EventType, HttpClient, SubscriptionClient, WebSocketClient}; use tracing::{debug, info}; @@ -47,11 +43,8 @@ impl Handler for HandshakeRequest { } 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 cw_client = CliWasmdClient::new(Url::parse(httpurl.as_str())?); + let tmrpc_client = HttpClient::new(config.node_url.as_str())?; + let cw_client = CliClient::neutrond(config.node_url.clone()); let (trusted_height, trusted_hash) = read_cached_hash_height(&config).await?; @@ -69,7 +62,9 @@ async fn handshake(args: HandshakeRequest, config: Config) -> Result Result Result Result { - let (hr, _) = bech32_decode(address_str).map_err(|e| anyhow!(e))?; - if hr != "wasm" { - return Err(anyhow!(hr)); - } - + let _ = bech32_decode(address_str).map_err(|e| anyhow!(e))?; address_str.parse().map_err(|e: ErrorReport| anyhow!(e)) } @@ -59,10 +55,8 @@ pub async fn block_tx_commit(client: &HttpClient, tx: Hash) -> Result Result<(Height, Hash), Error> { - let httpurl = Url::parse(&format!("http://{}", node_url)) - .map_err(|e| Error::GenericErr(e.to_string()))?; - let cw_client = CliWasmdClient::new(httpurl); +pub fn query_latest_height_hash(node_url: Url) -> Result<(Height, Hash), Error> { + let cw_client = CliClient::neutrond(node_url); let (trusted_height, trusted_hash) = cw_client .trusted_height_hash() diff --git a/crates/cli/src/request.rs b/crates/cli/src/request.rs index 60ad6c1a..5f0f987f 100644 --- a/crates/cli/src/request.rs +++ b/crates/cli/src/request.rs @@ -48,6 +48,7 @@ impl TryFrom for Request { label: args.contract_deploy.label, contract_manifest: args.contract_deploy.contract_manifest, release: args.enclave_build.release, + sk_file: args.sk_file, fmspc: args.fmspc, tcbinfo_contract: args.tcbinfo_contract, dcap_verifier_contract: args.dcap_verifier_contract, @@ -101,6 +102,7 @@ impl TryFrom for Request { EnclaveCommand::Build(_) => Ok(EnclaveBuildRequest {}.into()), EnclaveCommand::Start(args) => Ok(EnclaveStartRequest { unsafe_trust_latest: args.unsafe_trust_latest, + sk_file: args.sk_file, fmspc: args.fmspc, tcbinfo_contract: args.tcbinfo_contract, dcap_verifier_contract: args.dcap_verifier_contract, diff --git a/crates/cli/src/request/dev.rs b/crates/cli/src/request/dev.rs index c4f493a1..8ea1bbe5 100644 --- a/crates/cli/src/request/dev.rs +++ b/crates/cli/src/request/dev.rs @@ -13,6 +13,7 @@ pub struct DevRequest { pub label: String, pub contract_manifest: PathBuf, pub release: bool, + pub sk_file: PathBuf, pub fmspc: Option, pub tcbinfo_contract: Option, pub dcap_verifier_contract: Option, diff --git a/crates/cli/src/request/enclave_start.rs b/crates/cli/src/request/enclave_start.rs index 0c2f7fe6..9b1fba5a 100644 --- a/crates/cli/src/request/enclave_start.rs +++ b/crates/cli/src/request/enclave_start.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use cosmrs::AccountId; use quartz_common::enclave::types::Fmspc; use tendermint::{block::Height, Hash}; @@ -11,6 +13,7 @@ use crate::{ #[derive(Clone, Debug)] pub struct EnclaveStartRequest { pub unsafe_trust_latest: bool, + pub sk_file: PathBuf, pub fmspc: Option, pub tcbinfo_contract: Option, pub dcap_verifier_contract: Option, @@ -28,7 +31,7 @@ impl EnclaveStartRequest { if self.unsafe_trust_latest || 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)?; + let (trusted_height, trusted_hash) = query_latest_height_hash(config.node_url.clone())?; Ok((trusted_height, trusted_hash)) } else { diff --git a/crates/common/README.md b/crates/common/README.md new file mode 100644 index 00000000..e2c24a17 --- /dev/null +++ b/crates/common/README.md @@ -0,0 +1,12 @@ +# common + +A simple crate to re-export quartz core and protobufs: + +```rust +#[cfg(feature = "contract")] +pub use quartz_contract_core as contract; +#[cfg(feature = "enclave")] +pub use quartz_enclave_core as enclave; +#[cfg(feature = "proto")] +pub use quartz_proto::quartz as proto; +``` diff --git a/crates/contracts/README.md b/crates/contracts/README.md index 34029afb..0f354f10 100644 --- a/crates/contracts/README.md +++ b/crates/contracts/README.md @@ -1,61 +1,15 @@ # Quartz CosmWasm Packages -This repository contains a collection of packages designed to facilitate the development of CosmWasm smart contracts for Quartz apps. +CosmWasm packages for building Quartz apps and verifying remote +attestations from SGX. -## Packages - -### 1. `quartz-cw` - -The `quartz-cw` package offers a high-level framework for building attestation-aware smart contracts by wrapping CosmWasm messages in TEE attestations (e.g. DCAP). - -- Defines `Attested` wrapper for a message and its attestation -- Supports a MockAttestation type for development ease -- Implements session management for secure communication between contract and enclave -The `quartz-cw` package handles actual DCAP verification within smart contracts by calling the standalone `quartz-dcap-verifier` and `tcbinfo` contracts. - -### 2. `quartz-dcap-verifier` - -Your personal DCAP detective! This package is a standalone smart contract for verifying DCAP attestations that can be called by other contracts. - -- Thin wrapper for standalone smart contract around the functionality provided in the `quartz-tee-ra` package -- Provides query and execute entry points for attestation checks - -### 3. `quartz-tee-ra` - -This `quartz-tee-ra` handles Intel SGX remote attestation for both EPID and DCAP protocols. - -- Verifies EPID and DCAP attestations -- Provides core types and structures for SGX quotes -- Implements cryptographic verification of attestation reports - -### 4. `tcbinfo` - -The `tcbinfo` package manages and verifies TCB information crucial for maintaining enclave security. +The main interface for CosmWasm developers is package `core`. -- Stores and retrieves TCB information -- Verifies TCB signatures and certificates -- Provides a CosmWasm contract for TCB management - -### 5. `wasmd-client` - -The `wasmd-client` package offers a Rust client interface for interacting with Wasmd nodes. - -- Defines traits for querying and executing CosmWasm contracts -- Provides utilities for deploying and interacting with contracts - - -## Examples - -Check out the `integration_tests` modules in each package for usage examples and best practices! - -## Contributing - -We welcome contributions from the community! If you find any issues or have suggestions for improvement, please open an issue or submit a pull request. Make sure to follow the contribution guidelines outlined in the repository. - - -## Contact - -If you have any questions or need further assistance, please reach out to us at [quartz.support@informal.systems](mailto:quartz.support@informal.systems). +## Packages +1. `quartz-contract-core`. High-level framework for building attestation-aware smart contracts by wrapping CosmWasm messages in TEE attestations (e.g. DCAP). +1. `quartz-dcap-verifier`: Standalone smart contract for verifying DCAP attestations that can be called by other contracts. +1. `quartz-tee-ra`: Implements core types for SGX quotes and verification for + DCAP attestations +1. `quartz-tcbinfo`: Standalone smart contract for verifying attestations come + from valid/secure Trusted Compute Base (TCB) diff --git a/crates/contracts/core/README.md b/crates/contracts/core/README.md index 9267c329..dab31de7 100644 --- a/crates/contracts/core/README.md +++ b/crates/contracts/core/README.md @@ -1,28 +1,30 @@ -# Quartz CosmWasm (quartz-cw) +# Quartz CosmWasm (quartz-contract-core) -Quartz CosmWasm (quartz-cw) is a high-level framework for building attestation-aware smart contracts on CosmWasm. It provides a robust foundation for developing secure, Intel SGX-based contracts with built-in remote attestation support. +Quartz CosmWasm (quartz-contract-core) is a high-level framework for building attestation-aware smart contracts on CosmWasm. It provides a robust foundation for developing secure, Intel SGX-based contracts with built-in remote attestation support. ## Features -- `Attested` wrapper for secure message handling -- Traits and structures for easy contract development -- State management and message handling utilities -- Support for both DCAP and EPID attestation protocols +- `Attested` wrapper for a message and its attestation +- MockAttestation type for development ease +- Session management for secure communication between contract and enclave +- Verify DCAP attestations (by calling `dcap-verifier` and `tcbinfo` contracts) - Mock SGX support for testing environments +See also the [spec.md](./SPEC.md) + ## Installation -Add `quartz-cw` to your `Cargo.toml`: +Add `quartz-contract-core` to your `Cargo.toml`: ```toml [dependencies] -quartz-cw = { path = "../packages/quartz-cw" } +quartz-contract-core = { path = "../packages/quartz-contract-core" } ``` ## Usage -Here's a basic example of how to use `quartz-cw` in your CosmWasm contract: +Here's a basic example of how to use `quartz-contract-core` in your CosmWasm contract: ```rust use quartz_cw::prelude::*; @@ -49,7 +51,7 @@ pub fn execute( ## Key Components 1. `Attested`: A wrapper struct for holding a message and its attestation. -2. `Attestation`: A trait for attestation types (DCAP, EPID, Mock). +2. `Attestation`: A trait for attestation types (DCAP, Mock). 3. `HasUserData`: A trait for extracting user data from attestations. 4. `RawHandler`: A trait for handling raw messages. @@ -59,7 +61,7 @@ You can enable mock SGX support for testing by adding the `mock-sgx` feature to ```toml [dependencies] -quartz-cw = { path = "../packages/quartz-cw", features = ["mock-sgx"] } +quartz-contract-core = { path = "../packages/quartz-contract-core", features = ["mock-sgx"] } ``` ## Testing @@ -69,14 +71,3 @@ To run the tests: ```sh cargo test ``` - -## License - -This project is licensed under [LICENSE_NAME]. See the LICENSE file for details. - -## Contributing - -We welcome contributions! Please feel free to submit a Pull Request. - -For more information on the implementation details, check out the following files: - diff --git a/crates/contracts/core/SPEC.md b/crates/contracts/core/SPEC.md index 364e8688..54611b73 100644 --- a/crates/contracts/core/SPEC.md +++ b/crates/contracts/core/SPEC.md @@ -1,9 +1,9 @@ -# Quartz CosmWasm (quartz-cw) Specification +# Quartz CosmWasm (quartz-contract-core) Specification ## Abstract -This document specifies the `quartz-cw` package, which provides a high-level framework for building attestation-aware smart contracts on CosmWasm. The package implements secure message handling, state management, and attestation verification for Intel SGX-based contracts. +This document specifies the `quartz-contract-core` package, which provides a high-level framework for building attestation-aware smart contracts on CosmWasm. The package implements secure message handling, state management, and attestation verification for Intel SGX-based contracts. ## Table of Contents @@ -15,11 +15,11 @@ This document specifies the `quartz-cw` package, which provides a high-level fra ## Introduction -The `quartz-cw` package is designed to facilitate the development of secure, attestation-aware smart contracts on the CosmWasm platform. It provides a set of tools and abstractions that allow developers to easily integrate Intel SGX remote attestation into their smart contracts, ensuring that only authorized enclaves can interact with the contract's sensitive functions. +The `quartz-contract-core` package is designed to facilitate the development of secure, attestation-aware smart contracts on the CosmWasm platform. It provides a set of tools and abstractions that allow developers to easily integrate Intel SGX remote attestation into their smart contracts, ensuring that only authorized enclaves can interact with the contract's sensitive functions. ### Scope -This specification covers the core components of the `quartz-cw` package, including: +This specification covers the core components of the `quartz-contract-core` package, including: 1. The `Attested` wrapper for secure message handling 2. Attestation types and verification processes @@ -30,15 +30,15 @@ This specification covers the core components of the `quartz-cw` package, includ - Provide a secure and easy-to-use framework for attestation-aware smart contracts - Abstract away the complexities of SGX attestation verification -- Ensure compatibility with both DCAP and EPID attestation protocols (though EPID is deprecated now by Intel) +- Ensure compatibility with DCAP attestation protocols (EPID is deprecated now by Intel) - Allow for easy testing and mocking of SGX environments ## Functionality -The `quartz-cw` package provides the following key functionalities: +The `quartz-contract-core` package provides the following key functionalities: 1. Secure message wrapping with `Attested` -2. Attestation verification for DCAP and EPID protocols +2. Attestation verification for DCAP protocols 3. State management utilities for CosmWasm contracts 4. Execution handlers for attested messages @@ -47,12 +47,11 @@ The `quartz-cw` package provides the following key functionalities: - `Attested`: A wrapper struct that holds a message `M` and its attestation `A`. - `Attestation`: A trait that defines the common interface for different attestation types. - `DcapAttestation`: A struct representing a DCAP attestation. -- `EpidAttestation`: A struct representing an EPID attestation. - `MockAttestation`: A struct for mocking attestations in test environments. ## Implementation -The `quartz-cw` package is implemented in Rust and relies on the CosmWasm framework. The main components are: +The `quartz-contract-core` package is implemented in Rust and relies on the CosmWasm framework. The main components are: ### Attested Message Wrapper @@ -87,12 +86,11 @@ pub trait Attestation { ### Attestation Verification -The attestation verification process is handled by the `quartz-tee-ra` package, which is a dependency of `quartz-cw`. The verification functions are called within the execution handlers of `quartz-cw`. +The attestation verification process is handled by the `quartz-tee-ra` package, which is a dependency of `quartz-contract-core`. The verification functions are called within the execution handlers of `quartz-contract-core`. ```rust pub use intel_sgx::{ dcap::verify as verify_dcap_attestation, - epid::{types::IASReport, verifier::verify as verify_epid_attestation}, Error, }; ``` @@ -128,7 +126,7 @@ where ## Properties -The `quartz-cw` package ensures the following properties: +The `quartz-contract-core` package ensures the following properties: 1. **Attestation Integrity**: All messages wrapped with `Attested` must have a valid attestation that can be verified. @@ -136,13 +134,13 @@ The `quartz-cw` package ensures the following properties: 3. **Enclave Identity Verification**: The package verifies that messages come from authorized enclaves by checking the MRENCLAVE value. -4. **Protocol Flexibility**: The package supports both DCAP and EPID attestation protocols, allowing for different SGX deployment scenarios. +4. **DCAP Support**: The package supports DCAP attestation protocols. 5. **Testability**: The mock-sgx feature allows for easy testing of contracts without a real SGX environment. ## Assumptions -The `quartz-cw` package operates under the following assumptions: +The `quartz-contract-core` package operates under the following assumptions: 1. The underlying SGX hardware and software stack is secure and not compromised. @@ -152,8 +150,8 @@ The `quartz-cw` package operates under the following assumptions: 4. The communication channel between the enclave and the smart contract is secure and resistant to man-in-the-middle attacks. -5. The contract developers correctly implement the `quartz-cw` abstractions and follow secure coding practices. +5. The contract developers correctly implement the `quartz-contract-core` abstractions and follow secure coding practices. 6. The MRENCLAVE values of authorized enclaves are known and correctly configured in the contract's state. -By adhering to this specification, developers can create secure, attestation-aware smart contracts that leverage the power of Intel SGX technology within the CosmWasm ecosystem.# Quartz CosmWasm (quartz-cw) Specification +By adhering to this specification, developers can create secure, attestation-aware smart contracts that leverage the power of Intel SGX technology within the CosmWasm ecosystem.# Quartz CosmWasm (`quartz-contract-core`) Specification diff --git a/crates/contracts/dcap-verifier/README.md b/crates/contracts/dcap-verifier/README.md index 9ac8a14b..89929375 100644 --- a/crates/contracts/dcap-verifier/README.md +++ b/crates/contracts/dcap-verifier/README.md @@ -1,5 +1,11 @@ # CosmWasm smart contract to verify DCAP attestations +Your personal DCAP detective! This package is a standalone smart contract for verifying DCAP attestations that can be called by other contracts. + +- Thin wrapper for standalone smart contract around the functionality provided in the `quartz-tee-ra` package +- Provides query and execute entry points for attestation checks + + ## Testing instructions ``` wasmd query wasm contract-state smart "$CONTRACT" '{ @@ -10,4 +16,4 @@ wasmd query wasm contract-state smart "$CONTRACT" '{ "user_data": "9113b0be77ed5d0d68680ec77206b8d587ed40679b71321ccdd5405e4d54a6820000000000000000000000000000000000000000000000000000000000000000" } }' -``` \ No newline at end of file +``` diff --git a/crates/contracts/tcbinfo/Cargo.lock b/crates/contracts/tcbinfo/Cargo.lock deleted file mode 100644 index e1238b2c..00000000 --- a/crates/contracts/tcbinfo/Cargo.lock +++ /dev/null @@ -1,1197 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "asn1-rs" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "bech32" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bnum" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "cc" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "cosmwasm-crypto" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a339f6b59ff7ad4ae05a70512a4f3c19bf8fcc845d46bfef90f4ec0810f72c" -dependencies = [ - "digest 0.10.7", - "ed25519-zebra", - "k256", - "rand_core 0.6.4", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3bfea6af94a83880fb05478135ed0c256d9a2fcde58c595a10d64dcb9c925d" -dependencies = [ - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-schema" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "101d0739564bd34cba9b84bf73665f0822487ae3b29b2dd59930608ed3aafd43" -dependencies = [ - "cosmwasm-schema-derive", - "schemars", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cosmwasm-schema-derive" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4be75f60158478da2c5d319ed59295bca1687ad50c18215a0485aa91a995ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-std" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded932165de44cd0717979c34fc3b84d8e8066b8dde4f5bd78f96a643b090f90" -dependencies = [ - "base64", - "bech32 0.9.1", - "bnum", - "cosmwasm-crypto", - "cosmwasm-derive", - "derivative", - "forward_ref", - "hex", - "schemars", - "serde", - "serde-json-wasm", - "sha2 0.10.8", - "static_assertions", - "thiserror", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-multi-test" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e403ad6ec62c8bcbcb75f7f4940712d0142b6103310da2a9375252b942358caa" -dependencies = [ - "anyhow", - "bech32 0.11.0", - "cosmwasm-std", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools", - "prost", - "schemars", - "serde", - "sha2 0.10.8", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "semver", - "serde", - "thiserror", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash 0.8.11", - "allocator-api2", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2 0.10.8", - "signature", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "oid-registry" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys", -] - -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "schemars" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.68", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "tcbinfo" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "hashbrown 0.14.5", - "schemars", - "serde", - "thiserror", - "x509-parser", -] - -[[package]] -name = "thiserror" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "x509-parser" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "ring", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/crates/contracts/tcbinfo/README.md b/crates/contracts/tcbinfo/README.md index 6ae0123b..eac152ac 100644 --- a/crates/contracts/tcbinfo/README.md +++ b/crates/contracts/tcbinfo/README.md @@ -1,6 +1,6 @@ # CosmWasm SGX TcbInfo Smart Contract -This smart contract facilitates the storage and verification of `TcbInfo`s for Intel SGX. The contract ensures that +Standalone smart contract for storage and verification of `TcbInfo`s for Intel SGX. The contract ensures that TcbInfos are kept up-to-date so other contracts can query the latest TcbInfo state using the quote's `fmspc` during remote attestation verification to ensure the attesting enclave setup is up-to-date. @@ -28,4 +28,4 @@ wasmd tx wasm execute "$CONTRACT" "$EXECUTE" --from alice --chain-id testing -y ```shell wasmd query wasm contract-state smart "$CONTRACT" '{"get_tcb_info": {"fmspc": "00906ED50000"}}' -``` \ No newline at end of file +``` diff --git a/crates/contracts/tee-ra/README.md b/crates/contracts/tee-ra/README.md index b49817b3..d30a12bc 100644 --- a/crates/contracts/tee-ra/README.md +++ b/crates/contracts/tee-ra/README.md @@ -1,23 +1,13 @@ # Quartz TEE Remote Attestation (quartz-tee-ra) -Quartz TEE Remote Attestation is a Rust library that provides functionality for verifying Intel SGX remote attestations. It supports both EPID and DCAP attestation protocols, making it a versatile tool for secure enclave-based applications. +This `quartz-tee-ra` handles Intel SGX remote attestation for DCAP. ## Features -- EPID attestation verification - DCAP attestation verification - Support for Intel SGX quote parsing and validation - Integration with MobileCoin's attestation verifier -## Installation - -Add `quartz-tee-ra` to your `Cargo.toml`: - -```toml -[dependencies] -quartz-tee-ra = { path = "../packages/quartz-tee-ra" } -``` - ## Usage Here's a basic example of how to use `quartz-tee-ra` for DCAP attestation verification: @@ -36,19 +26,6 @@ fn verify_attestation(quote: Quote3>, collateral: Collateral, identities } ``` -For EPID attestation: - -```rust -use quartz_tee_ra::{verify_epid_attestation, IASReport}; - -fn verify_epid_attestation(report: IASReport, mrenclave: Vec, user_data: Vec) { - match verify_epid_attestation(report, mrenclave, user_data) { - Ok(_) => println!("EPID attestation verified successfully!"), - Err(e) => println!("EPID attestation verification failed: {:?}", e), - } -} -``` - ## API Reference The main functions exported by this library are: @@ -57,7 +34,6 @@ The main functions exported by this library are: ```21:25:cosmwasm/packages/quartz-tee-ra/src/lib.rs pub use intel_sgx::{ dcap::verify as verify_dcap_attestation, - epid::{types::IASReport, verifier::verify as verify_epid_attestation}, Error, }; ``` @@ -106,14 +82,6 @@ To run tests: cargo test ``` -## License - -[LICENSE_NAME] - see the LICENSE file for details. - -## Contributing - -Contributions are welcome! Please feel free to submit a Pull Request. - ## Safety This crate uses `#![deny(unsafe_code)]` to ensure everything is implemented in 100% Safe Rust. @@ -141,7 +109,3 @@ This crate uses `#![deny(unsafe_code)]` to ensure everything is implemented in 1 Note: There's a TODO to uncomment the `#![forbid(unsafe_code)]` once better wrappers for FFI structs and constructors are implemented. - -## Disclaimer - -This software is provided "as is" and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose. \ No newline at end of file diff --git a/crates/enclave/core/src/server.rs b/crates/enclave/core/src/server.rs index f184c2dc..1bab59e5 100644 --- a/crates/enclave/core/src/server.rs +++ b/crates/enclave/core/src/server.rs @@ -1,6 +1,7 @@ use std::{ convert::Infallible, net::SocketAddr, + path::PathBuf, sync::{Arc, Mutex}, time::Duration, }; @@ -31,6 +32,7 @@ use quartz_proto::quartz::{ }; use quartz_tm_stateless_verifier::make_provider; use rand::Rng; +use reqwest::Url; use serde::{Deserialize, Serialize}; use tendermint::{block::Height, Hash}; use tendermint_light_client::{ @@ -78,11 +80,14 @@ pub trait WebSocketHandler: Send + Sync + 'static { #[derive(Debug, Clone)] pub struct WsListenerConfig { - pub node_url: String, + pub node_url: Url, + pub ws_url: Url, + pub grpc_url: Url, pub chain_id: String, pub tx_sender: String, pub trusted_hash: Hash, pub trusted_height: Height, + pub sk_file: PathBuf, } /// A trait for wrapping a tonic service with the gRPC server handler @@ -154,8 +159,9 @@ impl QuartzServer { ws_handlers: &Vec>, ws_config: WsListenerConfig, ) -> Result<(), QuartzError> { - let wsurl = format!("ws://{}/websocket", ws_config.node_url); - let (client, driver) = WebSocketClient::new(wsurl.as_str()).await.unwrap(); + let (client, driver) = WebSocketClient::new(ws_config.ws_url.as_str()) + .await + .unwrap(); let driver_handle = tokio::spawn(async move { driver.run().await }); let mut subs = client.subscribe(Query::from(EventType::Tx)).await.unwrap(); diff --git a/crates/enclave/proto/build.rs b/crates/enclave/proto/build.rs index 755f1e02..6f522d81 100644 --- a/crates/enclave/proto/build.rs +++ b/crates/enclave/proto/build.rs @@ -1,6 +1,6 @@ fn main() -> Result<(), Box> { tonic_build::configure() .out_dir("src/prost") - .compile(&["proto/quartz.proto"], &["proto"])?; + .compile_protos(&["proto/quartz.proto"], &["proto"])?; Ok(()) } diff --git a/crates/utils/cw-client/Cargo.toml b/crates/utils/cw-client/Cargo.toml index e13e3167..7e9226a1 100644 --- a/crates/utils/cw-client/Cargo.toml +++ b/crates/utils/cw-client/Cargo.toml @@ -9,12 +9,21 @@ repository.workspace = true authors.workspace = true [lib] -path="src/lib.rs" +path = "src/lib.rs" [dependencies] -cosmrs.workspace = true +async-trait.workspace = true hex.workspace = true reqwest.workspace = true serde.workspace = true serde_json.workspace = true -anyhow.workspace = true \ No newline at end of file +anyhow.workspace = true +tonic.workspace = true + +cosmrs = { workspace = true, default-features = false, features = ["cosmwasm"] } +cosmos-sdk-proto = { workspace = true, default-features = false, features = ["grpc", "grpc-transport"] } +tendermint = { workspace = true, default-features = false } + +[dev-dependencies] +tokio.workspace = true +transfers-contract = { path = "../../../examples/transfers/contracts" } diff --git a/crates/utils/cw-client/README.md b/crates/utils/cw-client/README.md index c35fe59b..0eae2e0f 100644 --- a/crates/utils/cw-client/README.md +++ b/crates/utils/cw-client/README.md @@ -1,6 +1,6 @@ -# wasmd-client +# cw-client -`wasmd-client` is a Rust library that provides a trait and implementation for interacting with CosmWasm-enabled blockchains, specifically designed for use with the `wasmd` daemon. +`cw-client` is a Rust library that provides a trait and implementation for interacting with CosmWasm-enabled blockchains, specifically designed for use with the `wasmd` daemon. ## Features @@ -15,7 +15,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -wasmd-client = { path = "../packages/wasmd-client" } +cw-client = { path = "../packages/cw-client" } ``` ## Usage @@ -23,7 +23,7 @@ wasmd-client = { path = "../packages/wasmd-client" } The main interface is provided through the `WasmdClient` trait: -```9:44:cosmwasm/packages/wasmd-client/src/lib.rs +```9:44:cosmwasm/packages/cw-client/src/lib.rs pub trait WasmdClient { type Address: AsRef; type Query: ToString; diff --git a/crates/utils/cw-client/data/admin.sk b/crates/utils/cw-client/data/admin.sk new file mode 100644 index 00000000..e5b16d52 --- /dev/null +++ b/crates/utils/cw-client/data/admin.sk @@ -0,0 +1 @@ +ffc4d3c9119e9e8263de08c0f6e2368ac5c2dacecfeb393f6813da7d178873d2 \ No newline at end of file diff --git a/crates/utils/cw-client/src/cli.rs b/crates/utils/cw-client/src/cli.rs new file mode 100644 index 00000000..8aea0721 --- /dev/null +++ b/crates/utils/cw-client/src/cli.rs @@ -0,0 +1,255 @@ +use std::process::Command; + +use anyhow::anyhow; +use cosmrs::{tendermint::chain::Id, AccountId}; +use reqwest::Url; +use serde::de::DeserializeOwned; + +use crate::CwClient; + +#[derive(Clone, Debug)] +pub enum CliClientType { + Wasmd, + Neutrond, +} + +impl CliClientType { + fn bin(&self) -> String { + match self { + CliClientType::Wasmd => "wasmd", + CliClientType::Neutrond => "neutrond", + } + .to_string() + } +} + +#[derive(Clone, Debug)] +pub struct CliClient { + kind: CliClientType, + url: Url, + gas_price: String, +} + +impl CliClient { + pub fn new(kind: CliClientType, url: Url, gas_price: String) -> Self { + Self { + kind, + url, + gas_price, + } + } + + pub fn wasmd(url: Url) -> Self { + Self { + kind: CliClientType::Wasmd, + url, + gas_price: "0.0025ucosm".to_string(), + } + } + + pub fn neutrond(url: Url) -> Self { + Self { + kind: CliClientType::Neutrond, + url, + gas_price: "0.0053untrn".to_string(), + } + } + + fn new_command(&self) -> Command { + Command::new(self.kind.bin()) + } +} + +#[async_trait::async_trait] +impl CwClient for CliClient { + type Address = AccountId; + type Query = serde_json::Value; + type RawQuery = String; + type ChainId = Id; + type Error = anyhow::Error; + + async fn query_smart( + &self, + contract: &Self::Address, + query: Self::Query, + ) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["query", "wasm"]) + .args(["contract-state", "smart", contract.as_ref()]) + .arg(query.to_string()) + .args(["--output", "json"]); + + let output = command.output()?; + 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) + } + + fn query_raw( + &self, + contract: &Self::Address, + query: Self::RawQuery, + ) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["query", "wasm"]) + .args(["contract-state", "raw", contract.as_ref()]) + .arg(&query) + .args(["--output", "json"]); + + let output = command.output()?; + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + let query_result: R = serde_json::from_slice(&output.stdout).unwrap_or_default(); + Ok(query_result) + } + + fn query_tx(&self, txhash: &str) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["query", "tx"]) + .arg(txhash) + .args(["--output", "json"]); + + let output = command.output()?; + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + let query_result: R = serde_json::from_slice(&output.stdout).unwrap_or_default(); + Ok(query_result) + } + + async fn tx_execute( + &self, + contract: &Self::Address, + chain_id: &Id, + gas: u64, + sender: &str, + msg: M, + fees: &str, + ) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["--chain-id", chain_id.as_ref()]) + .args(["tx", "wasm"]) + .args(["execute", contract.as_ref(), &msg.to_string()]) + .args(["--gas", &gas.to_string()]) + .args(["--fees", fees]) + .args(["--from", sender]) + .args(["--output", "json"]) + .arg("-y"); + + let output = command.output()?; + + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + // TODO: find the rust type for the tx output and return that + Ok((String::from_utf8(output.stdout)?).to_string()) + } + + fn deploy( + &self, + chain_id: &Id, + sender: &str, + wasm_path: M, + ) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["tx", "wasm", "store", &wasm_path.to_string()]) + .args(["--from", sender]) + .args(["--chain-id", chain_id.as_ref()]) + .args(["--gas-prices", &self.gas_price]) + .args(["--gas", "auto"]) + .args(["--gas-adjustment", "1.3"]) + .args(["-o", "json"]) + .arg("-y"); + + let output = command.output()?; + + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + // TODO: find the rust type for the tx output and return that + Ok((String::from_utf8(output.stdout)?).to_string()) + } + + fn init( + &self, + chain_id: &Id, + sender: &str, + code_id: u64, + init_msg: M, + label: &str, + ) -> Result { + let mut command = self.new_command(); + let command = command + .args(["--node", self.url.as_str()]) + .args(["tx", "wasm", "instantiate"]) + .args([&code_id.to_string(), &init_msg.to_string()]) + .args(["--label", label]) + .args(["--from", sender]) + .arg("--no-admin") + .args(["--chain-id", chain_id.as_ref()]) + .args(["--gas-prices", &self.gas_price]) + .args(["--gas", "auto"]) + .args(["--gas-adjustment", "1.3"]) + .args(["-o", "json"]) + .arg("-y"); + + let output = command.output()?; + + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + // TODO: find the rust type for the tx output and return that + Ok((String::from_utf8(output.stdout)?).to_string()) + } + + fn trusted_height_hash(&self) -> Result<(u64, String), Self::Error> { + let mut command = self.new_command(); + let command = command.args(["--node", self.url.as_str()]).arg("status"); + + let output = command.output()?; + + if !output.status.success() { + return Err(anyhow!("{:?}", output)); + } + + let query_result: serde_json::Value = + serde_json::from_slice(&output.stdout).unwrap_or_default(); + + let sync_info = match self.kind { + CliClientType::Wasmd => "SyncInfo", + CliClientType::Neutrond => "sync_info", + }; + let trusted_height = query_result[sync_info]["latest_block_height"] + .as_str() + .ok_or(anyhow!("Could not query height"))?; + + let trusted_height = trusted_height.parse::()?; + + let trusted_hash = query_result[sync_info]["latest_block_hash"] + .as_str() + .ok_or(anyhow!("Could not query height"))? + .to_string(); + + Ok((trusted_height, trusted_hash)) + } +} diff --git a/crates/utils/cw-client/src/grpc.rs b/crates/utils/cw-client/src/grpc.rs new file mode 100644 index 00000000..be93edec --- /dev/null +++ b/crates/utils/cw-client/src/grpc.rs @@ -0,0 +1,269 @@ +use std::{error::Error, fs::File, io::Read, path::PathBuf}; + +use anyhow::anyhow; +use cosmos_sdk_proto::{ + cosmos::{ + auth::v1beta1::{ + query_client::QueryClient as AuthQueryClient, BaseAccount as RawBaseAccount, + QueryAccountRequest, + }, + tx::v1beta1::{ + service_client::ServiceClient, BroadcastMode, BroadcastTxRequest, BroadcastTxResponse, + }, + }, + cosmwasm::wasm::v1::{ + query_client::QueryClient as WasmdQueryClient, QuerySmartContractStateRequest, + }, + traits::Message, + Any, +}; +use cosmrs::{ + auth::BaseAccount, + cosmwasm::MsgExecuteContract, + crypto::{secp256k1::SigningKey, PublicKey}, + tendermint::chain::Id as TmChainId, + tx, + tx::{Fee, Msg, SignDoc, SignerInfo}, + AccountId, Coin, +}; +use reqwest::Url; +use serde::de::DeserializeOwned; + +use crate::CwClient; + +#[derive(Clone, Debug)] +pub struct GrpcClient { + sk_file: PathBuf, + url: Url, +} + +impl GrpcClient { + pub fn new(sk_file: PathBuf, url: Url) -> Self { + Self { sk_file, url } + } +} + +#[async_trait::async_trait] +impl CwClient for GrpcClient { + type Address = AccountId; + type Query = serde_json::Value; + type RawQuery = String; + type ChainId = TmChainId; + type Error = anyhow::Error; + + async fn query_smart( + &self, + contract: &Self::Address, + query: Self::Query, + ) -> Result { + let mut client = WasmdQueryClient::connect(self.url.to_string()).await?; + + let raw_query_request = QuerySmartContractStateRequest { + address: contract.to_string(), + query_data: query.to_string().into_bytes(), + }; + + let raw_query_response = client.smart_contract_state(raw_query_request).await?; + + let raw_value = raw_query_response.into_inner().data; + serde_json::from_slice(&raw_value) + .map_err(|e| anyhow!("failed to deserialize JSON reponse: {}", e)) + } + + fn query_raw( + &self, + _contract: &Self::Address, + _query: Self::RawQuery, + ) -> Result { + unimplemented!() + } + + fn query_tx(&self, _txhash: &str) -> Result { + unimplemented!() + } + + async fn tx_execute( + &self, + contract: &Self::Address, + chain_id: &TmChainId, + gas: u64, + _sender: &str, + msg: M, + _fees: &str, + ) -> Result { + let secret = { + let mut secret_hex = String::new(); + let mut sk_file = File::open(self.sk_file.clone())?; + sk_file.read_to_string(&mut secret_hex)?; + let secret = hex::decode(secret_hex)?; + SigningKey::from_slice(&secret) + .map_err(|e| anyhow!("failed to read secret key: {}", e))? + }; + + let tm_pubkey = secret.public_key(); + let sender = tm_pubkey + .account_id("neutron") + .map_err(|e| anyhow!("failed to create AccountId from pubkey: {}", e))?; + + let msgs = vec![MsgExecuteContract { + sender: sender.clone(), + contract: contract.clone(), + msg: msg.to_string().into_bytes(), + funds: vec![], + } + .to_any() + .unwrap()]; + + let account = account_info(self.url.to_string(), sender.to_string()) + .await + .map_err(|e| anyhow!("error querying account info: {}", e))?; + let amount = Coin { + amount: 11000u128, + denom: "untrn".parse().expect("hardcoded denom"), + }; + let tx_bytes = tx_bytes( + &secret, + amount, + gas, + tm_pubkey, + msgs, + account.sequence, + account.account_number, + chain_id, + ) + .map_err(|e| anyhow!("failed to create msg/tx: {}", e))?; + + let response = send_tx(self.url.to_string(), tx_bytes) + .await + .map_err(|e| anyhow!("failed to send tx: {}", e))?; + println!("{response:?}"); + Ok(response + .tx_response + .map(|tx_response| tx_response.txhash) + .unwrap_or_default()) + } + + fn deploy( + &self, + _chain_id: &TmChainId, + _sender: &str, + _wasm_path: M, + ) -> Result { + unimplemented!() + } + + fn init( + &self, + _chain_id: &TmChainId, + _sender: &str, + _code_id: u64, + _init_msg: M, + _label: &str, + ) -> Result { + unimplemented!() + } + + fn trusted_height_hash(&self) -> Result<(u64, String), Self::Error> { + unimplemented!() + } +} + +pub async fn account_info( + node: impl ToString, + address: impl ToString, +) -> Result> { + let mut client = AuthQueryClient::connect(node.to_string()).await?; + let request = tonic::Request::new(QueryAccountRequest { + address: address.to_string(), + }); + let response = client.account(request).await?; + let response = RawBaseAccount::decode(response.into_inner().account.unwrap().value.as_slice())?; + let account = BaseAccount::try_from(response)?; + Ok(account) +} + +#[allow(clippy::too_many_arguments)] +pub fn tx_bytes( + secret: &SigningKey, + amount: Coin, + gas: u64, + tm_pubkey: PublicKey, + msgs: Vec, + sequence_number: u64, + account_number: u64, + chain_id: &TmChainId, +) -> Result, Box> { + let tx_body = tx::Body::new(msgs, "", 0u16); + let signer_info = SignerInfo::single_direct(Some(tm_pubkey), sequence_number); + let auth_info = signer_info.auth_info(Fee::from_amount_and_gas(amount, gas)); + let sign_doc = SignDoc::new(&tx_body, &auth_info, chain_id, account_number)?; + let tx_signed = sign_doc.sign(secret)?; + Ok(tx_signed.to_bytes()?) +} + +pub async fn send_tx( + node: impl ToString, + tx_bytes: Vec, +) -> Result> { + let mut client = ServiceClient::connect(node.to_string()).await?; + let request = tonic::Request::new(BroadcastTxRequest { + tx_bytes, + mode: BroadcastMode::Sync.into(), + }); + let tx_response = client.broadcast_tx(request).await?; + Ok(tx_response.into_inner()) +} + +#[cfg(test)] +mod tests { + use std::error::Error; + + use serde_json::json; + use transfers_contract::msg::{execute::Request, QueryMsg::GetRequests}; + + use crate::{CwClient, GrpcClient}; + + #[tokio::test] + #[ignore] + async fn test_query() -> Result<(), Box> { + let sk_file = "../data/admin.sk".parse().unwrap(); + let url = "https://grpc-falcron.pion-1.ntrn.tech:80".parse().unwrap(); + let contract = "neutron15ruzx9wvrupt9cffzsp6868uad2svhfym2nsgxm2skpeqr3qrd4q4uwk83" + .parse() + .unwrap(); + + let cw_client = GrpcClient::new(sk_file, url); + let resp: Vec = cw_client + .query_smart(&contract, json!(GetRequests {})) + .await?; + println!("{resp:?}"); + + Ok(()) + } + + #[tokio::test] + #[ignore] + async fn test_execute() -> Result<(), Box> { + let sk_file = "data/admin.sk".parse().unwrap(); + let url = "https://grpc-falcron.pion-1.ntrn.tech:80".parse().unwrap(); + let contract = "neutron15ruzx9wvrupt9cffzsp6868uad2svhfym2nsgxm2skpeqr3qrd4q4uwk83" + .parse() + .unwrap(); + let chain_id = "pion-1".parse().unwrap(); + + let cw_client = GrpcClient::new(sk_file, url); + let tx_hash = cw_client + .tx_execute( + &contract, + &chain_id, + 2000000, + "/* unused since we're getting the account from the sk */", + json!([]), + "11000untrn", + ) + .await?; + println!("{}", tx_hash); + + Ok(()) + } +} diff --git a/crates/utils/cw-client/src/lib.rs b/crates/utils/cw-client/src/lib.rs index 54d41845..70ecb59e 100644 --- a/crates/utils/cw-client/src/lib.rs +++ b/crates/utils/cw-client/src/lib.rs @@ -1,19 +1,22 @@ -use std::process::Command; - -use anyhow::anyhow; -use cosmrs::{tendermint::chain::Id, AccountId}; +pub use cli::CliClient; +use cosmrs::tendermint::chain::Id; +pub use grpc::GrpcClient; use hex::ToHex; -use reqwest::Url; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::de::DeserializeOwned; + +pub mod cli; + +pub mod grpc; -pub trait WasmdClient { +#[async_trait::async_trait] +pub trait CwClient { type Address: AsRef; type Query: ToString; type RawQuery: ToHex; type ChainId: AsRef; type Error; - fn query_smart( + async fn query_smart( &self, contract: &Self::Address, query: Self::Query, @@ -27,13 +30,14 @@ pub trait WasmdClient { fn query_tx(&self, txhash: &str) -> Result; - fn tx_execute( + async fn tx_execute( &self, contract: &Self::Address, chain_id: &Id, gas: u64, sender: &str, msg: M, + fees: &str, ) -> Result; fn deploy( @@ -54,206 +58,3 @@ pub trait WasmdClient { fn trusted_height_hash(&self) -> Result<(u64, String), Self::Error>; } - -#[derive(Clone, Debug, Serialize, Deserialize, Default)] -pub struct QueryResult { - pub data: T, -} - -#[derive(Clone, Debug)] -pub struct CliWasmdClient { - url: Url, -} - -impl CliWasmdClient { - pub fn new(url: Url) -> Self { - Self { url } - } -} - -impl WasmdClient for CliWasmdClient { - type Address = AccountId; - type Query = serde_json::Value; - type RawQuery = String; - type ChainId = Id; - type Error = anyhow::Error; - - fn query_smart( - &self, - contract: &Self::Address, - query: Self::Query, - ) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["query", "wasm"]) - .args(["contract-state", "smart", contract.as_ref()]) - .arg(query.to_string()) - .args(["--output", "json"]); - - let output = command.output()?; - 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) - } - - fn query_raw( - &self, - contract: &Self::Address, - query: Self::RawQuery, - ) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["query", "wasm"]) - .args(["contract-state", "raw", contract.as_ref()]) - .arg(&query) - .args(["--output", "json"]); - - let output = command.output()?; - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - let query_result: R = serde_json::from_slice(&output.stdout).unwrap_or_default(); - Ok(query_result) - } - - fn query_tx(&self, txhash: &str) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["query", "tx"]) - .arg(txhash) - .args(["--output", "json"]); - - let output = command.output()?; - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - let query_result: R = serde_json::from_slice(&output.stdout).unwrap_or_default(); - Ok(query_result) - } - - fn tx_execute( - &self, - contract: &Self::Address, - chain_id: &Id, - gas: u64, - sender: &str, - msg: M, - ) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["--chain-id", chain_id.as_ref()]) - .args(["tx", "wasm"]) - .args(["execute", contract.as_ref(), &msg.to_string()]) - .args(["--gas", &gas.to_string()]) - .args(["--from", sender]) - .args(["--output", "json"]) - .arg("-y"); - - let output = command.output()?; - - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - // TODO: find the rust type for the tx output and return that - Ok((String::from_utf8(output.stdout)?).to_string()) - } - - fn deploy( - &self, - chain_id: &Id, - sender: &str, - wasm_path: M, - ) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["tx", "wasm", "store", &wasm_path.to_string()]) - .args(["--from", sender]) - .args(["--chain-id", chain_id.as_ref()]) - .args(["--gas-prices", "0.0025ucosm"]) - .args(["--gas", "auto"]) - .args(["--gas-adjustment", "1.3"]) - .args(["-o", "json"]) - .arg("-y"); - - let output = command.output()?; - - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - // TODO: find the rust type for the tx output and return that - Ok((String::from_utf8(output.stdout)?).to_string()) - } - - fn init( - &self, - chain_id: &Id, - sender: &str, - code_id: u64, - init_msg: M, - label: &str, - ) -> Result { - let mut wasmd = Command::new("wasmd"); - let command = wasmd - .args(["--node", self.url.as_str()]) - .args(["tx", "wasm", "instantiate"]) - .args([&code_id.to_string(), &init_msg.to_string()]) - .args(["--label", label]) - .args(["--from", sender]) - .arg("--no-admin") - .args(["--chain-id", chain_id.as_ref()]) - .args(["--gas-prices", "0.0025ucosm"]) - .args(["--gas", "auto"]) - .args(["--gas-adjustment", "1.3"]) - .args(["-o", "json"]) - .arg("-y"); - - let output = command.output()?; - - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - // TODO: find the rust type for the tx output and return that - Ok((String::from_utf8(output.stdout)?).to_string()) - } - - fn trusted_height_hash(&self) -> Result<(u64, String), Self::Error> { - let mut wasmd = Command::new("wasmd"); - let command = wasmd.args(["--node", self.url.as_str()]).arg("status"); - - let output = command.output()?; - - if !output.status.success() { - return Err(anyhow!("{:?}", output)); - } - - let query_result: serde_json::Value = - serde_json::from_slice(&output.stdout).unwrap_or_default(); - - let trusted_height = query_result["SyncInfo"]["latest_block_height"] - .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"))? - .to_string(); - - Ok((trusted_height, trusted_hash)) - } -} diff --git a/docker/enclave-sgx/Dockerfile b/docker/enclave-sgx/Dockerfile index ababf506..f44871d5 100644 --- a/docker/enclave-sgx/Dockerfile +++ b/docker/enclave-sgx/Dockerfile @@ -46,6 +46,7 @@ COPY --from=build /opt/src/${ENCLAVE_DIR}/quartz.manifest.template /opt/enclave/ WORKDIR /opt/enclave +# TODO - update entire file to use DCAP, not EPID RUN gramine-sgx-gen-private-key > /dev/null 2>&1 && \ gramine-manifest \ -Dlog_level="error" \ diff --git a/docs/_getting_started.md b/docs/_getting_started.md deleted file mode 100644 index aa9b1e1a..00000000 --- a/docs/_getting_started.md +++ /dev/null @@ -1,619 +0,0 @@ -# Getting Started - -Here you'll get quickly up and running with an example Quartz application. - -You can run this locally using a "mock" enclave (i.e. without real privacy or -attestations), or you can get access to a machine with Intel SGX enabled to run it securely. - -TODO sections: - -- Transfer Application - describe basic application -- Local Mock SGX - describe getting up and running locally with mock sgx (old demo instructions, updated with new quartz CLI) -done -- Real SGX - describe how to get setup quickly with SGX e.g. on Azure, and how to run the same example there - done needs review -- Public Testnet - describe how to deploy on Neutron testnet - TODO - -## Transfer Application Template - -The Transfer Application is a simple template / demo app designed to showcase very basic use of the Quartz framework. It allows users to deposit funds into a contract, transfer them privately within the contract's encrypted state, and ultimately withdraw whatever balance they have left or have accumulated. - -#### Key Features - -1. **Deposit Funds**: Users can deposit funds into a smart contract. -2. **Private Transfers**: Users can transfer funds privately within the contract - -3. **Withdraw Funds**: Users can withdraw their funds from the contract based on their balance in the encrypted state. - -#### Application Structure - -The application is divided into: - -1. **Frontend**: The user interface built with Next.js, cosmjs / graz. -2. **Contracts**: The backend application as a CosmWasm smart contract -3. **Enclave**: Code that executes off-chain and privately in an enclave - -#### Setting Up the Application - -To get started with the Transfer Application, follow these steps: - -**Prerequisites** -Ensure you have the following installed: -Go: Required for building wasmd. -Make: Typically pre-installed on Linux systems. -Git: For cloning the repository. -Websocat: To listen to the events. - - -### Install Dependencies -Install the necessary dependencies for both the frontend and backend. - -```bash - # Install Rust - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - rustup target add wasm32-unknown-unknown - - # Install Go tools - export PATH="${PATH}:${HOME}/go/bin" - source ~/.bashrc - go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest - - # Install grpcurl - go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest - - # Install websocat - cargo install websocat - -``` - -### Clone the Repository -First, clone the repository to your local machine. - -```bash - git clone ssh://git@github.com/informalsystems/cycles-quartz - cd cycles-quartz -``` - - - -### Install a local daemon (local neutrond/wasmd) -Install a local daemon to be able to easily interact with a local or remote chain. - -a. Neutron -```bash - git clone -b main https://github.com/neutron-org/neutron.git - cd neutron - make install -``` - -After the installation, to verify everything is working run: - -```bash - neutrond version -``` - -b. Wasmd - -```bash - git clone https://github.com/cosmwasm/wasmd/ - cd wasmd - git checkout v0.44.0 / 0.52.0 - go install ./cmd/wasmd -``` - -After the installation, to verify everything is working run: - -```bash - wasmd version -``` - - -### Run a local chain from docker - -Follow the instructions on [the docker folder]() -a. Neutron -```bash - cd docker/neutron - make start-docker-container -``` - -After the installation, you should see a `neutrond` container if you run - -``` - docker ps -``` - -b. Wasmd -```bash - cd docker/wasmd - make run -``` - -After the installation, you should see a `wasmd` container if you run - -``` - docker ps -``` - - - -### Installing the Quartz CLI -To install the Quartz CLI, run the following command from the `cycles-quartz` folder: - -```bash - cargo install --path cli/ -``` - - -### Quickstart on the basic using `dev` -To quickly get up and running, you can run the following `dev` command from the `cycles-quartz` folder: - - -```bash -quartz --mock-sgx --app-dir "apps/transfers/" dev --unsafe-trust-latest --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' -``` - -This command will build contract and enclave binaries, deploy, instantiate the contract, handshake and listen to the contract. - -To stop the enclave: -```bash - pkill -f quartz-app-tran -``` - -To restart: -```bash -rm -rf apps/transfers/.cache && quartz --mock-sgx --app-dir "apps/transfers/" dev --unsafe-trust-latest --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' -``` - -From here you can jump to the section on the [front-end](#### Building the front-end Application). - - - -### Create a new quartz app template - -To create a new Quartz app, use the `init` command: - -```bash -quartz init --name --path /path/to/your/project -``` - -This command will create a new directory structure for your Quartz app: -``` -new_app_name/ -├── contracts/ -├── enclave/ -├── frontend/ -└── README.md -``` - - - -### Build the Binaries -To build both the contract and enclave binaries, use the build command: - -```bash -quartz --mock-sgx --app-dir "apps/transfers/" contract build --contract-manifest "apps/transfers/contracts/Cargo.toml" -``` - -This command will compile the smart contract to WebAssembly and build the enclave binary. - -### Configuring and Running the Enclave - -To configure and run the enclave, use the following commands: - -```bash - # Configure the enclave -quartz --mock-sgx --app-dir "apps/transfers/" enclave build -``` - -```bash - # Start the enclave -quartz --mock-sgx --app-dir "apps/transfers/" enclave start -``` - -The enclave will start running and wait for commands. - -### Deploying the Contract - -With the enclave running, open a new terminal window to deploy the contract: - -```bash -quartz --mock-sgx --app-dir "apps/transfers/" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' - -``` - -Make note of the deployed contract address, as you'll need it for the next step. - -```bash -2024-09-24T11:11:51.233106Z INFO 📌 Contract Address: wasm1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrss5maay -``` - -### Performing the Handshake + activating listener - -To establish communication between the contract and the enclave, perform the handshake: - -```bash -quartz --mock-sgx --app-dir "apps/transfers/" handshake --contract -``` - -Replace `` with the address you received when deploying the contract. - -Make note of the handshake generate public key, as you'll need it for the `.env.local` files on the front-end. - -```bash -2024-09-24T11:12:16.961641Z INFO Handshake complete: 02360955ff74750f6ea0b539f41cce89451f591e4c835d0a5406e6effa96dd169d -``` - -Events coming from the contract will be logged following the handshake as they are retrieved by the listener. - -```bash -2024-09-24T11:12:25.156779Z INFO Enclave is listening for requests... -``` - -#### Building the front-end Application - -Once the application is set up, you can interact with it through the frontend. Make sure you have the Keplr extension installed in your browser. You can then deposit, transfer, and withdraw funds using different Keplr accounts. - - -```bash - # Go to the front-end folder - cd frontend - # Do a fresh install - npm ci - # Copy .env.example - cp .env.example .env.local - # Edit .env.local by adding `` and `` - nano .env.local -``` - -##### Example of app required variables - -``` -NEXT_PUBLIC_TARGET_CHAIN=localWasm -NEXT_PUBLIC_ENCLAVE_PUBLIC_KEY=02360955ff74750f6ea0b539f41cce89451f591e4c835d0a5406e6effa96dd169d -NEXT_PUBLIC_TRANSFERS_CONTRACT_ADDRESS=wasm1jfgr0vgunezkhfmdy7krrupu6yjhx224nxtjptll2ylkkqhyzeshrspu9 -``` - -Once the enviroment variables are set, the front-end application can be started with the following command: - -```bash - npm run dev -``` - - -For more detailed instructions on setting up and using the application, refer to the [README](apps/transfers/README.md) file. - - - -## Interacting with the Application - -Once you have the frontend running and connected to your local blockchain (or testnet), you can interact with the Transfer Application: - -1. Ensure you have the Keplr wallet extension installed in your browser. -2. Use one of the provided accounts [wasmd_docker](docker/wasmd/accounts/) / [neutrond_docker](docker/neutrond/accounts/) ) by importing it into your Keplr wallet or create a new one and fund it using the CLI with your `admin` / `val1` account. -3. Use the frontend to deposit funds into the contract. -4. Transfer funds privately between different accounts within the contract. -5. Withdraw funds from the contract back to your Keplr wallet. - -All transactions will be processed automatically by the enclave, ensuring the privacy and confidentiality of your transfers. - -This completes the basic setup and usage guide for the Transfer Application. In the next sections, we'll cover how to run this application with local Mock SGX, real SGX on Azure, and how to deploy it on the Neutron testnet. - - - - - -## Local daemon and wallet - -For all **testing** purposes, you can use the wallets we provide in the `docker/wasmd/accounts` folder. - -Once your `wasmd` is running, you can easily copy the wallets from docker to your local daemon `~/.config` folder: - -Here's how you can copy the user wallets from the Docker instance to your local wasmd configuration: - -1. First, ensure that your local wasmd instance is not running. If it is, stop it. - -2. Locate the directory where the Docker instance stores the wallet data. Based on the provided `Dockerfile`, it appears to be `/root` inside the container. - -3. Copy the wallet data from the Docker container to a temporary directory on your local machine: - -```bash -docker cp -r wasmd:/root/.wasmd/keyring-test temp-keyring -``` - -This command copies the `keyring-test` directory from the Docker container to a `temp-keyring` directory in your current local directory. - -4. Copy the wallet data from the temporary directory to your local wasmd configuration directory: - -```bash -cp -r ~/.temp-keyring/* ~/.wasmd/keyring-test/ -``` - -This command copies the contents of the `temp-keyring` directory to your local `~/.wasmd/keyring-test/` directory. - -5. Clean up the temporary directory: - -```bash -rm -rf ./temp-keyring -``` - -6. Verify that the wallets have been copied successfully by running the following command: - -```bash -wasmd keys list --keyring-backend=test -``` - -This should display the list of wallets that were present in the Docker container. - -### Alternative method with docker running -Now, let's add the admin key. We'll use the mnemonic from the admin.txt file in your Docker setup. First, let's view the contents of that file: - -```bash -docker exec wasmd cat /tmp/accounts/admin.txt -``` - -You should see a mnemonic phrase (a series of words) at the end of this output. - -Now, use this mnemonic to add the admin key to your local wasmd installation: -```bash -wasmd keys add admin --recover --keyring-backend=test -``` - -After completing these steps, your local wasmd instance should have the same `admin` wallets as the Docker instance. You can repeat the process for `alice`, `bob` and `charlie`. - - You can now start your local wasmd instance, and it will use the copied wallets. - -Note: Make sure to replace `wasmd` in the `docker cp` command with the actual name of your running Docker container if it differs. - - - - - -## Working with an Azure Sgx - - -Login via `ssh` into your Azure Sgx enabled machine. - -```bash - ssh username@21.6.21.71 -``` - -### Quickstart -Once logged in, install the `cli` with the following command: - -```bash - cargo install --path cli/ -``` - -We now need to build the binaries. - - -### Build the Binaries -To build both the contract binaries, use the build command: - -```bash -quartz --app-dir "apps/transfers/" contract build --contract-manifest "apps/transfers/contracts/Cargo.toml" -``` - - -This command will compile the smart contract to WebAssembly and build the contract binary. - - -### Configuring and Running the Enclave - -The following configuration assumes that the `wasmd` node will be running in the same Azure instance as the enclave. -If you wish to use another enclave provider you have to make sure that `QUARTZ_NODE_URL` is set to the enclave address and port as an argument as in: - -``` -QUARTZ_NODE_URL=87.23.1.3:11090 && quartz --app-dir "apps/transfers/" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' - -``` - -If you wish to use another blockchain you have to make sure that `--node-url` is set to the chain address and port as an option in the `cli` as in: - -``` -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" --node-url "https://92.43.1.4:26657" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' - -``` - - - -To configure and run the enclave, use the following commands: - -```bash - # Configure the enclave -quartz --app-dir "apps/transfers/" enclave build -``` - - -Before starting the enclave, you have to make sure that all relevant contracts (tcbinfo, dcap-verifier) have been instantiated as described below -```bash - # Start the enclave -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" enclave start --fmspc "00606A000000" --tcbinfo-contract "wasm1pk6xe9hr5wgvl5lcd6wp62236t5p600v9g7nfcsjkf6guvta2s5s7353wa" --dcap-verifier-contract "wasm107cq7x4qmm7mepkuxarcazas23037g4q9u72urzyqu7r4saq3l6srcykw2" -``` - -The enclave will start running and wait for commands. - -### Deploying the Contract - -With the enclave running, open a new terminal window to deploy the contract: - -```bash -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' -``` - -Make note of the deployed contract address, as you'll need it for the next step. - - -``` -2024-09-26T15:21:39.036639Z INFO 🆔 Code ID: 66 -2024-09-26T15:21:39.036640Z INFO 📌 Contract Address: wasm1z0az3d9j9s3rjmaukxc58t8hdydu8v0d59wy9p6slce66mwnzjusy76vdq -{"ContractDeploy":{"code_id":66,"contract_addr":"wasm1z0az3d9j9s3rjmaukxc58t8hdydu8v0d59wy9p6slce66mwnzjusy76vdq"}} - -``` - -### Performing the Handshake + activating listener - -To establish communication between the contract and the enclave, perform the handshake: - -```bash -quartz --app-dir "apps/transfers/" handshake --contract -``` - -Replace `` with the address you received when deploying the contract. - -Make note of the handshake generate public key, as you'll need it for the `.env.local` files on the front-end. - -```bash -2024-09-24T11:12:16.961641Z INFO Handshake complete: 02360955ff74750f6ea0b539f41cce89451f591e4c835d0a5406e6effa96dd169d -``` - -Events coming from the contract will be logged following the handshake as they are retrieved by the listener. - -```bash -2024-09-24T11:12:25.156779Z INFO Enclave is listening for requests... -``` - - -## Quartz cosmwasm packages -### Get the FMSPC of the host machine -``` -export QUOTE="/* quote generated during the handshake should work */" -cd utils/print-fmspc/ -cargo run > /dev/null -``` - - - -### Deploying the `tcbinfo` contract -1. Build and store the contract on-chain -``` -cargo run -- contract build --contract-manifest "../cosmwasm/packages/tcbinfo/Cargo.toml" -RES=$(wasmd tx wasm store ./target/wasm32-unknown-unknown/release/tcbinfo.wasm --from alice -y --output json --chain-id "testing" --gas-prices 0.0025ucosm --gas auto --gas-adjustment 1.3) -TX_HASH=$(echo $RES | jq -r '.["txhash"]') -``` -2. Instantiate the contract using Intel's root CA cert. -``` -CERT=$(sed ':a;N;$!ba;s/\n/\\n/g' ../cosmwasm/packages/quartz-tee-ra/data/root_ca.pem) -RES=$(wasmd query tx "$TX_HASH" --output json) -CODE_ID=$(echo $RES | jq -r '.logs[0].events[1].attributes[1].value') -wasmd tx wasm instantiate "$CODE_ID" "{\"root_cert\": \"$CERT\"}" --from "alice" --label "tcbinfo" --chain-id "testing" --gas-prices 0.0025ucosm --gas auto --gas-adjustment 1.3 -y --no-admin --output json -TCB_CONTRACT=$(wasmd query wasm list-contract-by-code "$CODE_ID" --output json | jq -r '.contracts[0]') -``` -3. Get the Tcbinfo for the given FMSPC. -``` -HEADERS=$(wget -q -S -O - https://api.trustedservices.intel.com/sgx/certification/v4/tcb?fmspc=00606A000000 2>&1 >/dev/null) -TCB_INFO=$(wget -q -O - https://api.trustedservices.intel.com/sgx/certification/v4/tcb?fmspc=00606A000000) -export TCB_ISSUER_CERT=$(echo "$HEADERS" | - grep 'TCB-Info-Issuer-Chain:' | - sed 's/.*TCB-Info-Issuer-Chain: //' | - sed 's/%0A/\n/g' | - sed 's/%20/ /g' | - sed 's/-----BEGIN%20CERTIFICATE-----/-----BEGIN CERTIFICATE-----/' | - sed 's/-----END%20CERTIFICATE-----/-----END CERTIFICATE-----/' | - perl -MURI::Escape -ne 'print uri_unescape($_)' | - awk '/-----BEGIN CERTIFICATE-----/{flag=1; print; next} /-----END CERTIFICATE-----/{print; flag=0; exit} flag') - -TCB_ISSUER_CERT=$(echo "$TCB_ISSUER_CERT" | sed ':a;N;$!ba;s/\n/\\n/g') -echo "TCB_INFO:" -echo "$TCB_INFO" -echo -echo "TCB_ISSUER_CERT:" -echo "$TCB_ISSUER_CERT" -``` -4. Add the Tcbinfo for the given FMSPC to the contract (and test it with a query) -``` -wasmd tx wasm execute "$TCB_CONTRACT" "{\"tcb_info\": $(echo "$TCB_INFO" | jq -Rs .), \"certificate\": \"$TCB_ISSUER_CERT\"}" --from admin --chain-id testing --gas auto --gas-adjustment 1.2 -y -wasmd query wasm contract-state smart "$TCB_CONTRACT" '{"get_tcb_info": {"fmspc": "00606A000000"}}' -``` - -### Deploying the `quartz-dcap-verifier` contract -1. Build the contract -``` -cargo run -- contract build --contract-manifest "../cosmwasm/packages/quartz-dcap-verifier/Cargo.toml" -``` -2. Optimize the contract -In order to optimized the contract, you need to install `wasm-opt` v.119 see HOWTO below -``` -wasm-opt -Oz ./target/wasm32-unknown-unknown/release/quartz_dcap_verifier.wasm -o ./target/wasm32-unknown-unknown/release/quartz_dcap_verifier.optimized.wasm -``` -3. Store the optimized contract on-chain -``` -RES=$(wasmd tx wasm store ./target/wasm32-unknown-unknown/release/quartz_dcap_verifier.optimized.wasm --from admin -y --output json --chain-id "testing" --gas-prices 0.0025ucosm --gas auto --gas-adjustment 1.3) -TX_HASH=$(echo $RES | jq -r '.["txhash"]') -RES=$(wasmd query tx "$TX_HASH" --output json) -CODE_ID=$(echo $RES | jq -r '.logs[0].events[1].attributes[1].value') -``` -4. Instantiate the `quartz-dcap-verifier` contract. -``` -wasmd tx wasm instantiate "$CODE_ID" null --from "admin" --label "dcap-verifier" --chain-id "testing" --gas-prices 0.0025ucosm --gas auto --gas-adjustment 1.3 -y --no-admin --output json -DCAP_CONTRACT=$(wasmd query wasm list-contract-by-code "$CODE_ID" --output json | jq -r '.contracts[0]') -``` - -### Quartz setup -``` -quartz --app-dir "../apps/transfers/" - --contract-manifest "../apps/transfers/contracts/Cargo.toml" \ - --unsafe-trust-latest \ - --init-msg '{"denom":"ucosm"}' \ - dev \ - --fmspc "00606A000000" \ - --tcbinfo-contract "$TCB_CONTRACT" \ - --dcap-verifier-contract "$DCAP_CONTRACT" -``` - - - - -#### HOWTO Install `wasm-opt` - -To install `wasm-opt` version 119 on an Azure SGX machine running Ubuntu, follow these steps: - -### 1. **Update and install dependencies:** - -Before installing `wasm-opt`, make sure your system is up-to-date and has the necessary build tools: - -```bash -sudo apt update -sudo apt install -y build-essential cmake git -``` - -### 2. **Download and build `wasm-opt` version 119:** - -The `wasm-opt` tool is part of the [Binaryen](https://github.com/WebAssembly/binaryen) project. To get version 119, you’ll need to clone the specific tag from the Binaryen GitHub repository. - -```bash -git clone https://github.com/WebAssembly/binaryen.git -cd binaryen -git checkout version_119 -``` - -### 3. **Build the project:** - -Next, you'll build Binaryen and the `wasm-opt` tool: - -```bash -cmake . && make -``` - -### 4. **Install `wasm-opt`:** - -Once the build is complete, you can install `wasm-opt` globally on your system: - -```bash -sudo make install -``` - -### 5. **Verify the installation:** - -Finally, confirm that `wasm-opt` version 119 is installed correctly by running: - -```bash -wasm-opt --version -``` - -This should return something like: - -``` -wasm-opt version_119 -``` - -Now, `wasm-opt` version 119 should be properly installed on your Azure SGX machine running Ubuntu. diff --git a/docs/building_apps.md b/docs/building_apps.md index c8173f0c..12699509 100644 --- a/docs/building_apps.md +++ b/docs/building_apps.md @@ -10,7 +10,7 @@ WARNING: Quartz provides utilities for secure communication with TEEs, but it DOES NOT specify a data model for applications. This gives application devs great power and flexibility, but with this power comes great -responsibility. App devs must remain dilligent to ensure their data model does +responsibility. App devs must remain diligent to ensure their data model does not leak private information (or leaks only what they are comfortable with). The Quartz framework intends to provide better tools and patterns for securely @@ -45,7 +45,7 @@ Private requests should be encrypted to authorized TEE keys and queued for execution at some frequency by the TEE. Private state should be managed in such a way that accessing/updating it does -not unecessarily leak private information. +not unnecessarily leak private information. Public responses can be executed directly on-chain (e.g. public balance changes), while private responses can be executed by verifying remote diff --git a/docs/getting_started.md b/docs/getting_started.md index 4d6020ba..e500da20 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -25,13 +25,13 @@ mock SGX: 1. Install dependencies (Rust, wasmd or neutrond) 2. Clone the repository: `git clone ssh://git@github.com/informalsystems/cycles-quartz` -3. Install Quartz CLI: `cargo install --path cli/` -4. Navigate to the example app: `cd apps/transfers` +3. Install Quartz CLI: `cargo install --path crates/cli` +4. Navigate to the example app: `cd examples/transfers` 4. Deploy the example app in one command (enclave, contracts, secure handshake): ```bash quartz --mock-sgx dev \ --unsafe-trust-latest \ - --contract-manifest "apps/transfers/contracts/Cargo.toml" \ + --contract-manifest "examples/transfers/contracts/Cargo.toml" \ --init-msg '{"denom":"ucosm"}' ``` 5. Set up the frontend (see [Frontend](#frontend)) @@ -41,7 +41,7 @@ For more detailed background and instructions, read on. ## Simple Example Quartz includes a simple example we call the `Transfer` application, -located in [/apps/transfers](/apps/transfers), that comes with a Keplr-based +located in [/examples/transfers](/examples/transfers), that comes with a Keplr-based frontend. It's a simple demo app designed to showcase very basic use of the Quartz framework. It allows users to deposit funds into a contract, transfer them privately within the contract's encrypted state (updated by the @@ -53,7 +53,7 @@ Every application has a common structure: 2. **Contracts**: The backend application as a CosmWasm smart contract 3. **Enclave**: Code that executes off-chain and privately in an enclave -Quartz is both a library (`quartz-cw`) for building SGX-aware CosmWasm +Quartz is both a library (`quartz-contract-core`) for building SGX-aware CosmWasm contracts, and a cli tool (`quartz`) for managing the enclave. The library takes care of establishing a secure connection to the enclave (see @@ -63,9 +63,9 @@ it. The quartz tool provides commands for managing the enclave. This guide is primarily about using the `quartz` tool to get the example app setup. For more on building application, see - [Building Apps](/docs/building_apps.md) - conceptual overview -- [quartz-cw](/cosmwasm/quartz-cw) - main library. provides msgs and handlers +- [quartz-contract-core](/cosmwasm/quartz-contract-core) - main library. provides msgs and handlers for the handshake and for verifying attestations -- [transfers contracts](/apps/transfers/contracts): transfer app example itself +- [transfers contracts](/examples/transfers/contracts): transfer app example itself Onwards with the installation and running our example app! @@ -107,7 +107,7 @@ Now clone and build the repo: ```bash git clone ssh://git@github.com/informalsystems/cycles-quartz cd cycles-quartz -cargo install --path cli/ +cargo install --path crates/cli ``` And check that it worked: @@ -169,10 +169,10 @@ First we build and run the enclave code. Quartz provides a `--mock-sgx` flag so we can deploy locally for testing and development purposes without needing access to an SGX core. -We can run everything from within the `apps/transfers` dir in this repo. To run -from elsewhere by specify a path, eg. from the root of the repo with `--app-dir apps/transfers`. +We can run everything from within the `examples/transfers` dir in this repo. To run +from elsewhere by specify a path, eg. from the root of the repo with `--app-dir examples/transfers`. -Now, from `apps/transfers`: +Now, from `examples/transfers`: 1. Build the enclave binary: ```bash @@ -197,7 +197,7 @@ continue. 2. Deploy the contract: ```bash quartz --mock-sgx contract deploy \ - --contract-manifest "apps/transfers/contracts/Cargo.toml" \ + --contract-manifest "examples/transfers/contracts/Cargo.toml" \ --init-msg '{"denom":"ucosm"}' ``` @@ -233,7 +233,7 @@ Now the contract is ready to start processing requests to the enclave. 1. Navigate to the frontend folder: ```bash - cd apps/transfers/frontend + cd examples/transfers/frontend ``` 2. Install dependencies: @@ -291,13 +291,13 @@ to get setup with SGX on Azure, and how to deploy quartz contracts to the Neutron testnet using real remote attestions from SGX cores on Azure. Real verification of SGX on a CosmWasm network requires two additional global contracts -to be deployed: dcap-verify and tcbinfo. The -dcap-verify contract provides the core verification of the SGX attestation -(called DCAP). The tcbinfo contract contains global information about secure +to be deployed: `quartz-dcap-verify` and `quartz-tcbinfo`. The +`quartz-dcap-verify` contract provides the core verification of the SGX attestation +(called DCAP). The `quartz-tcbinfo` contract contains global information about secure versions of SGX processors. Together they allow contracts built with quartz to securely verify remote attestations from SGX enclaves. -We have already predeployed the dcap-verify and tcbinfo contracts on the Neutron +We have already predeployed the `quartz-dcap-verify` and `quartz-tcbinfo` contracts on the Neutron testnet at TODO. To deploy these on your own testnet, see [below](#other-testnets-with-sgx). To begin, you'll need to deploy an SGX-enabled Azure instance and log in via ssh. @@ -309,13 +309,13 @@ Once logged in, clone and install Quartz like before (see TODO: - make this about deploying to neutron. -- do it from apps/transfers to avoid specifying `--app-dir` +- do it from examples/transfers to avoid specifying `--app-dir` To build both the contract binaries, use the build command: ```bash -quartz --app-dir "apps/transfers/" contract build --contract-manifest "apps/transfers/contracts/Cargo.toml" +quartz --app-dir "examples/transfers/" contract build --contract-manifest "examples/transfers/contracts/Cargo.toml" ``` This command will compile the smart contract to WebAssembly and build the contract binary. @@ -323,13 +323,13 @@ The following configuration assumes that the `wasmd` node will be running in the If you wish to use another enclave provider you have to make sure that `QUARTZ_NODE_URL` is set to the enclave address and port as an argument as in: ```bash -QUARTZ_NODE_URL=87.23.1.3:11090 && quartz --app-dir "apps/transfers/" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' +QUARTZ_NODE_URL=87.23.1.3:11090 && quartz --app-dir "examples/transfers/" contract deploy --contract-manifest "examples/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' ``` If you wish to use another blockchain you have to make sure that `--node-url` is set to the chain address and port as an option in the `cli` as in: ```bash -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" --node-url "https://92.43.1.4:26657" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' +QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "examples/transfers/" --node-url "https://92.43.1.4:26657" contract deploy --contract-manifest "examples/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' ``` ### Build and Run the SGX Enclave @@ -338,11 +338,11 @@ First we build the enclave like before: ```bash # Configure the enclave -quartz --app-dir "apps/transfers/" enclave build +quartz --app-dir "examples/transfers/" enclave build ``` Before starting the enclave, we should check that the relevant contracts -(tcbinfo, dcap-verifier) have been instantiated. +(`quartz-tcbinfo`, `quartz-dcap-verifier`) have been instantiated. TODO: how to query to check this? @@ -352,7 +352,7 @@ TODO: use variables for the contract addresses ```bash # Start the enclave -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" enclave start --fmspc "00606A000000" --tcbinfo-contract "wasm1pk6xe9hr5wgvl5lcd6wp62236t5p600v9g7nfcsjkf6guvta2s5s7353wa" --dcap-verifier-contract "wasm107cq7x4qmm7mepkuxarcazas23037g4q9u72urzyqu7r4saq3l6srcykw2" +QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "examples/transfers/" enclave start --fmspc "00606A000000" --tcbinfo-contract "wasm1pk6xe9hr5wgvl5lcd6wp62236t5p600v9g7nfcsjkf6guvta2s5s7353wa" --dcap-verifier-contract "wasm107cq7x4qmm7mepkuxarcazas23037g4q9u72urzyqu7r4saq3l6srcykw2" ``` The enclave will start running and wait for commands. @@ -362,7 +362,7 @@ The enclave will start running and wait for commands. With the enclave running, open a new terminal window to deploy the contract: ```bash -QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "apps/transfers/" contract deploy --contract-manifest "apps/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' +QUARTZ_NODE_URL=127.0.0.1:11090 && quartz --app-dir "examples/transfers/" contract deploy --contract-manifest "examples/transfers/contracts/Cargo.toml" --init-msg '{"denom":"ucosm"}' ``` Make note of the deployed contract address, as you'll need it for the next step. You should see output similar to: @@ -378,7 +378,7 @@ Make note of the deployed contract address, as you'll need it for the next step. To establish communication between the contract and the enclave, perform the handshake: ```bash -quartz --app-dir "apps/transfers/" handshake --contract +quartz --app-dir "examples/transfers/" handshake --contract ``` Replace `` with the address you received when deploying the contract. @@ -397,18 +397,18 @@ Events coming from the contract will be logged following the handshake as they a ## Other Testnets With SGX -To setup on another testnet we need to deploy a tcinfo contract and a -dcap-verifier contract. +To setup on another testnet we need to deploy a `quartz-tcbinfo` contract and a +`quartz-dcap-verifier` contract. ### Get the FMSPC of the host machine ```bash export QUOTE="/* quote generated during the handshake should work */" -cd utils/print-fmspc/ +cd crates/utils/print-fmspc/ cargo run > /dev/null ``` -### Deploying the `tcbinfo` contract +### Deploying the `quartz-tcbinfo` contract 1. Build and store the contract on-chain ```bash @@ -483,8 +483,8 @@ DCAP_CONTRACT=$(wasmd query wasm list-contract-by-code "$CODE_ID" --output json ### Quartz setup ```bash -quartz --app-dir "../apps/transfers/" \ - --contract-manifest "../apps/transfers/contracts/Cargo.toml" \ +quartz --app-dir "../examples/transfers/" \ + --contract-manifest "../examples/transfers/contracts/Cargo.toml" \ --unsafe-trust-latest \ --init-msg '{"denom":"ucosm"}' \ dev \ diff --git a/docs/how_it_works.md b/docs/how_it_works.md index 0c0b4afe..11b7525f 100644 --- a/docs/how_it_works.md +++ b/docs/how_it_works.md @@ -52,7 +52,7 @@ The goal of the handshake is to establish: - specific code is running on the TEE (given by an `mr_enclave`) - a specific TEE is running (given by a `nonce`) -- the TEE has a speciifc decryption key (given by a `pubkey`) +- the TEE has a specific decryption key (given by a `pubkey`) This is done in three corresponding steps: @@ -74,7 +74,7 @@ In SessionPubKey, the TEE verifies a light client proof that the nonce was stored in the contract, generates an encryption key pair, and remote attests to the nonce and pubkey. The smart contract verifies the RA and that the nonce is the same and stores the pubkey. -The TEE is now ready to process requests encrpyted to the pubkey. +The TEE is now ready to process requests encrypted to the pubkey. ## Execution diff --git a/examples/transfers/contracts/Cargo.lock b/examples/transfers/contracts/Cargo.lock index 6eb67b97..5c0b8005 100644 --- a/examples/transfers/contracts/Cargo.lock +++ b/examples/transfers/contracts/Cargo.lock @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "9720086b3357bcb44fce40117d769a4d068c70ecfa190850a980a71755f66fcc" dependencies = [ "base64", "chrono", @@ -1652,9 +1652,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "5f1abbfe725f27678f4663bcacb75a83e829fd464c25d78dd038a3a29e307cec" dependencies = [ "darling", "proc-macro2", diff --git a/examples/transfers/contracts/src/msg.rs b/examples/transfers/contracts/src/msg.rs index 8a5301b7..5f4ffedf 100644 --- a/examples/transfers/contracts/src/msg.rs +++ b/examples/transfers/contracts/src/msg.rs @@ -24,7 +24,7 @@ pub enum QueryMsg { pub enum ExecuteMsg { // quartz initialization Quartz(QuartzExecuteMsg), - + // User msgs // clear text Deposit, diff --git a/examples/transfers/enclave/Cargo.lock b/examples/transfers/enclave/Cargo.lock index a2e34a15..fd26df5a 100644 --- a/examples/transfers/enclave/Cargo.lock +++ b/examples/transfers/enclave/Cargo.lock @@ -268,9 +268,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", @@ -426,6 +426,29 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" +[[package]] +name = "bindgen" +version = "0.66.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.79", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -505,15 +528,30 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-emit" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1582e1c9e755dd6ad6b224dcffb135d199399a4568d454bd89fe515ca8425695" + [[package]] name = "cc" -version = "1.1.23" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -567,11 +605,22 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" dependencies = [ "clap_builder", "clap_derive", @@ -579,9 +628,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" dependencies = [ "anstyle", "clap_lex", @@ -659,20 +708,21 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cosmos-sdk-proto" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d1a42d9ef55bb4e84b48ce29860f55859e52e0088ebdb1371cedd62f2b78cc" +checksum = "8b2f63ab112b8c8e7b8a29c891adc48f43145beb21c0bfbf562957072c1e0beb" dependencies = [ - "prost 0.12.6", - "prost-types 0.12.6", - "tendermint-proto 0.37.0", + "prost", + "prost-types", + "tendermint-proto", + "tonic", ] [[package]] name = "cosmrs" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85efbd5a3487e52ccd77897ef8f97b077a015953b46623fabc939f39d9c501fc" +checksum = "9f21bb63ec6a903510a3d01f44735dd4914724e5eccbe409e6da6833d17c7829" dependencies = [ "cosmos-sdk-proto", "ecdsa", @@ -683,7 +733,7 @@ dependencies = [ "serde_json", "signature", "subtle-encoding", - "tendermint 0.37.0", + "tendermint", "thiserror", ] @@ -894,6 +944,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cw-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "cosmos-sdk-proto", + "cosmrs", + "hex", + "reqwest 0.12.8", + "serde", + "serde_json", + "tendermint", + "tonic", +] + [[package]] name = "cw-multi-test" version = "2.1.1" @@ -907,29 +973,13 @@ dependencies = [ "cw-utils", "derivative", "itertools 0.13.0", - "prost 0.13.3", + "prost", "schemars", "serde", "sha2 0.10.8", "thiserror", ] -[[package]] -name = "cw-proof" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" -dependencies = [ - "clap", - "cosmrs", - "displaydoc", - "ics23", - "prost 0.13.3", - "serde", - "serde_with", - "tendermint 0.38.1", - "tendermint-rpc", -] - [[package]] name = "cw-storage-plus" version = "2.0.0" @@ -1443,6 +1493,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" version = "0.13.0" @@ -1466,7 +1522,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1485,7 +1541,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1533,6 +1589,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "heck" version = "0.5.0" @@ -1578,6 +1640,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -1636,9 +1707,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1782,7 +1853,7 @@ dependencies = [ "blake3", "bytes", "hex", - "prost 0.13.3", + "prost", "ripemd", "sha2 0.10.8", "sha3", @@ -1822,12 +1893,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -1854,15 +1925,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1914,12 +1976,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -2005,7 +2083,8 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "mc-attestation-verifier" version = "0.4.3" -source = "git+https://github.com/informalsystems/attestation#ae86e2804abed218f4fd2fd4aec5e39408898cd8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf39fb1af41156ec868564ab53156d6dd75f1dc8a7a073acdfb217b6140d9e4" dependencies = [ "der", "displaydoc", @@ -2020,11 +2099,25 @@ dependencies = [ "x509-cert", ] +[[package]] +name = "mc-sgx-core-build" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94420a570e76dfc39924b4ec712c2df21a8d77e61ca5ba0857300b1c59889a5d" +dependencies = [ + "bindgen", + "cargo-emit", +] + [[package]] name = "mc-sgx-core-sys-types" version = "0.11.0" -source = "git+https://github.com/informalsystems/sgx#f25807776cbe10901f53d23fca548c9e4f6f284c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c5c33323d0f2855e63efaa538bdd7094104ff79f963734b4122f23302cff581" dependencies = [ + "bindgen", + "cargo-emit", + "mc-sgx-core-build", "serde", "serde_with", ] @@ -2032,7 +2125,8 @@ dependencies = [ [[package]] name = "mc-sgx-core-types" version = "0.11.0" -source = "git+https://github.com/informalsystems/sgx#f25807776cbe10901f53d23fca548c9e4f6f284c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1191b0bb2868ff5bdf7766d3b3e9fa9bb94c23149ae21a82485e6f5f44074106" dependencies = [ "bitflags 2.6.0", "displaydoc", @@ -2049,15 +2143,19 @@ dependencies = [ [[package]] name = "mc-sgx-dcap-sys-types" version = "0.11.0" -source = "git+https://github.com/informalsystems/sgx#f25807776cbe10901f53d23fca548c9e4f6f284c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd3e93a316a5c142de6fb9179970abc04ca4767732b90d118c90d531db47e89" dependencies = [ + "bindgen", + "mc-sgx-core-build", "mc-sgx-core-sys-types", ] [[package]] name = "mc-sgx-dcap-types" version = "0.11.0" -source = "git+https://github.com/informalsystems/sgx#f25807776cbe10901f53d23fca548c9e4f6f284c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42c618d93a3f9561bdc27231fa7965ebe855c8d74f5cd5467da194042e0671a9" dependencies = [ "const-oid", "displaydoc", @@ -2077,15 +2175,8 @@ dependencies = [ [[package]] name = "mc-sgx-util" version = "0.11.0" -source = "git+https://github.com/informalsystems/sgx#f25807776cbe10901f53d23fca548c9e4f6f284c" - -[[package]] -name = "mcmf" -version = "2.0.0" -source = "git+https://github.com/hu55a1n1/flow#cad8f3adb29d3be2177a31db0fa0e5c2a858beb0" -dependencies = [ - "cc", -] +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3c237bec3e33530c4b1a171c8c078ad5d525d5fae177ac9d62e8e454b3fffb7" [[package]] name = "memchr" @@ -2126,20 +2217,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "mtcs" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/mtcs.git#b2093085a53bc39107012fcae9e236edbc4433cb" -dependencies = [ - "displaydoc", - "itertools 0.10.5", - "log", - "mcmf", - "num-traits", - "petgraph 0.6.3", - "serde", -] - [[package]] name = "multimap" version = "0.10.0" @@ -2173,20 +2250,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -2197,15 +2260,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -2221,28 +2275,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2376,6 +2408,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "peg" version = "0.8.4" @@ -2418,16 +2456,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "petgraph" -version = "0.6.3" -source = "git+https://github.com/hu55a1n1/petgraph?branch=min-cost-flow-primal-dual#3a2664a3b9d1e5b71c411a6ed497cf576c1a86ae" -dependencies = [ - "fixedbitset", - "indexmap 1.9.3", - "num", -] - [[package]] name = "petgraph" version = "0.6.5" @@ -2435,7 +2463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.6.0", ] [[package]] @@ -2547,16 +2575,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive 0.12.6", -] - [[package]] name = "prost" version = "0.13.3" @@ -2564,7 +2582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.13.3", + "prost-derive", ] [[package]] @@ -2579,28 +2597,15 @@ dependencies = [ "log", "multimap", "once_cell", - "petgraph 0.6.5", + "petgraph", "prettyplease", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", "regex", "syn 2.0.79", "tempfile", ] -[[package]] -name = "prost-derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" -dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "prost-derive" version = "0.13.3" @@ -2614,22 +2619,13 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "prost-types" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" -dependencies = [ - "prost 0.12.6", -] - [[package]] name = "prost-types" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost 0.13.3", + "prost", ] [[package]] @@ -2643,44 +2639,42 @@ dependencies = [ "color-eyre", "cosmrs", "cosmwasm-std", + "cw-client", "cw-multi-test", "ecies", "futures-util", "hex", "k256", - "prost 0.13.3", + "prost", "quartz-common", + "quartz-tm-prover", "reqwest 0.12.8", "serde", "serde_json", "sha2 0.10.8", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", "tendermint-rpc", "thiserror", - "tm-prover", "tokio", "tonic", "tonic-build", "tracing", "transfers-contract", - "wasmd-client", ] [[package]] name = "quartz-common" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ - "quartz-cw", - "quartz-enclave", + "quartz-contract-core", + "quartz-enclave-core", "quartz-proto", ] [[package]] -name = "quartz-cw" +name = "quartz-contract-core" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ "ciborium", "cosmwasm-schema", @@ -2689,28 +2683,41 @@ dependencies = [ "hex", "k256", "quartz-dcap-verifier-msgs", + "quartz-tcbinfo-msgs", "quartz-tee-ra", "serde", "serde_json", "serde_with", "sha2 0.10.8", - "tcbinfo-msgs", "thiserror", ] +[[package]] +name = "quartz-cw-proof" +version = "0.1.0" +dependencies = [ + "clap", + "cosmrs", + "displaydoc", + "ics23", + "prost", + "serde", + "serde_with", + "tendermint", + "tendermint-rpc", +] + [[package]] name = "quartz-dcap-verifier-msgs" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", ] [[package]] -name = "quartz-enclave" +name = "quartz-enclave-core" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ "anyhow", "async-trait", @@ -2718,26 +2725,25 @@ dependencies = [ "color-eyre", "cosmrs", "cosmwasm-std", - "cw-proof", "ecies", "futures-util", "hex", "k256", "mc-sgx-dcap-sys-types", - "mtcs", - "quartz-cw", + "quartz-contract-core", + "quartz-cw-proof", "quartz-proto", "quartz-tee-ra", + "quartz-tm-stateless-verifier", "rand", "reqwest 0.12.8", "serde", "serde_json", "sha2 0.10.8", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", "tendermint-rpc", "thiserror", - "tm-stateless-verifier", "tokio", "tonic", "tower 0.5.1", @@ -2747,17 +2753,22 @@ dependencies = [ [[package]] name = "quartz-proto" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ - "prost 0.13.3", + "prost", "tonic", "tonic-build", ] +[[package]] +name = "quartz-tcbinfo-msgs" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", +] + [[package]] name = "quartz-tee-ra" version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2774,6 +2785,35 @@ dependencies = [ "x509-parser", ] +[[package]] +name = "quartz-tm-prover" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", + "cosmrs", + "futures", + "quartz-cw-proof", + "serde", + "serde_json", + "tendermint", + "tendermint-light-client", + "tendermint-light-client-detector", + "tendermint-rpc", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "quartz-tm-stateless-verifier" +version = "0.1.0" +dependencies = [ + "displaydoc", + "tendermint", + "tendermint-light-client", +] + [[package]] name = "quinn" version = "0.11.5" @@ -2784,7 +2824,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.0.0", "rustls 0.23.13", "socket2", "thiserror", @@ -2801,7 +2841,7 @@ dependencies = [ "bytes", "rand", "ring", - "rustc-hash", + "rustc-hash 2.0.0", "rustls 0.23.13", "slab", "thiserror", @@ -3064,6 +3104,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.0.0" @@ -3429,9 +3475,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "9720086b3357bcb44fce40117d769a4d068c70ecfa190850a980a71755f66fcc" dependencies = [ "base64 0.22.1", "chrono", @@ -3445,9 +3491,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "5f1abbfe725f27678f4663bcacb75a83e829fd464c25d78dd038a3a29e307cec" dependencies = [ "darling", "proc-macro2", @@ -3689,14 +3735,6 @@ dependencies = [ "libc", ] -[[package]] -name = "tcbinfo-msgs" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" -dependencies = [ - "cosmwasm-schema", -] - [[package]] name = "tempfile" version = "3.13.0" @@ -3710,37 +3748,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "tendermint" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954496fbc9716eb4446cdd6d00c071a3e2f22578d62aa03b40c7e5b4fda3ed42" -dependencies = [ - "bytes", - "digest 0.10.7", - "ed25519", - "ed25519-consensus", - "flex-error", - "futures", - "k256", - "num-traits", - "once_cell", - "prost 0.12.6", - "prost-types 0.12.6", - "ripemd", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.10.8", - "signature", - "subtle", - "subtle-encoding", - "tendermint-proto 0.37.0", - "time", - "zeroize", -] - [[package]] name = "tendermint" version = "0.38.1" @@ -3753,10 +3760,12 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", + "k256", "num-traits", "once_cell", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", + "ripemd", "serde", "serde_bytes", "serde_json", @@ -3765,7 +3774,7 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.38.1", + "tendermint-proto", "time", "zeroize", ] @@ -3779,7 +3788,7 @@ dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.38.1", + "tendermint", "toml", "url", ] @@ -3801,7 +3810,7 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client-verifier", "tendermint-rpc", "time", @@ -3824,9 +3833,9 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint 0.38.1", + "tendermint", "tendermint-light-client", - "tendermint-proto 0.38.1", + "tendermint-proto", "tendermint-rpc", "time", "tracing", @@ -3841,23 +3850,7 @@ dependencies = [ "derive_more 0.99.18", "flex-error", "serde", - "tendermint 0.38.1", - "time", -] - -[[package]] -name = "tendermint-proto" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" -dependencies = [ - "bytes", - "flex-error", - "prost 0.12.6", - "prost-types 0.12.6", - "serde", - "serde_bytes", - "subtle-encoding", + "tendermint", "time", ] @@ -3869,8 +3862,8 @@ checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" dependencies = [ "bytes", "flex-error", - "prost 0.13.3", - "prost-types 0.13.3", + "prost", + "prost-types", "serde", "serde_bytes", "subtle-encoding", @@ -3899,9 +3892,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.38.1", + "tendermint", "tendermint-config", - "tendermint-proto 0.38.1", + "tendermint-proto", "thiserror", "time", "tokio", @@ -3987,42 +3980,11 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tm-prover" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" -dependencies = [ - "clap", - "color-eyre", - "cosmrs", - "cw-proof", - "futures", - "serde", - "serde_json", - "tendermint 0.38.1", - "tendermint-light-client", - "tendermint-light-client-detector", - "tendermint-rpc", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tm-stateless-verifier" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" -dependencies = [ - "displaydoc", - "tendermint 0.38.1", - "tendermint-light-client", -] - [[package]] name = "tokio" -version = "1.39.2" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -4138,7 +4100,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -4147,9 +4109,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", @@ -4165,7 +4127,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.3", + "prost", "socket2", "tokio", "tokio-stream", @@ -4177,13 +4139,14 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568392c5a2bd0020723e3f387891176aabafe36fd9fcd074ad309dfa0c8eb964" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", "syn 2.0.79", ] @@ -4504,19 +4467,6 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" -[[package]] -name = "wasmd-client" -version = "0.1.0" -source = "git+ssh://git@github.com/informalsystems/cycles-quartz.git#e853c2ed1d7b9a720c1c39e822f701e9f71f13bb" -dependencies = [ - "anyhow", - "cosmrs", - "hex", - "reqwest 0.12.8", - "serde", - "serde_json", -] - [[package]] name = "web-sys" version = "0.3.70" @@ -4536,6 +4486,18 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi-util" version = "0.1.9" diff --git a/examples/transfers/enclave/Cargo.toml b/examples/transfers/enclave/Cargo.toml index 9ff86e77..c4f52e89 100644 --- a/examples/transfers/enclave/Cargo.toml +++ b/examples/transfers/enclave/Cargo.toml @@ -52,7 +52,7 @@ tracing = "0.1.39" futures-util = "0.3.30" # cosmos -cosmrs = { version = "0.17.0", default-features = false } +cosmrs = { version = "0.18.0", default-features = false } cosmwasm-std = { version = "2.1.1", default-features = false, features = [ "std", ] } diff --git a/examples/transfers/enclave/build.rs b/examples/transfers/enclave/build.rs index 0e6223c5..3977285c 100644 --- a/examples/transfers/enclave/build.rs +++ b/examples/transfers/enclave/build.rs @@ -1,6 +1,6 @@ fn main() -> Result<(), Box> { tonic_build::configure() .out_dir("src/prost") - .compile(&["proto/transfers.proto"], &["proto"])?; + .compile_protos(&["proto/transfers.proto"], &["proto"])?; Ok(()) } diff --git a/examples/transfers/enclave/quartz.manifest.template b/examples/transfers/enclave/quartz.manifest.template index 75799eff..1648be78 100644 --- a/examples/transfers/enclave/quartz.manifest.template +++ b/examples/transfers/enclave/quartz.manifest.template @@ -5,7 +5,7 @@ libos.entrypoint = "{{ quartz_dir }}/target/release/quartz-app-transfers-enclave loader.log_level = "{{ log_level }}" -loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}" +loader.env.LD_LIBRARY_PATH = "/lib:/usr/local/lib:{{ arch_libdir }}:/usr{{ arch_libdir }}" loader.env.HOME = "{{ home }}" loader.env.INSIDE_SGX = "1" loader.env.TLS = { passthrough = true } @@ -19,13 +19,17 @@ loader.env.RA_TLS_ISV_PROD_ID = { passthrough = true } loader.env.RA_TLS_EPID_API_KEY = { passthrough = true } loader.env.MYAPP_DATA = { passthrough = true } loader.env.QUARTZ_PORT = { passthrough = true } +loader.env.SSL_CERT_FILE = { passthrough = true } +loader.insecure__use_host_env = true loader.argv = ["quartz-app-transfers-enclave", - "--chain-id", "testing", + "--chain-id", "{{ chain_id }}", "--fmspc", "{{ fmspc }}", "--tcbinfo-contract", "{{ tcbinfo_contract }}", "--dcap-verifier-contract", "{{ dcap_verifier_contract }}", "--node-url", "{{ node_url }}", + "--ws-url", "{{ ws_url }}", + "--grpc-url", "{{ grpc_url }}", "--rpc-addr", "0.0.0.0:11090", "--trusted-height", "{{ trusted_height }}", "--trusted-hash", "{{ trusted_hash }}"] @@ -35,11 +39,14 @@ fs.mounts = [ { uri = "file:{{ arch_libdir }}", path = "{{ arch_libdir }}" }, { uri = "file:/usr/{{ arch_libdir }}", path = "/usr{{ arch_libdir }}" }, { uri = "file:{{ quartz_dir }}", path = "{{ quartz_dir }}" }, + { uri = "file:{{ quartz_dir }}/../../crates/utils/cw-client/data/admin.sk", path = "/admin.sk" }, + { uri = "file:/etc/ssl/certs/ca-certificates.crt", path = "/etc/ssl/certs/ca-certificates.crt" }, + { uri = "file:/usr/lib/ssl/cert.pem", path = "/usr/lib/ssl/cert.pem" }, ] # sgx.debug = true sgx.enclave_size = "512M" -sgx.max_threads = 4 +sgx.max_threads = 16 sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.remote_attestation = "{{ ra_type }}" @@ -52,12 +59,24 @@ sgx.trusted_files = [ "file:{{ gramine.runtimedir() }}/", "file:{{ arch_libdir }}/", "file:/usr/{{ arch_libdir }}/", + "file:/etc/ssl/certs/ca-certificates.crt", + "file:{{ quartz_dir }}/../../crates/utils/cw-client/data/admin.sk", ] sgx.allowed_files = [ - "file:{{ quartz_dir }}/exchange.sk", - "file:{{ quartz_dir }}/request.json", + "file:admin.sk", + "file:/etc/nsswitch.conf", + "file:/etc/host.conf", + "file:/etc/ethers", + "file:/etc/hosts", + "file:/etc/group", + "file:/etc/passwd", + "file:/etc/gai.conf", + "file:/etc/ssl/certs/ca-certificates.crt", + "file:/usr/lib/ssl/cert.pem", + "file:/etc/sgx_default_qcnl.conf", ] sys.insecure__allow_eventfd = true sys.enable_sigterm_injection = true +sys.enable_extra_runtime_domain_names_conf = true diff --git a/examples/transfers/enclave/src/cli.rs b/examples/transfers/enclave/src/cli.rs index 307038b2..dce99abe 100644 --- a/examples/transfers/enclave/src/cli.rs +++ b/examples/transfers/enclave/src/cli.rs @@ -1,9 +1,10 @@ -use std::{env, net::SocketAddr}; +use std::{env, net::SocketAddr, path::PathBuf}; use clap::Parser; use color_eyre::eyre::{eyre, Result}; use cosmrs::AccountId; use quartz_common::enclave::types::Fmspc; +use reqwest::Url; use tendermint::Hash; use tendermint_light_client::types::{Height, TrustThreshold}; @@ -64,11 +65,20 @@ pub struct Cli { #[clap(long, default_value = "5")] pub max_block_lag: u64, - #[clap(long, default_value = "127.0.0.1:11090")] - pub node_url: String, + #[clap(long, default_value = "http://127.0.0.1:26657")] + pub node_url: Url, + + #[clap(long, default_value = "ws://127.0.0.1/websocket")] + pub ws_url: Url, + + #[clap(long, default_value = "http://127.0.0.1:9090")] + pub grpc_url: Url, #[clap(long, default_value = "admin")] pub tx_sender: String, + + #[clap(long, default_value = "admin.sk")] + pub sk_file: PathBuf, } fn default_rpc_addr() -> SocketAddr { diff --git a/examples/transfers/enclave/src/main.rs b/examples/transfers/enclave/src/main.rs index ccc4f54e..da4b5ed2 100644 --- a/examples/transfers/enclave/src/main.rs +++ b/examples/transfers/enclave/src/main.rs @@ -32,8 +32,9 @@ use quartz_common::{ server::{QuartzServer, WsListenerConfig}, }, }; -use transfers_server::{TransfersOp, TransfersService}; use tokio::sync::mpsc; +use transfers_server::{TransfersOp, TransfersService}; + use crate::wslistener::WsListener; #[tokio::main(flavor = "current_thread")] @@ -73,10 +74,13 @@ async fn main() -> Result<(), Box> { let ws_config = WsListenerConfig { node_url: args.node_url, + ws_url: args.ws_url, + grpc_url: args.grpc_url, tx_sender: args.tx_sender, trusted_hash: args.trusted_hash, trusted_height: args.trusted_height, chain_id: args.chain_id, + sk_file: args.sk_file, }; let sk = Arc::new(Mutex::new(None)); diff --git a/examples/transfers/enclave/src/prost/transfers.rs b/examples/transfers/enclave/src/prost/transfers.rs index f978a7c8..3dd4782c 100644 --- a/examples/transfers/enclave/src/prost/transfers.rs +++ b/examples/transfers/enclave/src/prost/transfers.rs @@ -21,7 +21,13 @@ pub struct QueryResponse { } /// Generated client implementations. pub mod settlement_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] use tonic::codegen::*; use tonic::codegen::http::Uri; #[derive(Debug, Clone)] @@ -43,8 +49,8 @@ pub mod settlement_client { where T: tonic::client::GrpcService, T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); @@ -69,7 +75,7 @@ pub mod settlement_client { >, , - >>::Error: Into + Send + Sync, + >>::Error: Into + std::marker::Send + std::marker::Sync, { SettlementClient::new(InterceptedService::new(inner, interceptor)) } @@ -112,8 +118,7 @@ pub mod settlement_client { .ready() .await .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, + tonic::Status::unknown( format!("Service was not ready: {}", e.into()), ) })?; @@ -131,8 +136,7 @@ pub mod settlement_client { .ready() .await .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, + tonic::Status::unknown( format!("Service was not ready: {}", e.into()), ) })?; @@ -149,11 +153,17 @@ pub mod settlement_client { } /// Generated server implementations. pub mod settlement_server { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with SettlementServer. #[async_trait] - pub trait Settlement: Send + Sync + 'static { + pub trait Settlement: std::marker::Send + std::marker::Sync + 'static { async fn run( &self, request: tonic::Request, @@ -164,14 +174,14 @@ pub mod settlement_server { ) -> std::result::Result, tonic::Status>; } #[derive(Debug)] - pub struct SettlementServer { + pub struct SettlementServer { inner: Arc, accept_compression_encodings: EnabledCompressionEncodings, send_compression_encodings: EnabledCompressionEncodings, max_decoding_message_size: Option, max_encoding_message_size: Option, } - impl SettlementServer { + impl SettlementServer { pub fn new(inner: T) -> Self { Self::from_arc(Arc::new(inner)) } @@ -225,8 +235,8 @@ pub mod settlement_server { impl tonic::codegen::Service> for SettlementServer where T: Settlement, - B: Body + Send + 'static, - B::Error: Into + Send + 'static, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, { type Response = http::Response; type Error = std::convert::Infallible; @@ -327,23 +337,25 @@ pub mod settlement_server { } _ => { Box::pin(async move { - Ok( - http::Response::builder() - .status(200) - .header("grpc-status", tonic::Code::Unimplemented as i32) - .header( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ) - .body(empty_body()) - .unwrap(), - ) + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) }) } } } } - impl Clone for SettlementServer { + impl Clone for SettlementServer { fn clone(&self) -> Self { let inner = self.inner.clone(); Self { @@ -355,7 +367,9 @@ pub mod settlement_server { } } } - impl tonic::server::NamedService for SettlementServer { - const NAME: &'static str = "transfers.Settlement"; + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "transfers.Settlement"; + impl tonic::server::NamedService for SettlementServer { + const NAME: &'static str = SERVICE_NAME; } } diff --git a/examples/transfers/enclave/src/transfers_server.rs b/examples/transfers/enclave/src/transfers_server.rs index 47a944ef..fd2748b1 100644 --- a/examples/transfers/enclave/src/transfers_server.rs +++ b/examples/transfers/enclave/src/transfers_server.rs @@ -19,9 +19,9 @@ use quartz_common::{ }; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; +use tokio::sync::mpsc::Sender; use tonic::{Request, Response, Result as TonicResult, Status}; use transfers_contract::msg::execute::{ClearTextTransferRequestMsg, Request as TransfersRequest}; -use tokio::sync::mpsc::Sender; use crate::{ proto::{ @@ -113,7 +113,7 @@ pub enum TransfersOpEvent { pub struct TransfersOp { pub client: TransfersService, pub event: TransfersOpEvent, - pub config: WsListenerConfig + pub config: WsListenerConfig, } #[derive(Clone, Debug)] @@ -121,14 +121,19 @@ pub struct TransfersService { config: Config, sk: Arc>>, attestor: A, - pub queue_producer: Sender> + pub queue_producer: Sender>, } impl TransfersService where A: Attestor, { - pub fn new(config: Config, sk: Arc>>, attestor: A, queue_producer: Sender>) -> Self { + pub fn new( + config: Config, + sk: Arc>>, + attestor: A, + queue_producer: Sender>, + ) -> Self { Self { config, sk, diff --git a/examples/transfers/enclave/src/wslistener.rs b/examples/transfers/enclave/src/wslistener.rs index ed08b2cd..78d097ee 100644 --- a/examples/transfers/enclave/src/wslistener.rs +++ b/examples/transfers/enclave/src/wslistener.rs @@ -1,23 +1,21 @@ -//TODO: get rid of this use std::{collections::BTreeMap, str::FromStr}; use anyhow::{anyhow, Error, Result}; use cosmrs::{tendermint::chain::Id as ChainId, AccountId}; use cosmwasm_std::{Addr, HexBinary}; +use cw_client::{CwClient, GrpcClient}; use futures_util::StreamExt; use quartz_common::{ - contract::msg::execute::attested::{ - MockAttestation, RawAttested, RawAttestedMsgSansHandler, RawMockAttestation, - }, + contract::msg::execute::attested::{RawAttested, RawAttestedMsgSansHandler}, enclave::{ attestor::Attestor, server::{WebSocketHandler, WsListenerConfig}, }, }; -use reqwest::Url; +use quartz_tm_prover::{config::Config as TmProverConfig, prover::prove}; +use serde::Deserialize; use serde_json::json; use tendermint_rpc::{event::Event, query::EventType, SubscriptionClient, WebSocketClient}; -use quartz_tm_prover::{config::Config as TmProverConfig, prover::prove}; use tonic::Request; use tracing::info; use transfers_contract::msg::{ @@ -25,13 +23,11 @@ use transfers_contract::msg::{ AttestedMsg, ExecuteMsg, QueryMsg::{GetRequests, GetState}, }; -use cw_client::{CliWasmdClient, QueryResult, WasmdClient}; use crate::{ proto::{settlement_server::Settlement, QueryRequest, UpdateRequest}, transfers_server::{ - QueryRequestMessage, TransfersOp, TransfersOpEvent, - TransfersService, UpdateRequestMessage, + QueryRequestMessage, TransfersOp, TransfersOpEvent, TransfersService, UpdateRequestMessage, }, }; @@ -46,23 +42,26 @@ impl TryFrom for TransfersOpEvent { fn try_from(event: Event) -> Result { if let Some(events) = &event.events { - for (key, _) in events { + for key in events.keys() { match key.as_str() { k if k.starts_with("wasm-query_balance") => { let (contract_address, ephemeral_pubkey, sender) = - extract_event_info(TransfersOpEventTypes::Query, &events) - .map_err(|_| anyhow!("Failed to extract event info from query event"))?; + extract_event_info(TransfersOpEventTypes::Query, events).map_err( + |_| anyhow!("Failed to extract event info from query event"), + )?; return Ok(TransfersOpEvent::Query { contract_address, - ephemeral_pubkey: ephemeral_pubkey.ok_or(anyhow!("Missing ephemeral_pubkey"))?, + ephemeral_pubkey: ephemeral_pubkey + .ok_or(anyhow!("Missing ephemeral_pubkey"))?, sender: sender.ok_or(anyhow!("Missing sender"))?, }); } k if k.starts_with("wasm-transfer.action") => { let (contract_address, _, _) = - extract_event_info(TransfersOpEventTypes::Transfer, &events) - .map_err(|_| anyhow!("Failed to extract event info from transfer event"))?; + extract_event_info(TransfersOpEventTypes::Transfer, events).map_err( + |_| anyhow!("Failed to extract event info from transfer event"), + )?; return Ok(TransfersOpEvent::Transfer { contract_address }); } @@ -99,7 +98,11 @@ pub trait WsListener: Send + Sync + 'static { } #[async_trait::async_trait] -impl WsListener for TransfersService { +impl WsListener for TransfersService +where + A: Attestor, + A::RawAttestation: for<'de> Deserialize<'de> + Send, +{ async fn process(&self, event: TransfersOpEvent, config: WsListenerConfig) -> Result<()> { match event { TransfersOpEvent::Transfer { contract_address } => { @@ -116,9 +119,8 @@ impl WsListener for TransfersService { } } - let wsurl = format!("ws://{}/websocket", config.node_url); // Wait some blocks to make sure transaction was confirmed - two_block_waitoor(&wsurl).await?; + two_block_waitoor(config.ws_url.as_str()).await?; Ok(()) } @@ -141,58 +143,57 @@ fn extract_event_info( .map_err(|e| anyhow!("Failed to parse contract address: {}", e))?; // Set info for specific events - match op_event { - TransfersOpEventTypes::Query => { - sender = events - .get("message.sender") - .ok_or_else(|| anyhow!("Missing message.sender in events"))? - .first() - .cloned(); - - ephemeral_pubkey = events - .get("wasm-query_balance.emphemeral_pubkey") - .ok_or_else(|| anyhow!("Missing wasm-query_balance.emphemeral_pubkey in events"))? - .first() - .cloned(); - } - _ => {} + if let TransfersOpEventTypes::Query = op_event { + sender = events + .get("message.sender") + .ok_or_else(|| anyhow!("Missing message.sender in events"))? + .first() + .cloned(); + + ephemeral_pubkey = events + .get("wasm-query_balance.emphemeral_pubkey") + .ok_or_else(|| anyhow!("Missing wasm-query_balance.emphemeral_pubkey in events"))? + .first() + .cloned(); } Ok((contract_address, ephemeral_pubkey, sender)) } -async fn transfer_handler( +async fn transfer_handler( client: &TransfersService, contract: &AccountId, ws_config: &WsListenerConfig, -) -> Result<()> { +) -> Result<()> +where + A: Attestor, + A::RawAttestation: for<'de> Deserialize<'de>, +{ let chain_id = &ChainId::from_str(&ws_config.chain_id)?; - let httpurl = Url::parse(&format!("http://{}", ws_config.node_url))?; - let cw_client = CliWasmdClient::new(httpurl.clone()); + let cw_client = GrpcClient::new(ws_config.sk_file.clone(), ws_config.grpc_url.clone()); // Query contract state - let resp: QueryResult> = cw_client + let requests: Vec = cw_client .query_smart(contract, json!(GetRequests {})) + .await .map_err(|e| anyhow!("Problem querying contract state: {}", e))?; - let requests = resp.data; - let resp: QueryResult = cw_client + let state: HexBinary = cw_client .query_smart(contract, json!(GetState {})) + .await .map_err(|e| anyhow!("Problem querying contract state: {}", e))?; - let state = resp.data; // Request body contents let update_contents = UpdateRequestMessage { state, requests }; // Wait 2 blocks info!("Waiting 2 blocks for light client proof"); - let wsurl = format!("ws://{}/websocket", ws_config.node_url); - two_block_waitoor(&wsurl).await?; + two_block_waitoor(ws_config.ws_url.as_str()).await?; // Call tm prover with trusted hash and height let prover_config = TmProverConfig { - primary: httpurl.as_str().parse()?, - witnesses: httpurl.as_str().parse()?, + primary: ws_config.node_url.as_str().parse()?, + witnesses: ws_config.node_url.as_str().parse()?, trusted_height: ws_config.trusted_height, trusted_hash: ws_config.trusted_hash, verbose: "1".parse()?, // TODO: both tm-prover and cli define the same Verbosity struct. Need to define this once and import @@ -230,53 +231,52 @@ async fn transfer_handler( .into_inner(); // Extract json from enclave response - let attested: RawAttested = + let attested: RawAttested = serde_json::from_str(&update_response.message) .map_err(|e| anyhow!("Error deserializing UpdateMsg from enclave: {}", e))?; // Build on-chain response // TODO add non-mock support - let transfer_msg = ExecuteMsg::Update::(AttestedMsg { + let transfer_msg = ExecuteMsg::Update(AttestedMsg { msg: RawAttestedMsgSansHandler(attested.msg), - attestation: MockAttestation( - attested - .attestation - .as_slice() - .try_into() - .map_err(|_| anyhow!("slice with incorrect length"))?, - ) - .into(), + attestation: attested.attestation, }); // Post response to chain - let output = cw_client.tx_execute( - contract, - chain_id, - 2000000, - &ws_config.tx_sender, - json!(transfer_msg), - )?; + let output = cw_client + .tx_execute( + contract, + chain_id, + 2000000, + &ws_config.tx_sender, + json!(transfer_msg), + "11000untrn", + ) + .await?; println!("Output TX: {}", output); Ok(()) } -async fn query_handler( +async fn query_handler( client: &TransfersService, contract: &AccountId, - msg_sender: &String, - pubkey: &String, + msg_sender: &str, + pubkey: &str, ws_config: &WsListenerConfig, -) -> Result<()> { +) -> Result<()> +where + A: Attestor, + A::RawAttestation: for<'de> Deserialize<'de>, +{ let chain_id = &ChainId::from_str(&ws_config.chain_id)?; - let httpurl = Url::parse(&format!("http://{}", ws_config.node_url))?; - let cw_client = CliWasmdClient::new(httpurl); + let cw_client = GrpcClient::new(ws_config.sk_file.clone(), ws_config.grpc_url.clone()); // Query contract state - let resp: QueryResult = cw_client + let state: HexBinary = cw_client .query_smart(contract, json!(GetState {})) + .await .map_err(|e| anyhow!("Problem querying contract state: {}", e))?; - let state = resp.data; // Build request let update_contents = QueryRequestMessage { @@ -297,32 +297,28 @@ async fn query_handler( .into_inner(); // Extract json from the enclave response - let attested: RawAttested = + let attested: RawAttested = serde_json::from_str(&query_response.message) .map_err(|e| anyhow!("Error deserializing QueryResponseMsg from enclave: {}", e))?; // Build on-chain response // TODO add non-mock support - let query_msg = ExecuteMsg::QueryResponse::(AttestedMsg { + let query_msg = ExecuteMsg::QueryResponse(AttestedMsg { msg: RawAttestedMsgSansHandler(attested.msg), - attestation: MockAttestation( - attested - .attestation - .as_slice() - .try_into() - .map_err(|_| anyhow!("slice with incorrect length"))?, - ) - .into(), + attestation: attested.attestation, }); // Post response to chain - let output = cw_client.tx_execute( - contract, - chain_id, - 2000000, - &ws_config.tx_sender, - json!(query_msg), - )?; + let output = cw_client + .tx_execute( + contract, + chain_id, + 2000000, + &ws_config.tx_sender, + json!(query_msg), + "11000untrn", + ) + .await?; println!("Output TX: {}", output); Ok(()) diff --git a/examples/transfers/frontend/src/config/chain.ts b/examples/transfers/frontend/src/config/chain.ts index 6a519e50..ad68434a 100644 --- a/examples/transfers/frontend/src/config/chain.ts +++ b/examples/transfers/frontend/src/config/chain.ts @@ -2,6 +2,7 @@ import { ChainInfo } from '@keplr-wallet/types' import { localWasm } from './chains/localWasm' import { localNeutron } from './chains/localNeutron' +import { testnetNeutron } from './chains/testnetNeutron' const supportedChains: Record = { doWasm: { @@ -12,6 +13,7 @@ const supportedChains: Record = { }, localNeutron, localWasm, + testnetNeutron, } const chain = supportedChains[process.env.NEXT_PUBLIC_TARGET_CHAIN!] diff --git a/examples/transfers/frontend/src/config/chains/localNeutron.ts b/examples/transfers/frontend/src/config/chains/localNeutron.ts index 7c4a13aa..212f92d1 100644 --- a/examples/transfers/frontend/src/config/chains/localNeutron.ts +++ b/examples/transfers/frontend/src/config/chains/localNeutron.ts @@ -2,7 +2,7 @@ import { ChainInfo } from '@keplr-wallet/types' // Neutron local chain definition export const localNeutron: ChainInfo = { - chainId: 'testing', + chainId: 'test-1', chainName: 'Local Neutron Testchain', rpc: 'http://localhost:26657', rest: 'http://localhost:1317', diff --git a/examples/transfers/frontend/src/config/chains/testnetNeutron.ts b/examples/transfers/frontend/src/config/chains/testnetNeutron.ts new file mode 100644 index 00000000..5478a9e3 --- /dev/null +++ b/examples/transfers/frontend/src/config/chains/testnetNeutron.ts @@ -0,0 +1,43 @@ +import { ChainInfo } from '@keplr-wallet/types' + +// Neutron testnet chain definition +export const testnetNeutron: ChainInfo = { + chainId: 'pion-1', + chainName: 'Neutron Testnet', + rpc: 'https://rpc-falcron.pion-1.ntrn.tech', + rest: 'https://rest-falcron.pion-1.ntrn.tech', + stakeCurrency: { + coinDenom: 'NEUTRON', + coinMinimalDenom: 'untrn', + coinDecimals: 6, + coinGeckoId: 'neutron', + }, + bip44: { + coinType: 118, + }, + bech32Config: { + bech32PrefixAccAddr: 'neutron', + bech32PrefixAccPub: 'neutron' + 'pub', + bech32PrefixValAddr: 'neutron' + 'valoper', + bech32PrefixValPub: 'neutron' + 'valoperpub', + bech32PrefixConsAddr: 'neutron' + 'valcons', + bech32PrefixConsPub: 'neutron' + 'valconspub', + }, + currencies: [ + { + coinDenom: 'NTRN', + coinMinimalDenom: 'untrn', + coinDecimals: 6, + coinGeckoId: 'neutron', + }, + ], + feeCurrencies: [ + { + coinDenom: 'NTRN', + coinMinimalDenom: 'untrn', + coinDecimals: 6, + coinGeckoId: 'neutron', + gasPriceStep: { low: 0.001, average: 0.0025, high: 0.004 }, + }, + ], +} diff --git a/examples/transfers/quartz.neutron_pion-1.toml b/examples/transfers/quartz.neutron_pion-1.toml new file mode 100644 index 00000000..6c869214 --- /dev/null +++ b/examples/transfers/quartz.neutron_pion-1.toml @@ -0,0 +1,14 @@ +mock_sgx = false +tx_sender = "val1" +chain_id = "pion-1" +node_url = "https://rpc-falcron.pion-1.ntrn.tech" +ws_url = "wss://rpc-falcron.pion-1.ntrn.tech/websocket" +grpc_url = "https://grpc-falcron.pion-1.ntrn.tech:80" +# node_url = "https://neutron-testnet-rpc.polkachu.com" +# ws_url = "wss://neutron-testnet-rpc.polkachu.com/websocket" +# grpc_url = "https://grpc.baryon.remedy.tm.p2p.org:443" +enclave_rpc_addr = "https://127.0.0.1" +enclave_rpc_port = 11091 +trusted_hash = "" +trusted_height = 0 +release = true diff --git a/examples/transfers/quartz.toml b/examples/transfers/quartz.toml index 0371cee4..d59e9e00 100644 --- a/examples/transfers/quartz.toml +++ b/examples/transfers/quartz.toml @@ -1,7 +1,9 @@ mock_sgx = true tx_sender = "admin" chain_id = "testing" -node_url = "127.0.0.1:26657" +node_url = "http://127.0.0.1:26657" +ws_url = "ws://127.0.0.1/wesocket" +grpc_url = "http://127.0.0.1:9090" enclave_rpc_addr = "http://127.0.0.1" enclave_rpc_port = 11090 trusted_hash = ""