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

chore: switch to using subaccounts & deprecate tla creation #337

Closed
wants to merge 12 commits into from
8 changes: 3 additions & 5 deletions workspaces/src/network/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ use crate::network::server::SandboxServer;
use crate::network::Info;
use crate::result::{Execution, ExecutionFinalResult, Result};
use crate::rpc::client::Client;
use crate::types::{AccountId, InMemorySigner, NearToken, SecretKey};
use crate::types::{AccountId, InMemorySigner, SecretKey, SEED_DEPOSIT};
use crate::{Account, Contract, Network, Worker};

// Constant taken from nearcore crate to avoid dependency
const DEFAULT_DEPOSIT: NearToken = NearToken::from_near(100);
/// Local sandboxed environment/network, which can be used to test without interacting with
/// networks that are online such as mainnet and testnet. Look at [`workspaces::sandbox`]
/// for how to spin up a sandboxed network and interact with it.
Expand Down Expand Up @@ -129,7 +127,7 @@ impl TopLevelAccountCreator for Sandbox {
let root_signer = self.root_signer()?;
let outcome = self
.client()
.create_account(&root_signer, &id, sk.public_key(), DEFAULT_DEPOSIT)
.create_account(&root_signer, &id, sk.public_key(), SEED_DEPOSIT)
.await?;

let signer = InMemorySigner::from_secret_key(id, sk);
Expand All @@ -153,7 +151,7 @@ impl TopLevelAccountCreator for Sandbox {
&root_signer,
&id,
sk.public_key(),
DEFAULT_DEPOSIT,
SEED_DEPOSIT,
wasm.into(),
)
.await?;
Expand Down
5 changes: 3 additions & 2 deletions workspaces/src/network/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub trait NetworkInfo {
fn info(&self) -> &Info;
}

// NOTE: only the registrar can create top level accounts as of Protocol >=64
#[async_trait]
pub trait TopLevelAccountCreator {
async fn create_tla(
Expand All @@ -39,7 +40,7 @@ pub trait AllowDevAccountCreation {}

impl<T> Worker<T>
where
T: DevNetwork + TopLevelAccountCreator + 'static,
T: DevNetwork + TopLevelAccountCreator + 'static + NetworkInfo,
{
pub async fn create_tla(&self, id: AccountId, sk: SecretKey) -> Result<Execution<Account>> {
let res = self
Expand Down Expand Up @@ -73,7 +74,7 @@ where
}

pub async fn dev_generate(&self) -> (AccountId, SecretKey) {
let id = crate::rpc::tool::random_account_id();
let id = crate::rpc::tool::random_account_id(self.info().root_id.clone());
let sk = SecretKey::from_seed(KeyType::ED25519, DEV_ACCOUNT_SEED);
(id, sk)
}
Expand Down
3 changes: 2 additions & 1 deletion workspaces/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::rpc::client::{
use crate::rpc::query::{Query, ViewFunction};
use crate::types::{
AccessKey, AccountId, Gas, InMemorySigner, KeyType, NearToken, PublicKey, SecretKey,
SEED_DEPOSIT,
};
use crate::worker::Worker;
use crate::{Account, CryptoHash, Network};
Expand Down Expand Up @@ -435,7 +436,7 @@ impl<'a, 'b> CreateAccountTransaction<'a, 'b> {
signer,
parent_id,
new_account_id,
initial_balance: NearToken::from_yoctonear(100000000000000000000000u128),
initial_balance: SEED_DEPOSIT,
secret_key: None,
}
}
Expand Down
9 changes: 7 additions & 2 deletions workspaces/src/rpc/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@ pub(crate) fn into_state_map(state_items: Vec<StateItem>) -> HashMap<Vec<u8>, Ve
.collect()
}

pub(crate) fn random_account_id() -> AccountId {
pub(crate) fn random_account_id(parent_id: AccountId) -> AccountId {
let mut rng = rand::thread_rng();
let random_num = rng.gen_range(10000000000000usize..99999999999999);
let account_id = format!("dev-{}-{}", Utc::now().format("%Y%m%d%H%M%S"), random_num);
let account_id = format!(
"dev-{}-{}.{}",
Utc::now().format("%Y%m%d%H%M%S"),
random_num,
parent_id
);
let account_id: AccountId = account_id
.try_into()
.expect("could not convert dev account into AccountId");
Expand Down
4 changes: 4 additions & 0 deletions workspaces/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ pub type BlockHeight = u64;
/// Shard index, from 0 to NUM_SHARDS - 1.
pub type ShardId = u64;

/// This is an arbitrary amount used in the context of this library to seed test/sandbox accounts with
/// some amount of NEAR tokens to be able to perform transactions.
pub(crate) const SEED_DEPOSIT: NearToken = NearToken::from_near(100);

fn from_base58(s: &str) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
bs58::decode(s).into_vec().map_err(|err| err.into())
}
Expand Down
2 changes: 1 addition & 1 deletion workspaces/tests/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::Path;
#[test(tokio::test)]
async fn test_subaccount_creation() -> anyhow::Result<()> {
let worker = near_workspaces::sandbox().await?;
let account = worker.dev_create_account().await?;
let account = worker.root_account()?;

let sub = account
.create_subaccount("subaccount")
Expand Down
35 changes: 20 additions & 15 deletions workspaces/tests/cross_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,29 @@ async fn test_cross_contract_create_contract() -> anyhow::Result<()> {
let contract = worker.dev_deploy(FACTORY_CONTRACT).await?;
let status_amt = NearToken::from_near(35);

// Expect to fail for trying to create a new contract account with too short of a
// top level account name, such as purely just "status"
let status_id: AccountId = "status".parse().unwrap();
let outcome = cross_contract_create_contract(&status_id, &status_amt, &contract).await?;
let failures = outcome.failures();
assert!(
failures.len() == 1,
"Expected one receipt failure for creating too short of a TLA, but got {} failures",
failures.len()
);
#[cfg(feature = "experimental")]
if let Ok(conf) = worker.genesis_config().await {
if conf.protocol_version >= 64 {
// Expect the creation of a top level account to fail.
let status_id: AccountId = "status-top-level-account-long-name".parse().unwrap();
let outcome =
cross_contract_create_contract(&status_id, &status_amt, &contract).await?;
let failures = outcome.failures();
assert!(
failures.len() == 1,
"Expected one receipt failure for creating a top level account, but got {} failures",
failures.len()
);
}
}

// Expect to succeed after calling into the contract with expected length for a
// top level account.
let status_id: AccountId = "status-top-level-account-long-name".parse().unwrap();
// Expect the creation of a subaccount like "status.{contract_id}" to pass.
let status_id: AccountId = format!("status.{}", contract.id()).parse().unwrap();
let outcome = cross_contract_create_contract(&status_id, &status_amt, &contract).await?;
let failures = outcome.failures();
assert!(
failures.is_empty(),
"Expected no failures for creating a TLA, but got {} failures",
"Expected no failures for creating a subaccount, but got {} failures",
failures.len(),
);

Expand All @@ -60,7 +64,8 @@ async fn test_cross_contract_calls() -> anyhow::Result<()> {
let contract = worker.dev_deploy(FACTORY_CONTRACT).await?;
let status_amt = NearToken::from_near(35);

let status_id: AccountId = "status-top-level-account-long-name".parse().unwrap();
// "status.{contract_id}" is the account that will be created by the factory contract.
let status_id: AccountId = format!("status.{}", contract.id()).parse().unwrap();
cross_contract_create_contract(&status_id, &status_amt, &contract)
.await?
.into_result()?;
Expand Down
Loading
Loading