Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neutron client in pure rust #234

Merged
merged 43 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fbdf043
Extract wasmd_cli mod
hu55a1n1 Oct 1, 2024
0175517
Rename WasmdClient trait to CwClient
hu55a1n1 Oct 1, 2024
13f1452
Make some trait methods async
hu55a1n1 Oct 1, 2024
441ebb1
Fix cosmos deps to align proto defs
hu55a1n1 Oct 1, 2024
d05d675
Impl NeutronClient
hu55a1n1 Oct 1, 2024
b805da6
Update usages of CwClient to use new async methods
hu55a1n1 Oct 2, 2024
2e66e19
Merge branch 'main' into hu55a1n1/wasmd-client-rs
hu55a1n1 Oct 2, 2024
49c0868
Use NeutrondClient in enclave
hu55a1n1 Oct 2, 2024
b1618d1
Add test for neutrond client impl
hu55a1n1 Oct 2, 2024
cc9a3e0
Add query test for neutrond client impl
hu55a1n1 Oct 2, 2024
144e4df
Add execute test for neutrond client impl
hu55a1n1 Oct 2, 2024
7962e27
cargo fmt
hu55a1n1 Oct 2, 2024
335ae2a
Improve error handling
hu55a1n1 Oct 2, 2024
eb7d5d9
Pass sk-file to enclave
hu55a1n1 Oct 2, 2024
00e89db
cargo fmt
hu55a1n1 Oct 2, 2024
aab313d
Fix deprecation warning
hu55a1n1 Oct 2, 2024
8af4bc9
Use Url instead of String everywhere
hu55a1n1 Oct 2, 2024
dbbe057
Update manifest to enable DNS name resolution
hu55a1n1 Oct 2, 2024
31c4ac9
Add ws_url and grpc_url
hu55a1n1 Oct 2, 2024
85d5fad
misc clippy fixes
hu55a1n1 Oct 2, 2024
984ea74
Rename CliWasmdClient -> CliClient
hu55a1n1 Oct 2, 2024
493fd43
Bin agnostic CliClient
hu55a1n1 Oct 2, 2024
11d7fc8
Pass chain-id to enclave
hu55a1n1 Oct 2, 2024
b48d4b3
Improve CliClient
hu55a1n1 Oct 2, 2024
0d120c8
Rename NeutrondClient to GrpcClient
hu55a1n1 Oct 2, 2024
bcd921c
Increase max_thread and mount /usr/lib/ssl/cert.pem
hu55a1n1 Oct 2, 2024
ba753a5
Remove check for `wasm` prefix in contract addrs
hu55a1n1 Oct 2, 2024
2b399b5
Fix contract_deploy
hu55a1n1 Oct 2, 2024
0ac4c8e
Add fees to CwClient tx_execute
hu55a1n1 Oct 2, 2024
8603574
Fix hardcoded chain-id in handshake tx
hu55a1n1 Oct 3, 2024
727d695
Fix test build and warnings
hu55a1n1 Oct 3, 2024
3c96959
Fix URL in cw client
hu55a1n1 Oct 3, 2024
e17f58d
Remove QueryResult
hu55a1n1 Oct 3, 2024
c19c0eb
Cleanup
hu55a1n1 Oct 3, 2024
38ddb96
Fix enclave to support generic attestations
hu55a1n1 Oct 3, 2024
a3f6a21
Fix incorrect URL param in block waiter
hu55a1n1 Oct 3, 2024
5e011d8
debugs for printing dirs
hu55a1n1 Oct 3, 2024
7f6312d
Adjust gas limit and fees for transfers txs
hu55a1n1 Oct 3, 2024
c4c8fde
hardcode sk-file path
hu55a1n1 Oct 3, 2024
00d916f
clippy fixes
hu55a1n1 Oct 3, 2024
abd50bd
Add neutron testnet config
hu55a1n1 Oct 3, 2024
03e3f93
Import frontend neutron stuff
hu55a1n1 Oct 3, 2024
9f21f4a
Prettier
hu55a1n1 Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 117 additions & 126 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 41 additions & 2 deletions crates/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -79,6 +81,7 @@ pub enum Command {
Dev(DevArgs),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Subcommand, Serialize)]
pub enum ContractCommand {
Build(ContractBuildArgs),
Expand All @@ -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
Expand All @@ -123,7 +127,20 @@ pub struct HandshakeArgs {
/// <host>:<port> to tendermint rpc interface for this chain
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub node_url: Option<String>,
#[serde_as(as = "Option<DisplayFromStr>")]
pub node_url: Option<Url>,

/// websocket URL
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde_as(as = "Option<DisplayFromStr>")]
pub ws_url: Option<Url>,

/// gRPC URL
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde_as(as = "Option<DisplayFromStr>")]
pub grpc_url: Option<Url>,

/// RPC interface for the Quartz enclave
#[arg(long)]
Expand All @@ -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
Expand All @@ -152,7 +170,20 @@ pub struct ContractDeployArgs {
/// <host>:<port> to tendermint rpc interface for this chain
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub node_url: Option<String>,
#[serde_as(as = "Option<DisplayFromStr>")]
pub node_url: Option<Url>,

/// websocket URL
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde_as(as = "Option<DisplayFromStr>")]
pub ws_url: Option<Url>,

/// gRPC URL
#[arg(long)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde_as(as = "Option<DisplayFromStr>")]
pub grpc_url: Option<Url>,

/// Name or address of private key with which to sign
#[arg(long)]
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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")]
Expand Down
36 changes: 33 additions & 3 deletions crates/cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -20,7 +23,18 @@ pub struct Config {

/// <host>:<port> 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")]
Expand Down Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down
50 changes: 37 additions & 13 deletions crates/cli/src/handler/contract_deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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? {
Expand All @@ -81,8 +76,23 @@ async fn deploy(
)?)?;
let res = block_tx_commit(&tmrpc_client, deploy_output.txhash).await?;

let log: Vec<Log> = 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
Expand All @@ -108,8 +118,22 @@ async fn deploy(
)?)?;
let res = block_tx_commit(&tmrpc_client, init_output.txhash).await?;

let log: Vec<Log> = 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);
Expand Down
1 change: 1 addition & 0 deletions crates/cli/src/handler/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
26 changes: 24 additions & 2 deletions crates/cli/src/handler/enclave_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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,
];
Expand Down Expand Up @@ -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?;

Expand Down Expand Up @@ -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!(
Expand All @@ -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={}",
Expand Down
Loading
Loading