From 44346ef4d5baf823cacbc96a8433a74d4518a9b9 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sun, 14 Jan 2024 17:26:50 +0100 Subject: [PATCH 1/2] Replaced rc by arc in daemon --- cw-orch-daemon/src/builder.rs | 6 ++-- cw-orch-daemon/src/core.rs | 6 ++-- cw-orch-daemon/src/sender.rs | 10 +++--- cw-orch-daemon/src/sync/core.rs | 4 +-- .../cw-orch-core/src/environment/state.rs | 32 ++++++++++++++++++- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/cw-orch-daemon/src/builder.rs b/cw-orch-daemon/src/builder.rs index 984de2a9c..c165a0f19 100644 --- a/cw-orch-daemon/src/builder.rs +++ b/cw-orch-daemon/src/builder.rs @@ -1,5 +1,5 @@ use crate::{log::print_if_log_disabled, DaemonAsync, DaemonBuilder}; -use std::rc::Rc; +use std::sync::Arc; use ibc_chain_registry::chain::ChainData; @@ -63,7 +63,7 @@ impl DaemonAsyncBuilder { .deployment_id .clone() .unwrap_or(DEFAULT_DEPLOYMENT.to_string()); - let state = Rc::new(DaemonState::new(chain, deployment_id, false).await?); + let state = Arc::new(DaemonState::new(chain, deployment_id, false).await?); // if mnemonic provided, use it. Else use env variables to retrieve mnemonic let sender = if let Some(mnemonic) = &self.mnemonic { Sender::from_mnemonic(&state, mnemonic)? @@ -72,7 +72,7 @@ impl DaemonAsyncBuilder { }; let daemon = DaemonAsync { state, - sender: Rc::new(sender), + sender: Arc::new(sender), }; print_if_log_disabled()?; Ok(daemon) diff --git a/cw-orch-daemon/src/core.rs b/cw-orch-daemon/src/core.rs index 129b626ee..897b26592 100644 --- a/cw-orch-daemon/src/core.rs +++ b/cw-orch-daemon/src/core.rs @@ -26,8 +26,8 @@ use serde_json::from_str; use std::{ fmt::Debug, io::Write, - rc::Rc, str::{from_utf8, FromStr}, + sync::Arc, time::Duration, }; @@ -62,7 +62,7 @@ pub struct DaemonAsync { /// Sender to send transactions to the chain pub sender: Wallet, /// State of the daemon - pub state: Rc, + pub state: Arc, } impl DaemonAsync { @@ -84,7 +84,7 @@ impl DaemonAsync { } impl ChainState for DaemonAsync { - type Out = Rc; + type Out = Arc; fn state(&self) -> Self::Out { self.state.clone() diff --git a/cw-orch-daemon/src/sender.rs b/cw-orch-daemon/src/sender.rs index a413580d6..02ed6e6ae 100644 --- a/cw-orch-daemon/src/sender.rs +++ b/cw-orch-daemon/src/sender.rs @@ -34,7 +34,7 @@ use cosmwasm_std::{coin, Addr, Coin}; use cw_orch_core::{log::LOCAL_LOGS, CwOrchEnvVars}; use secp256k1::{All, Context, Secp256k1, Signing}; -use std::{convert::TryFrom, rc::Rc, str::FromStr}; +use std::{convert::TryFrom, str::FromStr, sync::Arc}; use cosmos_modules::vesting::PeriodicVestingAccount; use tonic::transport::Channel; @@ -44,18 +44,18 @@ const BUFFER_THRESHOLD: u64 = 200_000; const SMALL_GAS_BUFFER: f64 = 1.4; /// A wallet is a sender of transactions, can be safely cloned and shared within the same thread. -pub type Wallet = Rc>; +pub type Wallet = Arc>; /// Signer of the transactions and helper for address derivation /// This is the main interface for simulating and signing transactions pub struct Sender { pub private_key: PrivateKey, pub secp: Secp256k1, - pub(crate) daemon_state: Rc, + pub(crate) daemon_state: Arc, } impl Sender { - pub fn new(daemon_state: &Rc) -> Result, DaemonError> { + pub fn new(daemon_state: &Arc) -> Result, DaemonError> { let kind = ChainKind::from(daemon_state.chain_data.network_type.clone()); // NETWORK_MNEMONIC_GROUP let env_variable_name = kind.mnemonic_env_variable_name(); @@ -71,7 +71,7 @@ impl Sender { /// Construct a new Sender from a mnemonic pub fn from_mnemonic( - daemon_state: &Rc, + daemon_state: &Arc, mnemonic: &str, ) -> Result, DaemonError> { let secp = Secp256k1::new(); diff --git a/cw-orch-daemon/src/sync/core.rs b/cw-orch-daemon/src/sync/core.rs index 1d416d194..ca5f37f6e 100644 --- a/cw-orch-daemon/src/sync/core.rs +++ b/cw-orch-daemon/src/sync/core.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, rc::Rc, time::Duration}; +use std::{fmt::Debug, sync::Arc, time::Duration}; use super::super::{sender::Wallet, DaemonAsync}; use crate::{ @@ -74,7 +74,7 @@ impl Daemon { } impl ChainState for Daemon { - type Out = Rc; + type Out = Arc; fn state(&self) -> Self::Out { self.daemon.state.clone() diff --git a/packages/cw-orch-core/src/environment/state.rs b/packages/cw-orch-core/src/environment/state.rs index f80a91bd6..93da025dc 100644 --- a/packages/cw-orch-core/src/environment/state.rs +++ b/packages/cw-orch-core/src/environment/state.rs @@ -2,7 +2,7 @@ use crate::error::CwEnvError; use cosmwasm_std::Addr; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; /// State accessor trait. /// Indicates that the type has access to an underlying state. @@ -107,3 +107,33 @@ impl StateInterface for Rc { (**self).deploy_details() } } + +impl StateInterface for Arc { + fn get_address(&self, contract_id: &str) -> Result { + (**self).get_address(contract_id) + } + + fn set_address(&mut self, contract_id: &str, address: &Addr) { + (*Arc::make_mut(self)).set_address(contract_id, address) + } + + fn get_code_id(&self, contract_id: &str) -> Result { + (**self).get_code_id(contract_id) + } + + fn set_code_id(&mut self, contract_id: &str, code_id: u64) { + (*Arc::make_mut(self)).set_code_id(contract_id, code_id) + } + + fn get_all_addresses(&self) -> Result, CwEnvError> { + (**self).get_all_addresses() + } + + fn get_all_code_ids(&self) -> Result, CwEnvError> { + (**self).get_all_code_ids() + } + + fn deploy_details(&self) -> DeployDetails { + (**self).deploy_details() + } +} From f6e4393804a9617509c5fff7a12e9e3ccea2b1f7 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 23 Jan 2024 15:31:59 +0100 Subject: [PATCH 2/2] Added warning about thread usage of daemon --- cw-orch-daemon/src/core.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cw-orch-daemon/src/core.rs b/cw-orch-daemon/src/core.rs index f1c0864cb..2a83a5942 100644 --- a/cw-orch-daemon/src/core.rs +++ b/cw-orch-daemon/src/core.rs @@ -57,6 +57,13 @@ use tonic::transport::Channel; Different Cosmos SDK modules can be queried through the daemon by calling the [`DaemonAsync::query_client`] method with a specific querier. See [Querier](crate::queriers) for examples. + + ## Warning + + This daemon is thread safe and can be used between threads. + However, please make sure that you are not trying to broadcast multiple transactions at once when using this Daemon on different threads. + If you do so, you WILL get account sequence errors and your transactions won't get broadcasted. + Use a Mutex on top of this DaemonAsync to avoid such errors. */ pub struct DaemonAsync { /// Sender to send transactions to the chain