diff --git a/Cargo.lock b/Cargo.lock index 3b2f07491..37e0cbb17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5745,6 +5745,7 @@ dependencies = [ "libra-types", "serde_json", "tokio", + "url", ] [[package]] diff --git a/framework/cached-packages/src/libra_framework_sdk_builder.rs b/framework/cached-packages/src/libra_framework_sdk_builder.rs index 3c5903005..a3bae1d52 100644 --- a/framework/cached-packages/src/libra_framework_sdk_builder.rs +++ b/framework/cached-packages/src/libra_framework_sdk_builder.rs @@ -13,7 +13,6 @@ #![allow(dead_code)] #![allow(unused_imports)] #![allow(clippy::too_many_arguments)] - use diem_types::{ account_address::AccountAddress, transaction::{EntryFunction, TransactionPayload}, diff --git a/framework/libra-framework/sources/diem_governance.move b/framework/libra-framework/sources/diem_governance.move index ba0e5c2f1..404c77604 100644 --- a/framework/libra-framework/sources/diem_governance.move +++ b/framework/libra-framework/sources/diem_governance.move @@ -423,7 +423,7 @@ module diem_framework::diem_governance { } #[view] - // is the proposal complete and executed? + // how many votes on the proposal public fun get_votes(proposal_id: u64): (u128, u128) { voting::get_votes(@diem_framework, proposal_id) } diff --git a/framework/libra-framework/sources/ol_sources/address_utils.move b/framework/libra-framework/sources/ol_sources/address_utils.move index dd696932a..4125aa66e 100644 --- a/framework/libra-framework/sources/ol_sources/address_utils.move +++ b/framework/libra-framework/sources/ol_sources/address_utils.move @@ -33,6 +33,9 @@ module ol_framework::address_utils { // Shuffle addresses with the same values to ensure randomness position public fun shuffle_duplicates(addresses: &mut vector
, values: &vector) { + // belt and suspenders, if migration didn't happen. + // assert!(randomness::is_init(), error::invalid_state(ERANDOM_INIT_ERROR)); + assert!(vector::length(addresses) == vector::length(values), error::invalid_argument(EDIFFERENT_LENGTH)); let len = vector::length(values); let i = 0; diff --git a/framework/libra-framework/sources/ol_sources/epoch_boundary.move b/framework/libra-framework/sources/ol_sources/epoch_boundary.move index b4f65c337..f16de9b44 100644 --- a/framework/libra-framework/sources/ol_sources/epoch_boundary.move +++ b/framework/libra-framework/sources/ol_sources/epoch_boundary.move @@ -43,7 +43,7 @@ module diem_framework::epoch_boundary { const ETRIGGER_EPOCH_UNAUTHORIZED: u64 = 1; /// Epoch is not ready for reconfiguration const ETRIGGER_NOT_READY: u64 = 2; - /// Epoch number mismat + /// Epoch number mismatch const ENOT_SAME_EPOCH: u64 = 3; /////// Constants //////// @@ -254,20 +254,22 @@ module diem_framework::epoch_boundary { } #[view] - /// check to see if the epoch Boundary Bit is true + /// check to see if the epoch BoundaryBit is true public fun can_trigger(): bool acquires BoundaryBit { let state = borrow_global_mut(@ol_framework); assert!(state.ready, ETRIGGER_NOT_READY); - assert!(state.closing_epoch == reconfiguration::get_current_epoch(), + // greater than, in case there is an epoch change due to an epoch bump in + // testnet Twin tools, or a rescue operation. + assert!(state.closing_epoch <= reconfiguration::get_current_epoch(), ENOT_SAME_EPOCH); true } // This function handles the necessary migrations that occur at the epoch boundary // when new modules or structures are added by chain upgrades. - fun migrate_data(root: &signer) { - randomness::initialize(root); - migrations::execute(root); + fun migrate_data(framework: &signer) { + randomness::initialize(framework); + migrations::execute(framework); } // Contains all of 0L's business logic for end of epoch. diff --git a/framework/libra-framework/sources/ol_sources/vouch.move b/framework/libra-framework/sources/ol_sources/vouch.move index 1f7473db9..573278b4e 100644 --- a/framework/libra-framework/sources/ol_sources/vouch.move +++ b/framework/libra-framework/sources/ol_sources/vouch.move @@ -11,7 +11,7 @@ module ol_framework::vouch { use diem_framework::system_addresses; use diem_framework::transaction_fee; - use diem_std::debug::print; + use diem_std::debug::print; friend diem_framework::genesis; friend ol_framework::proof_of_fee; diff --git a/framework/libra-framework/sources/randomness.move b/framework/libra-framework/sources/randomness.move index 7fab83a78..682d14076 100644 --- a/framework/libra-framework/sources/randomness.move +++ b/framework/libra-framework/sources/randomness.move @@ -37,7 +37,7 @@ module diem_framework::randomness { friend diem_framework::block; friend ol_framework::musical_chairs; - const DST: vector = b"ALL_YOUR_BASE"; + const INIT_SEED: vector = b"all your base are belong to us"; const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; @@ -68,12 +68,17 @@ module diem_framework::randomness { move_to(framework, PerBlockRandomness { epoch: 0, round: 0, - seed: option::none(), + seed: option::some(INIT_SEED), seq: 0, }); } } + #[view] + public fun is_init(): bool { + exists(@diem_framework) + } + #[test_only] public fun initialize_for_testing(framework: &signer) acquires PerBlockRandomness { initialize(framework); @@ -98,11 +103,16 @@ module diem_framework::randomness { // public facing API. // assert!(is_unbiasable(), E_API_USE_IS_BIASIBLE); - let input = DST; let randomness = borrow_global_mut(@diem_framework); - let seed = *option::borrow(&randomness.seed); - vector::append(&mut input, seed); + // belt and suspenders if something didn't initialize + let input = if (option::is_some(&randomness.seed)) { + *option::borrow(&randomness.seed) + } else { + INIT_SEED + }; + + // 0L NOTE: these native APIs dont exist in 0L V7. // get_transaction_hash() doesnt exist. So different than vendor, // we will always increment a seed based on the block hash. @@ -110,6 +120,7 @@ module diem_framework::randomness { // transaction. // we will add the script hash of the entry function as a placeholder // though this will likely not be adding much entropy. + vector::append(&mut input, transaction_context::get_script_hash()); diff --git a/framework/releases/head.mrb b/framework/releases/head.mrb index eb3be61ff..d0e20fa11 100644 Binary files a/framework/releases/head.mrb and b/framework/releases/head.mrb differ diff --git a/smoke-tests/src/configure_validator.rs b/smoke-tests/src/configure_validator.rs index 11ae0a4ab..8cb6d3e7f 100644 --- a/smoke-tests/src/configure_validator.rs +++ b/smoke-tests/src/configure_validator.rs @@ -1,43 +1,59 @@ -use diem_forge::{LocalSwarm, Swarm}; +use diem_forge::{LocalSwarm, Node}; use diem_sdk::crypto::PrivateKey; use diem_sdk::types::LocalAccount; +use diem_types::chain_id::NamedChain; use libra_types::core_types::network_playlist::NetworkPlaylist; use libra_types::{core_types::app_cfg::AppCfg, exports::AuthenticationKey}; use std::path::PathBuf; -use url::Url; /// Set up the 0L local files, and get an AppCfg back after initializing in a temp dir, that will drop at the end of the test. -pub async fn init_val_config_files( +pub fn init_val_config_files( swarm: &mut LocalSwarm, nth: usize, - dir: PathBuf, + dir_opt: Option, ) -> anyhow::Result<(LocalAccount, AppCfg)> { - let info = swarm.diem_public_info_for_node(nth); - let url: Url = info.url().parse().unwrap(); + // TODO: unclear why public info needs to be a mutable borrow + let node = swarm + .validators() + .nth(nth) + .expect("could not get nth validator"); + let url = node.rest_api_endpoint(); - let node = swarm.validators().next().unwrap(); - let np = NetworkPlaylist::new(Some(url), Some(diem_types::chain_id::NamedChain::TESTING)); + let dir = dir_opt.unwrap_or(node.config_path().parent().unwrap().to_owned()); + + let chain_name = NamedChain::from_chain_id(&swarm.chain_id()).ok(); + let np = NetworkPlaylist::new(Some(url), chain_name); + let cfg_key = node.account_private_key().as_ref().unwrap(); + let prikey = cfg_key.private_key(); + let pubkey = prikey.public_key(); let mut app_cfg = AppCfg::init_app_configs( - AuthenticationKey::ed25519(&node.account_private_key().as_ref().unwrap().public_key()), + AuthenticationKey::ed25519(&pubkey), node.peer_id(), Some(dir), Some(np.chain_name), Some(np), - ) - .unwrap(); - - let pri_key = node - .account_private_key() - .as_ref() - .expect("could not get pri_key") - .private_key(); - let auth = AuthenticationKey::ed25519(&pri_key.public_key()); + )?; + let profile = app_cfg .get_profile_mut(None) .expect("could not get profile"); - profile.set_private_key(&pri_key); - let local_account = LocalAccount::new(auth.derived_address(), pri_key, 0); + profile.set_private_key(&prikey); + + let local_account = LocalAccount::new(profile.account, prikey, 0); Ok((local_account, app_cfg)) } + +/// helper to save libra-cli config files for each of the validators in +/// their local temp folder (alongside validator.yaml) +pub fn save_cli_config_all(swarm: &mut LocalSwarm) -> anyhow::Result<()> { + let len = swarm.validators().count(); + for i in 0..len { + // a libra-cli-config file will be created at the temp swarm + // directory of the node + let (_, app_cfg) = init_val_config_files(swarm, i, None)?; + let _file = app_cfg.save_file()?; + } + Ok(()) +} diff --git a/testsuites/twin/Makefile b/testsuites/twin/Makefile new file mode 100644 index 000000000..d18fedd2e --- /dev/null +++ b/testsuites/twin/Makefile @@ -0,0 +1,122 @@ +# NOTE: you'll need to have a db of a fullnode already synced +# twin tool will make a copy of this +# THE DB WILL NOT BE WRITTEN TO + +# TMP_DIR = /tmp/.tmpCu3Rxh/ + +ifndef DB_DIR +DB_DIR=$$HOME/.libra/data/db +endif + +ifndef UPGRADE_SCRIPT_PATH +UPGRADE_SCRIPT_PATH = $$HOME/upgrade-six/ +endif + +ifndef FRAMEWORK_SOURCE_PATH +FRAMEWORK_SOURCE_PATH = $$HOME/libra-framework/framework +endif + +ifndef DIEM_FORGE_NODE_BIN_PATH +DIEM_FORGE_NODE_BIN_PATH = $$HOME/.cargo/bin/libra +endif + +PROPOSAL_ID = 6 + +##### INSTRUCTIONS + +# Grab the essentials: +# sudo apt update +# sudo apt install -y git build-essential cmake clang llvm libgmp-dev pkg-config libssl-dev lld libpq-dev +# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + +# 1. use an up to date libra-cli binary +# > cargo build --release -p libra --locked +# > cp target/release/libra ~/.cargo/bin/ + +# 2. Make sure you have a fullnode that is already syced, you'll need the DB_DIR of it +# if you are starting fresh use: +# > libra config fullnode-init +# > libra node +# check height while syncing +# > watch -n 5 'curl -s 127.0.0.1:9101/metrics | grep diem_state_sync_version' + +# 2. compile the new libra-framework MOVE code with: +# > make upgrade-script +# note the defaults for input: FRAMEWORK_SOURCE_PATH and and output: UPGRADE_SCRIPT_PATH + +# 3. start a Twin swarm locally +# > make start-twin +# NOTE: the output `temp files found at: /tmp/<......> ` +# A local Twin of mainnet is now running on your machine. + +# 4. export that temp dir to your path +# > export TMP_DIR=/tmp/<......> + +# Now your can do transactions as the new random validators +# 5. check validator set +# > make view-vals + +# 6. try to tigger epoch +# > make tx-epoch +# NOTE: this usually should fail unless enough time has passed. + +# 7. Send the full upgrade e2e +# > make upgrade-ceremony + +# 8. check the state of the proposal +# > make view-state + +# start twin with three validators +start-twin: + cargo run -p libra-twin-tests -- -d ${DB_DIR} -c 3 + + +######### UPGRADE SCRIPT GENERATION +upgrade-script: move-build-framework move-build-script + +move-build-framework: + cd ${FRAMEWORK_SOURCE_PATH} && libra move framework release + +move-build-script: + libra move framework upgrade --core-modules libra-framework --output-dir ${UPGRADE_SCRIPT_PATH} --framework-local-dir ${FRAMEWORK_SOURCE_PATH} + +######## EPOCH TRIGGER +tx-epoch: + libra txs -c ${TMP_DIR}/0/libra-cli-config.yaml governance epoch-boundary + + +######## UPGRADE TRANSACTIONS +upgrade-ceremony: tx-propose tx-vote tx-resolve + +tx-propose: + libra txs -c ${TMP_DIR}/0/libra-cli-config.yaml governance propose -d ${UPGRADE_SCRIPT_PATH}/1-libra-framework -m https://tbd.com + +tx-vote: + libra txs -c ${TMP_DIR}/0/libra-cli-config.yaml governance vote -i ${PROPOSAL_ID} + libra txs -c ${TMP_DIR}/1/libra-cli-config.yaml governance vote -i ${PROPOSAL_ID} + libra txs -c ${TMP_DIR}/2/libra-cli-config.yaml governance vote -i ${PROPOSAL_ID} + +tx-resolve: + libra txs -c ${TMP_DIR}/0/libra-cli-config.yaml --tx-profile critical governance resolve -i ${PROPOSAL_ID} -d ${UPGRADE_SCRIPT_PATH}/1-libra-framework + +#### VIEW STATE OF UPGRADE PROPOSALS +view-state: + libra query -c ${TMP_DIR}/0/libra-cli-config.yaml view -f 0x1::diem_governance::get_proposal_state -a ${PROPOSAL_ID} + +view-resolve: + libra query -c ${TMP_DIR}/0/libra-cli-config.yaml view -f 0x1::diem_governance::get_can_resolve -a ${PROPOSAL_ID} + +view-vals: + libra query -c ${TMP_DIR}/0/libra-cli-config.yaml view -f 0x1::stake::get_current_validators + + +######## OTHER +debug-keys: + cat ${TMP_DIR}/0/private-identity.yaml + cat ${TMP_DIR}/1/private-identity.yaml + cat ${TMP_DIR}/2/private-identity.yaml + +help-tx-bid-shuffle: + libra txs -c ${TMP_DIR}/0/libra-cli-config.yaml validator pof -b 0.3 -e 1000 + libra txs -c ${TMP_DIR}/1/libra-cli-config.yaml validator pof -b 0.4 -e 1000 + libra txs -c ${TMP_DIR}/2/libra-cli-config.yaml validator pof -b 0.5 -e 1000 diff --git a/testsuites/twin/src/runner.rs b/testsuites/twin/src/runner.rs index 4699c7a5c..c7705ce28 100644 --- a/testsuites/twin/src/runner.rs +++ b/testsuites/twin/src/runner.rs @@ -1,7 +1,6 @@ use clap::{self, Parser}; use libra_smoke_tests::libra_smoke::LibraSmoke; use std::{fs, path::PathBuf}; - /// Twin of the network #[derive(Parser)] @@ -29,6 +28,9 @@ impl Twin { let num_validators = self.count_vals.unwrap_or(1); let mut smoke = LibraSmoke::new(Some(num_validators), None).await?; + // save_cli_config_all(&mut smoke.swarm)?; + + // thread::sleep(Duration::from_secs(60)); Twin::make_twin_swarm(&mut smoke, Some(db_path), true).await?; Ok(()) diff --git a/testsuites/twin/src/setup.rs b/testsuites/twin/src/setup.rs index 024e0e72a..93bd0272f 100644 --- a/testsuites/twin/src/setup.rs +++ b/testsuites/twin/src/setup.rs @@ -7,7 +7,7 @@ use diem_types::{ waypoint::Waypoint, }; use fs_extra::dir; -use libra_smoke_tests::libra_smoke::LibraSmoke; +use libra_smoke_tests::{configure_validator, libra_smoke::LibraSmoke}; use libra_txs::txs_cli_vals::ValidatorTxs; use smoke_test::test_utils::{MAX_CONNECTIVITY_WAIT_SECS, MAX_HEALTHY_WAIT_SECS}; use std::{ @@ -221,6 +221,7 @@ impl Twin { } /// Apply the rescue blob to the swarm db + /// returns the temp directory of the swarm pub async fn make_twin_swarm( smoke: &mut LibraSmoke, reference_db: Option, @@ -270,7 +271,7 @@ impl Twin { let temp_path = temp.path(); assert!(temp_path.exists()); let temp_db_path = Self::temp_backup_db(&reference_db, temp_path)?; - dbg!(&temp_db_path); + assert!(temp_db_path.exists()); println!("2. Create a rescue blob from the reference db"); @@ -305,7 +306,9 @@ impl Twin { .wait_for_all_nodes_to_catchup_to_version(start_version + 10, Duration::from_secs(30)) .await?; - let cli_tools = smoke.first_account_app_cfg()?; + // place a libra-cli-config.yaml in the home dir of the swarm vals + // helps test the cli tools + configure_validator::save_cli_config_all(&mut smoke.swarm)?; let duration_upgrade = start_upgrade.elapsed(); println!( @@ -313,18 +316,22 @@ impl Twin { duration_upgrade ); + let temp_dir = smoke.swarm.dir(); + println!("temp files found at: {}", temp_dir.display()); + if keep_running { dialoguer::Confirm::new() .with_prompt("swarm will keep running in background. Would you like to exit?") .interact()?; + // NOTE: all validators will stop when the LibraSmoke goes out of context. + // but since it's borrowed in this function you should assume it will continue until the caller goes out of scope. } - // NOTE: all validators will stop when the LibraSmoke goes out of context. - Ok(cli_tools.workspace.node_home) + + Ok(temp_dir.to_owned()) } /// Extract the credentials of the random validator async fn extract_credentials(marlon_node: &LocalNode) -> anyhow::Result { - println!("extracting swarm validator credentials"); // get the necessary values from the current db let account = marlon_node.config().get_peer_id().unwrap(); diff --git a/tools/query/Cargo.toml b/tools/query/Cargo.toml index 1d46f9288..4724b433b 100644 --- a/tools/query/Cargo.toml +++ b/tools/query/Cargo.toml @@ -21,6 +21,7 @@ indoc = { workspace = true } libra-types = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } +url = { workspace = true } [dev-dependencies] hex = { workspace = true } diff --git a/tools/query/src/query_cli.rs b/tools/query/src/query_cli.rs index 00a789fad..b4263880c 100644 --- a/tools/query/src/query_cli.rs +++ b/tools/query/src/query_cli.rs @@ -1,7 +1,14 @@ +use std::path::PathBuf; + use crate::query_type::QueryType; + use anyhow::Result; use clap::Parser; +use libra_types::{ + core_types::app_cfg::AppCfg, exports::Client, type_extensions::client_ext::ClientExt, +}; use serde_json; +use url::Url; #[derive(Parser)] #[clap(name = env!("CARGO_PKG_NAME"), author, version, about, long_about = None, arg_required_else_help = true)] @@ -10,13 +17,38 @@ pub struct QueryCli { #[clap(subcommand)] /// what to query subcommand: QueryType, + + /// optional, path to the libra cli config file + #[clap(short, long)] + pub config_path: Option, + + /// optional, URL of the upstream node to send tx to, including port + /// Otherwise will default to what is in the config file + #[clap(short, long)] + pub url: Option, } impl QueryCli { pub async fn run(&self) -> Result<()> { - // TODO: get client from configs + // Query requires a URL for upstream + // the user should set one explicitly + // Otherwise the tool will try to fetch the libra config from the + // usual location: ~/.libra + // The user can set an alternative path the the config, + // which is useful in testnets. + + // Initialize client + let client = if let Some(u) = &self.url { + Client::new(u.clone()) + } else if let Some(p) = &self.config_path { + let app_cfg = AppCfg::load(Some(p.to_owned()))?; + let (c, _) = Client::from_libra_config(&app_cfg, None).await?; + c + } else { + Client::default().await? + }; - let res = self.subcommand.query_to_json(None).await?; + let res = self.subcommand.query_to_json(&client).await?; let pretty_json = serde_json::to_string_pretty(&res)?; println!("{}", pretty_json); diff --git a/tools/query/src/query_type.rs b/tools/query/src/query_type.rs index 778c2d3db..f6645b6a7 100644 --- a/tools/query/src/query_type.rs +++ b/tools/query/src/query_type.rs @@ -128,15 +128,10 @@ pub enum QueryType { } impl QueryType { - pub async fn query_to_json(&self, client_opt: Option) -> Result { - let client = match client_opt { - Some(c) => c, - None => Client::default().await?, - }; - + pub async fn query_to_json(&self, client: &Client) -> Result { match self { QueryType::Balance { account } => { - let res = get_account_balance_libra(&client, *account).await?; + let res = get_account_balance_libra(client, *account).await?; Ok(json!(res.scaled())) } QueryType::View { @@ -145,12 +140,12 @@ impl QueryType { args, } => { let res = - get_view(&client, function_id, type_args.to_owned(), args.to_owned()).await?; + get_view(client, function_id, type_args.to_owned(), args.to_owned()).await?; let json = json!({ "body": res }); Ok(json) } QueryType::Epoch => { - let num = get_epoch(&client).await?; + let num = get_epoch(client).await?; let json = json!({ "epoch": num, }); @@ -178,7 +173,7 @@ impl QueryType { } } QueryType::ValConfig { account } => { - let res = get_val_config(&client, *account).await?; + let res = get_val_config(client, *account).await?; // make this readable, turn the network address into a string Ok(json!({ @@ -189,7 +184,7 @@ impl QueryType { })) } QueryType::BlockHeight => { - let height = get_height(&client).await?; + let height = get_height(client).await?; Ok(json!({ "BlockHeight": height })) } QueryType::Events { @@ -197,8 +192,7 @@ impl QueryType { withdrawn_or_deposited, seq_start, } => { - let res = - get_events(&client, *account, *withdrawn_or_deposited, *seq_start).await?; + let res = get_events(client, *account, *withdrawn_or_deposited, *seq_start).await?; Ok(json!({ "events": res })) } QueryType::Txs { @@ -208,7 +202,7 @@ impl QueryType { txs_type, } => { let res: Vec = get_transactions( - &client, + client, *account, *txs_height, *txs_count, @@ -228,21 +222,21 @@ impl QueryType { Ok(json!({ "transactions": prune_res })) } QueryType::ComWalletMigrated { account } => { - let res = is_community_wallet_migrated(&client, *account).await?; + let res = is_community_wallet_migrated(client, *account).await?; Ok(json!({ "migrated": res })) } QueryType::ComWalletSigners { account } => { // Wont work at the moment as there is no community wallet that with governace structure - let _res = community_wallet_signers(&client, *account).await?; + let _res = community_wallet_signers(client, *account).await?; Ok(json!({ "signers": "None"})) } QueryType::ComWalletPendTransactions { account } => { // Wont work at the moment as there is no community wallet migrated - let _res = community_wallet_scheduled_transactions(&client, *account).await?; + let _res = community_wallet_scheduled_transactions(client, *account).await?; Ok(json!({ "pending_transactions": "None" })) } QueryType::Annotate { account } => { - let dbgger = DiemDebugger::rest_client(client)?; + let dbgger = DiemDebugger::rest_client(client.clone())?; let version = dbgger.get_latest_version().await?; let blob = dbgger .annotate_account_state_at_version(account.to_owned(), version) diff --git a/tools/query/tests/query.rs b/tools/query/tests/query.rs index 7eb49b421..dee3f67bf 100644 --- a/tools/query/tests/query.rs +++ b/tools/query/tests/query.rs @@ -13,7 +13,7 @@ async fn libra_query_test() { let c = s.client(); let q = QueryType::Balance { account: val_acct }; - match q.query_to_json(Some(c.to_owned())).await { + match q.query_to_json(&c).await { Ok(v) => { println!("v: {:?}", v); let b: LibraBalanceDisplay = serde_json::from_value(v).unwrap(); @@ -38,7 +38,7 @@ async fn account_annotate_test() { let c = s.client(); let q = QueryType::Annotate { account: val_acct }; - let res = q.query_to_json(Some(c)).await.unwrap(); + let res = q.query_to_json(&c).await.unwrap(); println!("{:#}", &res.as_str().unwrap()); assert!(res.as_str().unwrap().contains("drop")); } diff --git a/tools/query/tests/view.rs b/tools/query/tests/view.rs index fae52115a..917989c8b 100644 --- a/tools/query/tests/view.rs +++ b/tools/query/tests/view.rs @@ -15,7 +15,7 @@ async fn libra_view_test() { type_args: None, args: None, }; - match q.query_to_json(Some(c.to_owned())).await { + match q.query_to_json(&c).await { Ok(v) => { println!("v: {:?}", v); } diff --git a/tools/rescue/tests/support/mod.rs b/tools/rescue/tests/support/mod.rs index 2da940e71..ca8b368c7 100644 --- a/tools/rescue/tests/support/mod.rs +++ b/tools/rescue/tests/support/mod.rs @@ -126,8 +126,7 @@ pub async fn upgrade_multiple_impl( let d = diem_temppath::TempPath::new(); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut smoke.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut smoke.swarm, 0, Some(d.path().to_owned())) .context("could not init validator config")?; // This step should fail. The view function does not yet exist in the system address. diff --git a/tools/txs/src/txs_cli.rs b/tools/txs/src/txs_cli.rs index 99b3c3783..9712783c1 100644 --- a/tools/txs/src/txs_cli.rs +++ b/tools/txs/src/txs_cli.rs @@ -26,7 +26,7 @@ pub struct TxsCli { #[clap(subcommand)] pub subcommand: Option, - /// optional, path to the config file + /// optional, path to the libra cli config file #[clap(short, long)] pub config_path: Option, @@ -138,20 +138,26 @@ pub enum TxsSub { impl TxsCli { /// Executes the transaction CLI command based on parsed arguments. pub async fn run(&self) -> Result<()> { + // Load application configuration + let app_cfg = AppCfg::load(self.config_path.clone())?; + let profile = app_cfg.get_profile(None)?; + // Determine private key based on CLI options or prompts let pri_key = if let Some(pk) = &self.test_private_key { + println!("using private key from cli args --test-private-key"); Ed25519PrivateKey::from_encoded_string(pk)? } else if let Some(m) = &self.mnemonic { + println!("using private key from cli args --mnemonic"); let legacy = get_keys_from_mnem(m.to_string())?; legacy.child_0_owner.pri_key + } else if let Ok(p) = profile.borrow_private_key() { + println!("use private key from test libra-cli-config.yaml"); + p.to_owned() } else { let legacy = get_keys_from_prompt()?; legacy.child_0_owner.pri_key }; - // Load application configuration - let app_cfg = AppCfg::load(self.config_path.clone())?; - // Determine chain ID and URL for client let chain_name = self.chain_id.unwrap_or(app_cfg.workspace.default_chain_id); let url = if let Some(u) = self.url.as_ref() { diff --git a/tools/txs/tests/community_wallet.rs b/tools/txs/tests/community_wallet.rs index cbb6c8b5a..d69201132 100644 --- a/tools/txs/tests/community_wallet.rs +++ b/tools/txs/tests/community_wallet.rs @@ -1527,8 +1527,7 @@ async fn setup_environment() -> (LibraSmoke, TempPath, AccountAddress, String, A .await .expect("Could not start libra smoke"); - configure_validator::init_val_config_files(&mut s.swarm, 0, dir.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(dir.path().to_owned())) .expect("Could not initialize validator config"); let account_address = "0x029633a96b0c0e81cc26cf2baefdbd479dab7161fbd066ca3be850012342cdee"; diff --git a/tools/txs/tests/gov_script.rs b/tools/txs/tests/gov_script.rs index ca3454670..be127587b 100644 --- a/tools/txs/tests/gov_script.rs +++ b/tools/txs/tests/gov_script.rs @@ -24,8 +24,7 @@ async fn smoke_gov_script() { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); let this_path = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap(); diff --git a/tools/txs/tests/onboard_validator.rs b/tools/txs/tests/onboard_validator.rs index 0874da43f..00f2decf5 100644 --- a/tools/txs/tests/onboard_validator.rs +++ b/tools/txs/tests/onboard_validator.rs @@ -34,8 +34,7 @@ async fn smoke_onboard_validator() -> anyhow::Result<()> { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); // 1. CREATE THE ACCOUNT diff --git a/tools/txs/tests/publish.rs b/tools/txs/tests/publish.rs index d5dbcff99..55530b34f 100644 --- a/tools/txs/tests/publish.rs +++ b/tools/txs/tests/publish.rs @@ -20,8 +20,7 @@ async fn smoke_publish() { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); // 1) the genesis validator to build and publish a fixture Move module ("tests/fixtures/test_publish"). diff --git a/tools/txs/tests/transfer.rs b/tools/txs/tests/transfer.rs index 5f6547d49..0f17fcfe1 100644 --- a/tools/txs/tests/transfer.rs +++ b/tools/txs/tests/transfer.rs @@ -22,8 +22,7 @@ async fn smoke_transfer_existing_account() { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); // let s = LibraSmoke::new(Some(2)).await.expect("can't start swarm"); @@ -62,8 +61,7 @@ async fn smoke_transfer_create_account() -> Result<(), anyhow::Error> { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); let client = s.client(); @@ -110,8 +108,7 @@ async fn smoke_transfer_estimate() { .expect("could not start libra smoke"); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .expect("could not init validator config"); // case 2. Account does not yet exist. diff --git a/types/src/core_types/app_cfg.rs b/types/src/core_types/app_cfg.rs index 567974763..5efe8a1dd 100644 --- a/types/src/core_types/app_cfg.rs +++ b/types/src/core_types/app_cfg.rs @@ -76,6 +76,7 @@ impl AppCfg { let mut default_config = AppCfg::default(); let profile = Profile::new(authkey, account); + default_config.workspace.default_profile = Some(profile.nickname.to_owned()); default_config.user_profiles = vec![profile]; default_config.workspace.node_home = config_path.unwrap_or_else(global_config_dir); @@ -138,7 +139,10 @@ impl AppCfg { let yaml = serde_yaml::to_string(&self)?; let home_path = &self.workspace.node_home.clone(); // create home path if doesn't exist, usually only in dev/ci environments. - fs::create_dir_all(home_path)?; + if !home_path.exists() { + fs::create_dir_all(home_path)?; + } + let toml_path = home_path.join(CONFIG_FILE_NAME); let mut file = fs::File::create(&toml_path)?; file.write_all(yaml.as_bytes())?; @@ -192,7 +196,7 @@ impl AppCfg { let p = self.user_profiles.get(idx).context("no profile at index")?; // The privilege to use this software depends on the user upholding a code of conduct and taking the pledge. Totally cool if you don't want to, but you'll need to write your own tools. if !p.check_has_pledge(0) { - println!("user profile has not taken 'Protect the Game' pledge, exiting."); + println!("user profile has not taken 'Protect the Game' pledge. Future releases will exit here."); } Ok(p) } @@ -383,9 +387,7 @@ pub struct Profile { pub account: AccountAddress, /// Miner Authorization Key for 0L Blockchain. Note: not the same as public key, nor account. pub auth_key: AuthenticationKey, - /// Private key only for use with testing - /// Note: skip_serializing so that it is never saved to disk. - #[serde(skip_serializing)] + /// Danger: private key only for use with testing test_private_key: Option, /// nickname for this profile pub nickname: String, @@ -399,16 +401,8 @@ pub struct Profile { pub locale: Option, /// An opportunity for the Miner to write a message on their genesis block. pub statement: String, - /// Pledges the user took pub pledges: Option>, - // NOTE: V7: deprecated - // Deprecation: : /// ip address of this node. May be different from transaction URL. - // pub ip: Ipv4Addr, - - // V7.0.3 deprecated - // Deprecation: /// Other nodes to connect for fallback connections - // pub upstream_nodes: Option>, } impl Default for Profile { diff --git a/upgrade-tests/tests/support/mod.rs b/upgrade-tests/tests/support/mod.rs index 3a82ed418..304beb0a8 100644 --- a/upgrade-tests/tests/support/mod.rs +++ b/upgrade-tests/tests/support/mod.rs @@ -25,8 +25,7 @@ pub async fn upgrade_multiple_impl( let d = diem_temppath::TempPath::new(); let (_, _app_cfg) = - configure_validator::init_val_config_files(&mut s.swarm, 0, d.path().to_owned()) - .await + configure_validator::init_val_config_files(&mut s.swarm, 0, Some(d.path().to_owned())) .context("could not init validator config")?; // This step should fail. The view function does not yet exist in the system address.