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

feat: Fixed dev_deploy to use registrar account to create top-level accounts (nearcore 1.37.0+ forbidden to create top-level accounts by non-registrar accounts) #360

Merged
merged 6 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions workspaces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
83 changes: 82 additions & 1 deletion workspaces/src/network/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -74,3 +75,83 @@ pub(crate) fn set_sandbox_configs(home_dir: impl AsRef<Path>) -> 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<Path>) -> 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<Path>) -> 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(())
}
1 change: 1 addition & 0 deletions workspaces/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ pub use self::testnet::Testnet;
pub use self::variants::{
AllowDevAccountCreation, NetworkClient, NetworkInfo, TopLevelAccountCreator,
};
pub use config::set_sandbox_genesis;
18 changes: 16 additions & 2 deletions workspaces/src/network/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ impl Sandbox {
)),
}
}

pub(crate) fn registrar_signer(&self) -> Result<InMemorySigner> {
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,
Expand Down Expand Up @@ -126,7 +140,7 @@ impl TopLevelAccountCreator for Sandbox {
id: AccountId,
sk: SecretKey,
) -> Result<Execution<Account>> {
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)
Expand All @@ -146,7 +160,7 @@ impl TopLevelAccountCreator for Sandbox {
sk: SecretKey,
wasm: &[u8],
) -> Result<Execution<Contract>> {
let root_signer = self.root_signer()?;
let root_signer = self.registrar_signer()?;
let outcome = self
.client()
.create_account_and_deploy(
Expand Down
2 changes: 2 additions & 0 deletions workspaces/src/network/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand Down
15 changes: 2 additions & 13 deletions workspaces/tests/cross_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand All @@ -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(())
}

Expand All @@ -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()?;
Expand Down
1 change: 1 addition & 0 deletions workspaces/tests/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;

Expand Down
Loading