use std::{
env, fs,
path::{Path, PathBuf},
};
use once_cell::sync::Lazy;
use casper_execution_engine::engine_state::{Error, WasmV1Result};
use casper_storage::data_access_layer::GenesisRequest;
use casper_types::{bytesrepr::Bytes, GenesisAccount, GenesisConfig};
use super::{DEFAULT_ROUND_SEIGNIORAGE_RATE, DEFAULT_SYSTEM_CONFIG, DEFAULT_UNBONDING_DELAY};
use crate::{
GenesisConfigBuilder, DEFAULT_AUCTION_DELAY, DEFAULT_CHAINSPEC_REGISTRY,
DEFAULT_GENESIS_CONFIG_HASH, DEFAULT_GENESIS_TIMESTAMP_MILLIS,
DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS, DEFAULT_PROTOCOL_VERSION, DEFAULT_STORAGE_COSTS,
DEFAULT_VALIDATOR_SLOTS, DEFAULT_WASM_CONFIG,
};
static RUST_WORKSPACE_PATH: Lazy<PathBuf> = Lazy::new(|| {
let path = Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.and_then(Path::parent)
.expect("CARGO_MANIFEST_DIR should have parent");
assert!(
path.exists(),
"Workspace path {} does not exists",
path.display()
);
path.to_path_buf()
});
static RUST_WORKSPACE_WASM_PATH: Lazy<PathBuf> = Lazy::new(|| {
let path = RUST_WORKSPACE_PATH
.join("target")
.join("wasm32-unknown-unknown")
.join("release");
assert!(
path.exists() || RUST_TOOL_WASM_PATH.exists(),
"Rust Wasm path {} does not exists",
path.display()
);
path
});
static RUST_TOOL_WASM_PATH: Lazy<PathBuf> = Lazy::new(|| {
env::current_dir()
.expect("should get current working dir")
.join("wasm")
});
static MAYBE_CARGO_TARGET_DIR_WASM_PATH: Lazy<Option<PathBuf>> = Lazy::new(|| {
let maybe_target = std::env::var("CARGO_TARGET_DIR").ok();
maybe_target.as_ref().map(|path| {
Path::new(path)
.join("wasm32-unknown-unknown")
.join("release")
})
});
static WASM_PATHS: Lazy<Vec<PathBuf>> = Lazy::new(get_compiled_wasm_paths);
fn get_compiled_wasm_paths() -> Vec<PathBuf> {
let mut ret = vec![
RUST_WORKSPACE_WASM_PATH.clone(),
RUST_TOOL_WASM_PATH.clone(),
];
if let Some(cargo_target_dir_wasm_path) = &*MAYBE_CARGO_TARGET_DIR_WASM_PATH {
ret.push(cargo_target_dir_wasm_path.clone());
};
ret
}
pub fn read_wasm_file<T: AsRef<Path>>(contract_file: T) -> Bytes {
let mut attempted_paths = vec![];
if contract_file.as_ref().is_relative() {
for wasm_path in WASM_PATHS.iter() {
let mut filename = wasm_path.clone();
filename.push(contract_file.as_ref());
if let Ok(wasm_bytes) = fs::read(&filename) {
return Bytes::from(wasm_bytes);
}
attempted_paths.push(filename);
}
}
if let Ok(wasm_bytes) = fs::read(contract_file.as_ref()) {
return Bytes::from(wasm_bytes);
}
attempted_paths.push(contract_file.as_ref().to_owned());
let mut error_msg =
"\nFailed to open compiled Wasm file. Tried the following locations:\n".to_string();
for attempted_path in attempted_paths {
error_msg = format!("{} - {}\n", error_msg, attempted_path.display());
}
panic!("{}\n", error_msg);
}
pub fn create_genesis_config(accounts: Vec<GenesisAccount>) -> GenesisConfig {
let wasm_config = *DEFAULT_WASM_CONFIG;
let system_config = *DEFAULT_SYSTEM_CONFIG;
let validator_slots = DEFAULT_VALIDATOR_SLOTS;
let auction_delay = DEFAULT_AUCTION_DELAY;
let locked_funds_period_millis = DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS;
let round_seigniorage_rate = DEFAULT_ROUND_SEIGNIORAGE_RATE;
let unbonding_delay = DEFAULT_UNBONDING_DELAY;
let genesis_timestamp_millis = DEFAULT_GENESIS_TIMESTAMP_MILLIS;
let storage_costs = *DEFAULT_STORAGE_COSTS;
GenesisConfigBuilder::default()
.with_accounts(accounts)
.with_wasm_config(wasm_config)
.with_system_config(system_config)
.with_validator_slots(validator_slots)
.with_auction_delay(auction_delay)
.with_locked_funds_period_millis(locked_funds_period_millis)
.with_round_seigniorage_rate(round_seigniorage_rate)
.with_unbonding_delay(unbonding_delay)
.with_genesis_timestamp_millis(genesis_timestamp_millis)
.with_storage_costs(storage_costs)
.build()
}
pub fn create_run_genesis_request(accounts: Vec<GenesisAccount>) -> GenesisRequest {
let config = create_genesis_config(accounts);
GenesisRequest::new(
DEFAULT_GENESIS_CONFIG_HASH,
DEFAULT_PROTOCOL_VERSION,
config,
DEFAULT_CHAINSPEC_REGISTRY.clone(),
)
}
pub fn get_precondition_failure(exec_result: &WasmV1Result) -> &Error {
assert!(
exec_result.has_precondition_failure(),
"should be a precondition failure"
);
exec_result.error().expect("should have an error")
}