diff --git a/README.md b/README.md index 7f72586c..bce6fad6 100644 --- a/README.md +++ b/README.md @@ -339,3 +339,4 @@ These environment variables will be useful if there was ever a snag hit: - `NEAR_RPC_TIMEOUT_SECS`: The default is 10 seconds, but this is the amount of time beforing timing out waiting for a RPC service when talking to the sandbox or any other network such as testnet. - `NEAR_SANDBOX_BIN_PATH`: Set this to our own prebuilt `neard-sandbox` bin path if we want to use a non-default version of the sandbox or configure nearcore with our own custom features that we want to test in workspaces. +- `NEAR_SANDBOX_MAX_PAYLOAD_SIZE`: Sets the max payload size for sending transaction commits to sandbox. The default is 1gb and is necessary for patching large states. diff --git a/workspaces/Cargo.toml b/workspaces/Cargo.toml index 1fc636c6..a65378ad 100644 --- a/workspaces/Cargo.toml +++ b/workspaces/Cargo.toml @@ -24,6 +24,7 @@ rand = "0.8.4" reqwest = { version = "0.11", features = ["json"] } serde = "1.0" serde_json = "1.0" +json-patch = "0.2" thiserror = "1.0" tokio = { version = "1", features = ["full"] } tokio-retry = "0.3" diff --git a/workspaces/src/network/config.rs b/workspaces/src/network/config.rs new file mode 100644 index 00000000..86d5e72e --- /dev/null +++ b/workspaces/src/network/config.rs @@ -0,0 +1,68 @@ +//! Network specific configurations used to modify behavior inside a chain. +//! This is so far only useable with sandbox networks since it would require +//! direct access to a node to change the config. Each network like mainnet +//! and testnet already have pre-configured settings; meanwhile sandbox can +//! have additional settings on top of them to facilitate custom behavior +//! such as sending large requests to the sandbox network. +// +// NOTE: nearcore has many, many configs which can easily change in the future +// so this config.rs file just purely modifies the data and does not try to +// replicate all the structs from nearcore side; which can be a huge maintenance +// churn if we were to. + +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +use serde_json::Value; + +use crate::error::ErrorKind; +use crate::Result; + +/// Overwrite the $home_dir/config.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(home_dir: &Path, value: Value) -> Result<()> { + let config_file = + File::open(home_dir.join("config.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))?; + + json_patch::merge(&mut config, &value); + let config_file = + File::create(home_dir.join("config.json")).map_err(|err| ErrorKind::Io.custom(err))?; + serde_json::to_writer(config_file, &config).map_err(|err| ErrorKind::Io.custom(err))?; + + Ok(()) +} + +/// Limit how much nearcore/sandbox can receive per payload. The default set by nearcore is not +/// enough for certain sandbox operations like patching contract state in the case of contracts +/// larger than 10mb. +fn max_sandbox_json_payload_size() -> Result { + let max_files = match std::env::var("NEAR_SANDBOX_MAX_PAYLOAD_SIZE") { + Ok(val) => val + .parse::() + .map_err(|err| ErrorKind::DataConversion.custom(err))?, + + // Default is 1GB which should suit most contract sizes. + Err(_err) => 1024 * 1024 * 1024, + }; + + Ok(max_files) +} + +/// Set extra configs for the sandbox defined by workspaces. +pub(crate) fn set_sandbox_configs(home_dir: &Path) -> Result<()> { + overwrite( + home_dir, + serde_json::json!({ + "rpc": { + "limits_config": { + "json_payload_max_size": max_sandbox_json_payload_size()?, + }, + }, + }), + ) +} diff --git a/workspaces/src/network/mod.rs b/workspaces/src/network/mod.rs index 98868398..eee289eb 100644 --- a/workspaces/src/network/mod.rs +++ b/workspaces/src/network/mod.rs @@ -3,11 +3,13 @@ //! Currently the builtin network types are [`Mainnet`], [`Testnet`], and [`Sandbox`]. mod betanet; +mod config; mod info; mod mainnet; mod sandbox; mod server; mod testnet; + pub(crate) mod variants; pub(crate) use variants::DEV_ACCOUNT_SEED; diff --git a/workspaces/src/network/server.rs b/workspaces/src/network/server.rs index 85393d09..68813727 100644 --- a/workspaces/src/network/server.rs +++ b/workspaces/src/network/server.rs @@ -43,6 +43,10 @@ impl SandboxServer { .map_err(|e| SandboxErrorCode::InitFailure.custom(e))?; info!(target: "workspaces", "sandbox init: {:?}", output); + // 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)?; + let child = sandbox::run(&home_dir, self.rpc_port, self.net_port) .map_err(|e| SandboxErrorCode::RunFailure.custom(e))?;