diff --git a/workspaces/Cargo.toml b/workspaces/Cargo.toml index daf6ac24..7215ea16 100644 --- a/workspaces/Cargo.toml +++ b/workspaces/Cargo.toml @@ -39,11 +39,11 @@ near-crypto = "0.20.0" near-primitives = "0.20.0" near-jsonrpc-primitives = "0.20.0" near-jsonrpc-client = { version = "0.8", features = ["sandbox"] } -near-sandbox-utils = "0.7.0" +near-sandbox-utils = "0.8.0" near-chain-configs = { version = "0.20.0", optional = true } [build-dependencies] -near-sandbox-utils = "0.7.0" +near-sandbox-utils = "0.8.0" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/workspaces/src/network/config.rs b/workspaces/src/network/config.rs index 258504b3..c4509d89 100644 --- a/workspaces/src/network/config.rs +++ b/workspaces/src/network/config.rs @@ -11,8 +11,9 @@ // churn if we were to. use std::fs::File; -use std::io::BufReader; +use std::io::{BufReader, Write}; use std::path::Path; +use std::str::FromStr; use serde_json::Value; @@ -74,3 +75,83 @@ pub(crate) fn set_sandbox_configs(home_dir: impl AsRef) -> Result<()> { }), ) } + +/// Overwrite the $home_dir/genesis.json file over a set of entries. `value` will be used per (key, value) pair +/// where value can also be another dict. This recursively sets all entry in `value` dict to the config +/// dict, and saves back into `home_dir` at the end of the day. +fn overwrite_genesis(home_dir: impl AsRef) -> Result<()> { + let home_dir = home_dir.as_ref(); + let config_file = + File::open(home_dir.join("genesis.json")).map_err(|err| ErrorKind::Io.custom(err))?; + let config = BufReader::new(config_file); + let mut config: Value = + serde_json::from_reader(config).map_err(|err| ErrorKind::DataConversion.custom(err))?; + + let config = config.as_object_mut().expect("expected to be object"); + let mut total_supply = u128::from_str( + config + .get_mut("total_supply") + .expect("expected exist total_supply") + .as_str() + .unwrap_or_default(), + ) + .unwrap_or_default(); + let registrar_amount = 10_000_000_000_000_000_000_000_000_000_u128; + total_supply += registrar_amount; + config.insert( + "total_supply".to_string(), + Value::String(total_supply.to_string()), + ); + let records = config.get_mut("records").expect("expect exist records"); + records + .as_array_mut() + .expect("expected to be array") + .push(serde_json::json!( + { + "Account": { + "account_id": "registrar", + "account": { + "amount": registrar_amount.to_string(), + "locked": "0", + "code_hash": "11111111111111111111111111111111", + "storage_usage": 182 + } + } + } + )); + records + .as_array_mut() + .expect("expected to be array") + .push(serde_json::json!( + { + "AccessKey": { + "account_id": "registrar", + "public_key": "ed25519:5BGSaf6YjVm7565VzWQHNxoyEjwr3jUpRJSGjREvU9dB", + "access_key": { + "nonce": 0, + "permission": "FullAccess" + } + } + } + )); + + let config_file = + File::create(home_dir.join("genesis.json")).map_err(|err| ErrorKind::Io.custom(err))?; + serde_json::to_writer(config_file, &config).map_err(|err| ErrorKind::Io.custom(err))?; + + Ok(()) +} + +pub fn set_sandbox_genesis(home_dir: impl AsRef) -> Result<()> { + overwrite_genesis(&home_dir)?; + let registrar_key = r#"{"account_id":"registrar","public_key":"ed25519:5BGSaf6YjVm7565VzWQHNxoyEjwr3jUpRJSGjREvU9dB","private_key":"ed25519:3tgdk2wPraJzT4nsTuf86UX41xgPNk3MHnq8epARMdBNs29AFEztAuaQ7iHddDfXG9F2RzV1XNQYgJyAyoW51UBB"}"#; + let mut registrar_wallet = File::create(home_dir.as_ref().join("registrar.json")) + .map_err(|err| ErrorKind::Io.custom(err))?; + registrar_wallet + .write_all(registrar_key.as_bytes()) + .map_err(|err| ErrorKind::Io.custom(err))?; + registrar_wallet + .flush() + .map_err(|err| ErrorKind::Io.custom(err))?; + Ok(()) +} diff --git a/workspaces/src/network/mod.rs b/workspaces/src/network/mod.rs index 147a0802..c03a5995 100644 --- a/workspaces/src/network/mod.rs +++ b/workspaces/src/network/mod.rs @@ -27,3 +27,4 @@ pub use self::testnet::Testnet; pub use self::variants::{ AllowDevAccountCreation, NetworkClient, NetworkInfo, TopLevelAccountCreator, }; +pub use config::set_sandbox_genesis; diff --git a/workspaces/src/network/sandbox.rs b/workspaces/src/network/sandbox.rs index 1cea0ba1..4552fc5a 100644 --- a/workspaces/src/network/sandbox.rs +++ b/workspaces/src/network/sandbox.rs @@ -45,6 +45,20 @@ impl Sandbox { )), } } + + pub(crate) fn registrar_signer(&self) -> Result { + match &self.server.validator_key { + ValidatorKey::HomeDir(home_dir) => { + let path = home_dir.join("registrar.json"); + InMemorySigner::from_file(&path) + } + ValidatorKey::Known(account_id, secret_key) => Ok(InMemorySigner::from_secret_key( + account_id.clone(), + secret_key.clone(), + )), + } + } + pub(crate) async fn from_builder_with_version<'a>( build: NetworkBuilder<'a, Self>, version: &str, @@ -126,7 +140,7 @@ impl TopLevelAccountCreator for Sandbox { id: AccountId, sk: SecretKey, ) -> Result> { - let root_signer = self.root_signer()?; + let root_signer = self.registrar_signer()?; let outcome = self .client() .create_account(&root_signer, &id, sk.public_key(), DEFAULT_DEPOSIT) @@ -146,7 +160,7 @@ impl TopLevelAccountCreator for Sandbox { sk: SecretKey, wasm: &[u8], ) -> Result> { - let root_signer = self.root_signer()?; + let root_signer = self.registrar_signer()?; let outcome = self .client() .create_account_and_deploy( diff --git a/workspaces/src/network/server.rs b/workspaces/src/network/server.rs index ffd14457..f910105c 100644 --- a/workspaces/src/network/server.rs +++ b/workspaces/src/network/server.rs @@ -122,6 +122,8 @@ impl SandboxServer { // Configure `$home_dir/config.json` to our liking. Sandbox requires extra settings // for the best user experience, and being able to offer patching large state payloads. crate::network::config::set_sandbox_configs(&home_dir)?; + // Configure `$home_dir/genesis.json` to our liking. + crate::network::config::set_sandbox_genesis(&home_dir)?; // Try running the server with the follow provided rpc_ports and net_ports let (rpc_port, rpc_port_lock) = acquire_unused_port().await?; diff --git a/workspaces/tests/cross_contract.rs b/workspaces/tests/cross_contract.rs index 2b407c55..74e1efcd 100644 --- a/workspaces/tests/cross_contract.rs +++ b/workspaces/tests/cross_contract.rs @@ -29,7 +29,7 @@ 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 + // Expect to fail for trying to create a new contract account with 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?; @@ -40,17 +40,6 @@ async fn test_cross_contract_create_contract() -> anyhow::Result<()> { 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(); - 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", - failures.len(), - ); - Ok(()) } @@ -60,7 +49,7 @@ 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(); + let status_id: AccountId = format!("status.{}", contract.id()).parse().unwrap(); cross_contract_create_contract(&status_id, &status_amt, &contract) .await? .into_result()?; diff --git a/workspaces/tests/deploy.rs b/workspaces/tests/deploy.rs index bf5806f5..b6df67dc 100644 --- a/workspaces/tests/deploy.rs +++ b/workspaces/tests/deploy.rs @@ -70,6 +70,7 @@ async fn test_manually_spawned_deploy() -> anyhow::Result<()> { .await .unwrap(); tracing::info!(target: "workspaces-test", "sandbox-init: {:?}", output); + near_workspaces::network::set_sandbox_genesis(&home_dir)?; let mut child = near_sandbox_utils::run(&home_dir, rpc_port, net_port)?;