Skip to content

Commit

Permalink
add a mutex for tla functions
Browse files Browse the repository at this point in the history
  • Loading branch information
itegulov committed Feb 8, 2022
1 parent f3cca3a commit 8262636
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 10 deletions.
1 change: 1 addition & 0 deletions workspaces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Library for automating workflows and testing NEAR smart contracts.
"""

[dependencies]
async-mutex = "1.4.0"
async-trait = "0.1"
anyhow = "1.0"
base64 = "0.13"
Expand Down
23 changes: 14 additions & 9 deletions workspaces/src/network/sandbox_shared.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
use std::path::PathBuf;
use std::str::FromStr;

use async_trait::async_trait;
use once_cell::sync::Lazy;

use super::{
Account, AllowDevAccountCreation, AllowStatePatching, CallExecution, Contract, NetworkClient,
NetworkInfo, TopLevelAccountCreator,
};

use crate::network::sandbox::NEAR_BASE;
use crate::network::server::SandboxServer;
use crate::network::Info;
use crate::rpc::client::Client;
use crate::types::{AccountId, Balance, InMemorySigner, SecretKey};
use async_mutex::Mutex;
use async_trait::async_trait;
use once_cell::sync::Lazy;
use std::path::PathBuf;
use std::str::FromStr;

static SHARED_SERVER: Lazy<SandboxServer> = Lazy::new(|| {
let mut server = SandboxServer::default();
server.start().unwrap();
server
});

// Constant taken from nearcore crate to avoid dependency
pub(crate) const NEAR_BASE: Balance = 1_000_000_000_000_000_000_000_000;
// Using a shared sandbox instance is thread-safe as long as all threads use it with their own
// account. This means, however, is that the creation of these accounts should be sequential in
// order to avoid duplicated nonces.
static TLA_ACCOUNT_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));

const DEFAULT_DEPOSIT: Balance = 100 * NEAR_BASE;

Expand Down Expand Up @@ -69,10 +70,12 @@ impl TopLevelAccountCreator for SandboxShared {
sk: SecretKey,
) -> anyhow::Result<CallExecution<Account>> {
let root_signer = self.root_signer();
let guard = TLA_ACCOUNT_MUTEX.lock().await;
let outcome = self
.client
.create_account(&root_signer, &id, sk.public_key(), DEFAULT_DEPOSIT)
.await?;
drop(guard);

let signer = InMemorySigner::from_secret_key(id.clone(), sk);
Ok(CallExecution {
Expand All @@ -88,6 +91,7 @@ impl TopLevelAccountCreator for SandboxShared {
wasm: &[u8],
) -> anyhow::Result<CallExecution<Contract>> {
let root_signer = self.root_signer();
let guard = TLA_ACCOUNT_MUTEX.lock().await;
let outcome = self
.client
.create_account_and_deploy(
Expand All @@ -98,6 +102,7 @@ impl TopLevelAccountCreator for SandboxShared {
wasm.into(),
)
.await?;
drop(guard);

let signer = InMemorySigner::from_secret_key(id.clone(), sk);
Ok(CallExecution {
Expand Down
10 changes: 9 additions & 1 deletion workspaces/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ impl Client {
&self,
method: &M,
) -> MethodCallResult<M::Response, M::Error> {
retry(|| async { JsonRpcClient::connect(&self.rpc_addr).call(method).await }).await
retry(|| async {
// A new client is required since using a shared one between different threads can
// cause https://github.com/hyperium/hyper/issues/2112
JsonRpcClient::new_client()
.connect(&self.rpc_addr)
.call(method)
.await
})
.await
}

async fn send_tx_and_retry(
Expand Down

0 comments on commit 8262636

Please sign in to comment.