diff --git a/Cargo.lock b/Cargo.lock index 558ce74..d4fd3c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -176,7 +176,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -305,6 +305,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + [[package]] name = "block-buffer" version = "0.9.0" @@ -355,9 +361,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -1147,6 +1153,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.28" @@ -2033,11 +2045,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2046,9 +2058,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2311,7 +2323,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -3138,9 +3150,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ "memchr", ] diff --git a/secretrs/examples/contract_query.rs b/secretrs/examples/contract_query.rs index bffe066..c565464 100644 --- a/secretrs/examples/contract_query.rs +++ b/secretrs/examples/contract_query.rs @@ -4,7 +4,7 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use secretrs::{ - clients::{ComputeQueryClient, RegistrationQueryClient}, + grpc_clients::{ComputeQueryClient, RegistrationQueryClient}, proto::secret::compute::v1beta1::{QueryByContractAddressRequest, QuerySecretContractRequest}, utils::encryption::EncryptionUtils, }; diff --git a/secretrs/examples/encrypt.rs b/secretrs/examples/encrypt.rs index ad64dbe..6870e19 100644 --- a/secretrs/examples/encrypt.rs +++ b/secretrs/examples/encrypt.rs @@ -3,14 +3,10 @@ use serde::{Deserialize, Serialize}; use secretrs::utils::EncryptionUtils; -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - TokenInfo {}, -} - #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { + color_eyre::install()?; + let code_hash = "9a00ca4ad505e9be7e6e6dddf8d939b7ec7e9ac8e109c8681f10db9cacb36d42"; let query = QueryMsg::TokenInfo {}; @@ -18,13 +14,17 @@ async fn main() -> Result<()> { let encrypted = encryption_utils.encrypt(code_hash, &query)?; let nonce = encrypted.nonce(); let query = encrypted.into_inner(); - println!("Encrypted query: {}", hex::encode(&query)); // Use this to decrypt responses from the enclave: - let decrypted_bytes = encryption_utils.decrypt(&nonce, &query)?; println!("Decrypted query: {}", String::from_utf8(decrypted_bytes)?); Ok(()) } + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + TokenInfo {}, +} diff --git a/secretrs/examples/query.rs b/secretrs/examples/query.rs index d780086..2448624 100644 --- a/secretrs/examples/query.rs +++ b/secretrs/examples/query.rs @@ -1,15 +1,19 @@ use color_eyre::{eyre::OptionExt, owo_colors::OwoColorize, Result}; use secretrs::{ - clients::{AuthQueryClient, BankQueryClient, ComputeQueryClient, GrpcClient, TxServiceClient}, + grpc_clients::{ + AuthQueryClient, BankQueryClient, ComputeQueryClient, GrpcClient, TxServiceClient, + }, proto, }; -// const GRPC_URL: &str = "http://localhost:9090"; const GRPC_URL: &str = "http://grpc.testnet.secretsaturn.net:9090"; const TEST_ADDRESS: &str = "secret1ap26qrlp8mcq2pg6r47w43l0y8zkqm8a450s03"; +#[tokio::main(flavor = "current_thread")] async fn async_main() -> Result<()> { + color_eyre::install()?; + // A single item page used throughout for brevity use proto::cosmos::base::query::v1beta1::PageRequest; let _one_page = Some(PageRequest { @@ -44,7 +48,7 @@ async fn async_main() -> Result<()> { // Method #1 if let Some(any) = response.account { let base_account = any.to_msg::()?; - let base_account = secretrs::auth::BaseAccount::try_from(base_account)?; + let base_account = cosmrs::auth::BaseAccount::try_from(base_account)?; println!( "Example: \"{}'s account number is {} and sequence is {} at block {}\"", base_account.address.bright_green(), @@ -58,7 +62,7 @@ async fn async_main() -> Result<()> { // let base_account = response // .account // .and_then(|any| any.to_msg::().ok() ) - // .and_then(|base_account| secretrs::auth::BaseAccount::try_from(base_account).ok()) + // .and_then(|base_account| cosmrs::auth::BaseAccount::try_from(base_account).ok()) // .ok_or_eyre("No Account")?; // println!("Account: {:?}", base_account.green()); @@ -121,17 +125,3 @@ async fn async_main() -> Result<()> { Ok(()) } - -fn main() -> Result<()> { - color_eyre::install()?; - - // Create a new Tokio runtime using the current thread scheduler - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - // Use the runtime to run the async code - rt.block_on(async_main()) -} diff --git a/secretrs/examples/tx.rs b/secretrs/examples/tx.rs index ce011c3..4c8a918 100644 --- a/secretrs/examples/tx.rs +++ b/secretrs/examples/tx.rs @@ -1,30 +1,21 @@ -// #![allow(unused)] - use color_eyre::{owo_colors::OwoColorize, Result}; use tokio::time::{sleep, Duration}; -use secretrs::proto::cosmos::tx::v1beta1::BroadcastTxRequest; use secretrs::{ bank::MsgSend, - clients::{GrpcClient, TxServiceClient}, + grpc_clients::{GrpcClient, TxServiceClient}, + proto::cosmos::tx::v1beta1::BroadcastTxRequest, query::PageRequest, tendermint::Hash, tx::{self, Fee, Msg, SignDoc, SignerInfo, Tx}, AccountId, Coin, }; -// const GRPC_URL: &str = "http://grpc.testnet.secretsaturn.net:9090"; const GRPC_URL: &str = "http://localhost:9090"; -async fn async_main() -> Result<()> { - // A single item page used throughout for brevity - let _one_page = Some(PageRequest { - key: vec![], - offset: 0, - limit: 1, - count_total: true, - reverse: false, - }); +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<()> { + color_eyre::install()?; // Tx Broadcast println!("\n{}", "Tx Service".underline().blue()); @@ -87,17 +78,3 @@ async fn async_main() -> Result<()> { Ok(()) } - -fn main() -> Result<()> { - color_eyre::install()?; - - // Create a new Tokio runtime using the current thread scheduler - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .enable_time() - .build() - .unwrap(); - - // Use the runtime to run the async code - rt.block_on(async_main()) -} diff --git a/secretrs/src/dev.rs b/secretrs/src/dev.rs deleted file mode 100644 index 7174444..0000000 --- a/secretrs/src/dev.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! Development-related functionality. -//! -//! This module contains support for integration testing against a -//! Secret Network full node (localsecret) running inside of Docker. - -#![allow(clippy::panic)] - -use crate::{ - rpc::{self, Client}, - tx::Tx, -}; -use std::{ffi::OsStr, panic, process, str, time::Duration}; -use tendermint::Hash; -use tokio::time; - -/// Docker image (on Docker Hub) containing a single-node test environment for -/// [`localsecret`], the reference implementation of a Cosmos Hub full node. -/// -/// [`localsecret`]: https://github.com/scrtlabs/LocalSecret -pub const LOCALSECRET_DOCKER_IMAGE: &str = "ghcr.io/scrtlabs/localsecret"; - -/// Invoke `docker run` with the given arguments, calling the provided function -/// after the container has booted and terminating the container after the -/// provided function completes, catching panics and propagating them to ensure -/// that the container reliably shuts down. -/// -/// Prints log output from the container in the event an error occurred. -pub fn docker_run(args: A, f: F) -> R -where - A: IntoIterator, - S: AsRef, - F: FnOnce() -> R + panic::UnwindSafe, -{ - let container_id = exec_docker_command("run", args); - let result = panic::catch_unwind(f); - - if result.is_err() { - let logs = exec_docker_command("logs", [&container_id]); - - println!("\n---- docker stdout ----"); - println!("{}", logs); - } - - exec_docker_command("kill", [&container_id]); - - match result { - Ok(res) => res, - Err(err) => panic::resume_unwind(err), - } -} - -/// Execute a given `docker` command, returning what was written to stdout -/// if the command completed successfully. -/// -/// Panics if the `docker` process exits with an error code. -fn exec_docker_command(name: &str, args: A) -> String -where - A: IntoIterator, - S: AsRef, -{ - let output = process::Command::new("docker") - .arg(name) - .args(args) - .stdout(process::Stdio::piped()) - .output() - .unwrap_or_else(|err| panic!("error invoking `docker {}`: {}", name, err)); - - if !output.status.success() { - panic!("`docker {}` exited with error status: {:?}", name, output); - } - - str::from_utf8(&output.stdout) - .expect("UTF-8 error decoding docker output") - .trim_end() - .to_owned() -} - -/// Wait for the node to produce the first block. -/// -/// This should be used at the beginning of the test lifecycle to ensure -/// the node is fully booted. -pub async fn poll_for_first_block(rpc_client: &rpc::HttpClient) { - rpc_client - .wait_until_healthy(Duration::from_secs(5)) - .await - .expect("error waiting for RPC to return healthy responses"); - - let mut attempts_remaining = 25; - - while let Err(e) = rpc_client.latest_block().await { - if !matches!(e.detail(), rpc::error::ErrorDetail::Serde(_)) { - panic!("unexpected error waiting for first block: {:?}", e); - } - - if attempts_remaining == 0 { - panic!("timeout waiting for first block"); - } - - attempts_remaining -= 1; - time::sleep(Duration::from_millis(200)).await; - } -} - -/// Wait for a transaction with the given hash to appear in the blockchain -pub async fn poll_for_tx(rpc_client: &rpc::HttpClient, tx_hash: Hash) -> Tx { - let attempts = 5; - - // TODO(tarcieri): better conversion or unified `Hash` type, see tendermint-rs#1221 - #[allow(clippy::unwrap_used)] - let tx_hash = tendermint::Hash::Sha256(tx_hash.as_ref().try_into().unwrap()); - - for _ in 0..attempts { - // TODO(tarcieri): handle not found errors - if let Ok(tx) = Tx::find_by_hash(rpc_client, tx_hash).await { - return tx; - } - } - - panic!("couldn't find transaction after {} attempts!", attempts); -} diff --git a/secretrs/src/clients.rs b/secretrs/src/grpc_clients.rs similarity index 84% rename from secretrs/src/clients.rs rename to secretrs/src/grpc_clients.rs index 0b0537d..04bb163 100644 --- a/secretrs/src/clients.rs +++ b/secretrs/src/grpc_clients.rs @@ -75,42 +75,6 @@ pub use ::secret_sdk_proto::secret::registration::v1beta1::query_client::QueryCl // pub use ::secret_sdk_proto::secret::emergencybutton::v1beta1::msg_client::MsgClient as EmergencyButtonMsgClient; // pub use ::secret_sdk_proto::secret::intertx::v1beta1::msg_client::MsgClient as InterTxMsgClient; -// Experimental! - -#[cfg(feature = "grpc")] -#[async_trait] -pub trait GrpcClient { - async fn grpc_find_by_hash( - grpc_client: &mut TxServiceClient<::tonic::transport::Channel>, - tx_hash: Hash, - ) -> Result; -} - -#[cfg(feature = "grpc")] -#[async_trait] -impl GrpcClient for Tx { - async fn grpc_find_by_hash( - grpc_client: &mut TxServiceClient<::tonic::transport::Channel>, - tx_hash: Hash, - ) -> Result { - use cosmrs::proto::cosmos::tx::v1beta1::GetTxRequest; - - grpc_client - .get_tx(GetTxRequest { - hash: tx_hash.to_string(), - }) - .await - .map_err(ErrorReport::from) - .and_then(|resp| { - resp.into_inner() - .tx - .ok_or(Error::TxNotFound { hash: tx_hash }) - .map_err(ErrorReport::from) - }) - .and_then(TryInto::try_into) - } -} - #[cfg(target_arch = "wasm32")] #[cfg(test)] mod test { diff --git a/secretrs/src/lib.rs b/secretrs/src/lib.rs index c2e238c..f9dda8b 100644 --- a/secretrs/src/lib.rs +++ b/secretrs/src/lib.rs @@ -1,23 +1,15 @@ -#![doc = include_str!("../README.md")] - //! # SecretRS - //! //! SecretRS re-exports `cosmrs` at the top-level of the crate. //! This allows `secretrs` to be used as a drop-in replacement for `cosmrs`. -pub use cosmrs::*; - pub mod compute; #[cfg(feature = "grpc-core")] -pub mod clients; - +pub mod grpc_clients; pub mod utils; -// TODO - this really belongs in a separate crate -// #[cfg(feature = "dev")] -// pub mod dev; - -pub use crate::utils::EncryptionUtils; +pub use utils::EncryptionUtils; +pub use cosmrs::*; pub use secret_sdk_proto::{self as proto, SECRET_VERSION}; diff --git a/secretrs/src/utils/consts.rs b/secretrs/src/utils/consts.rs deleted file mode 100644 index 5bdd559..0000000 --- a/secretrs/src/utils/consts.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![allow(unused)] - -// Chain info -pub static CHAIN_PREFIX: &str = "secret"; -pub static SCRT_DERIVATION_PATH: &str = "m/44'/529'/0'/0/0"; -pub static COIN_DENOM: &str = "uscrt"; diff --git a/secretrs/src/utils/encryption.rs b/secretrs/src/utils/encryption.rs index 9263d03..a3daba8 100644 --- a/secretrs/src/utils/encryption.rs +++ b/secretrs/src/utils/encryption.rs @@ -1,44 +1,10 @@ -use std::fmt::Debug; - -use derive_more::From; +use aes_siv::{siv::Aes128Siv, Key, KeyInit}; use hex_literal::hex; use nanorand::rand::Rng; - -use aes_siv::{siv::Aes128Siv, Key, KeyInit}; use x25519_dalek::{PublicKey, StaticSecret}; -pub type Result = core::result::Result; - -#[derive(Debug, From)] -pub enum Error { - EmptyCiphertext, - - InvalidCodeHash, - - InvalidChainId { - chain_id: String, - }, - - #[from] - FromHex(hex::FromHexError), - - #[from] - FromUtf8(std::string::FromUtf8Error), - - #[from] - SerdeJson(serde_json::Error), - - #[from] - AesSiv(aes_siv::Error), -} - -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{self:?}") - } -} - -impl std::error::Error for Error {} +use super::Error; +type Result = core::result::Result; const DEVNET_CHAIN_IDS: [&str; 1] = ["secretdev-1"]; const TESTNET_CHAIN_IDS: [&str; 1] = ["pulsar-3"]; diff --git a/secretrs/src/utils/error.rs b/secretrs/src/utils/error.rs index 41e0b09..e577b06 100644 --- a/secretrs/src/utils/error.rs +++ b/secretrs/src/utils/error.rs @@ -1,17 +1,32 @@ -pub type Result = std::result::Result; +use derive_more::From; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, From)] pub enum Error { - #[error("{0}")] - Generic(String), - #[error(transparent)] - CosmRs(#[from] cosmrs::ErrorReport), - #[error(transparent)] - SerdeJson(#[from] serde_json::Error), - #[error(transparent)] - Base64Decode(#[from] base64::DecodeError), - #[error(transparent)] - FromUtf8(#[from] std::string::FromUtf8Error), - #[error(transparent)] - FromHex(#[from] hex::FromHexError), + EmptyCiphertext, + + InvalidCodeHash, + + InvalidChainId { + chain_id: String, + }, + + #[from] + FromHex(hex::FromHexError), + + #[from] + FromUtf8(std::string::FromUtf8Error), + + #[from] + SerdeJson(serde_json::Error), + + #[from] + AesSiv(aes_siv::Error), +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:?}") + } } + +impl std::error::Error for Error {} diff --git a/secretrs/src/utils/mod.rs b/secretrs/src/utils/mod.rs index bbbcabf..e31faf3 100644 --- a/secretrs/src/utils/mod.rs +++ b/secretrs/src/utils/mod.rs @@ -41,7 +41,6 @@ //! let data = String::from_utf8(decoded_bytes)?; //! ```` -pub(crate) mod consts; pub mod encryption; pub mod error;