From c3b7c820fede48ef948fb6b54a0905d3459ec973 Mon Sep 17 00:00:00 2001 From: lpgeiger <1364012+lpgeiger@users.noreply.github.com> Date: Mon, 7 Jun 2021 10:04:46 -0400 Subject: [PATCH] Autopay text (#551) * patch paths on github actions * fix text output of autopay instructions --- .github/workflows/integration.yaml | 34 +++++- ol/cli/src/cache.rs | 2 +- ol/cli/src/explorer/app.rs | 6 +- .../src/node/{chain_info.rs => chain_view.rs} | 0 ol/cli/src/node/mod.rs | 2 +- ol/cli/src/node/node.rs | 14 ++- .../alice.fixed_once.autopay_batch.json | 12 ++ ol/integration-tests/test-autopay.mk | 112 ++++++++++++++++++ ol/{util => integration-tests}/test-mining.mk | 2 +- .../test-upgrade.mk | 2 +- ol/txs/src/commands/autopay_batch_cmd.rs | 47 +------- ol/txs/src/commands/create_validator_cmd.rs | 44 ++++--- ol/types/src/autopay.rs | 58 +++++++++ 13 files changed, 255 insertions(+), 80 deletions(-) rename ol/cli/src/node/{chain_info.rs => chain_view.rs} (100%) create mode 100644 ol/fixtures/autopay/alice.fixed_once.autopay_batch.json create mode 100644 ol/integration-tests/test-autopay.mk rename ol/{util => integration-tests}/test-mining.mk (97%) rename ol/{util => integration-tests}/test-upgrade.mk (97%) diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index adea8deb8d..a843739a11 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -29,8 +29,34 @@ jobs: run: sudo apt-get install -y lld - name: Check branch run: echo "${{ steps.branch-name.outputs.current_branch }}" - - name: Swarm upgrade test - run: RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/util/test-mining.mk test + - name: Swarm mining test + run: RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/integration-tests/test-mining.mk test + autopay: + name: Autopay + runs-on: self-hosted + timeout-minutes: 45 + env: + NODE_ENV: test + TEST: y + steps: + - uses: actions/checkout@v2 + - name: Get branch names + id: branch-name + uses: tj-actions/branch-names@v4 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.46.0 + override: true + components: rustfmt, clippy + - name: Install deps + run: sudo apt-get install -y lld + - name: Check branch + run: echo "${{ steps.branch-name.outputs.current_branch }}" + - name: Swarm autopay percent-change + run: RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/integration-tests/test-autopay.mk test-percent-change + - name: Swarm autopay fixed-once + run: RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/integration-tests/test-autopay.mk test-fixed-once upgrade: name: Stdlib Upgrade runs-on: self-hosted @@ -53,6 +79,6 @@ jobs: - name: File permissions run: sudo chmod -R 777 language/stdlib/ - name: Swarm upgrade test - run: BRANCH_NAME=${{ steps.branch-name.outputs.current_branch }} RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/util/test-upgrade.mk test + run: BRANCH_NAME=${{ steps.branch-name.outputs.current_branch }} RUSTC_WRAPPER=sccache SOURCE_PATH=./ make -f ol/integration-tests/test-upgrade.mk test + - \ No newline at end of file diff --git a/ol/cli/src/cache.rs b/ol/cli/src/cache.rs index 386af2639b..e55adbb695 100644 --- a/ol/cli/src/cache.rs +++ b/ol/cli/src/cache.rs @@ -2,7 +2,7 @@ use crate::{ check::items::Items, mgmt::management::HostProcess, - node::{account::OwnerAccountView, chain_info::ChainView, states::HostState}, + node::{account::OwnerAccountView, chain_view::ChainView, states::HostState}, }; use anyhow::Error; use serde::{Deserialize, Serialize}; diff --git a/ol/cli/src/explorer/app.rs b/ol/cli/src/explorer/app.rs index af769443a3..35589cf2b6 100644 --- a/ol/cli/src/explorer/app.rs +++ b/ol/cli/src/explorer/app.rs @@ -1,6 +1,6 @@ #[allow(missing_docs)] -use crate::node::chain_info; +use crate::node::chain_view; use crate::node::node::Node; use super::TabsState; use libra_json_rpc_client::views::TransactionView; @@ -60,9 +60,9 @@ pub struct App<'a> { /// caches for account state pub account_state: Option, /// caches for chain state - pub chain_state: Option, + pub chain_state: Option, /// caches for validator list - pub validators: Vec, + pub validators: Vec, /// latest fetched tx version pub last_fetch_tx_version: u64, /// transaction list diff --git a/ol/cli/src/node/chain_info.rs b/ol/cli/src/node/chain_view.rs similarity index 100% rename from ol/cli/src/node/chain_info.rs rename to ol/cli/src/node/chain_view.rs diff --git a/ol/cli/src/node/mod.rs b/ol/cli/src/node/mod.rs index 91b6dc75ec..21a1339d57 100644 --- a/ol/cli/src/node/mod.rs +++ b/ol/cli/src/node/mod.rs @@ -1,7 +1,7 @@ //! `node` state of the host, account, node, and miner pub mod node; pub mod account; -pub mod chain_info; +pub mod chain_view; pub mod query; pub mod sync; pub mod client; diff --git a/ol/cli/src/node/node.rs b/ol/cli/src/node/node.rs index f70638c956..5124ebd933 100644 --- a/ol/cli/src/node/node.rs +++ b/ol/cli/src/node/node.rs @@ -12,6 +12,7 @@ use libra_json_rpc_client::views::{MinerStateResourceView}; use libra_types::waypoint::Waypoint; use libra_types::{account_address::AccountAddress, account_state::AccountState}; use storage_interface::DbReader; +use super::client; use super::{account::OwnerAccountView, states::HostState}; /// name of key in kv store for sync @@ -72,6 +73,14 @@ impl Node { }; } + /// default node connection from configs + pub fn default_from_cfg(mut cfg: AppCfg) -> Node { + // NOTE: not intended for swarm. + let client = client::pick_client(None, &mut cfg).unwrap(); + Node::new(client, cfg, false) + } + + /// refresh all checks pub fn refresh_checks(&mut self) -> &mut Self { self.vitals.items.configs_exist = self.configs_exist(); @@ -146,11 +155,6 @@ impl Node { } } - /// is validator jailed - pub fn is_jailed() -> bool { - unimplemented!("Don't know how to implement") - } - /// Is current account in validator set pub fn is_in_validator_set(&self) -> bool { match &self.chain_state { diff --git a/ol/fixtures/autopay/alice.fixed_once.autopay_batch.json b/ol/fixtures/autopay/alice.fixed_once.autopay_batch.json new file mode 100644 index 0000000000..22ebe7d377 --- /dev/null +++ b/ol/fixtures/autopay/alice.fixed_once.autopay_batch.json @@ -0,0 +1,12 @@ +{ + "autopay_instructions": [ + { + "note": "test balance", + "uid": 0, + "destination": "88E74DFED34420F2AD8032148280A84B", + "type_of": "FixedOnce", + "value": 1, + "duration_epochs": 1 + } + ] +} \ No newline at end of file diff --git a/ol/integration-tests/test-autopay.mk b/ol/integration-tests/test-autopay.mk new file mode 100644 index 0000000000..407841fe66 --- /dev/null +++ b/ol/integration-tests/test-autopay.mk @@ -0,0 +1,112 @@ +SHELL=/usr/bin/env bash +DATA_PATH = ${HOME}/.0L +SWARM_TEMP = ${DATA_PATH}/swarm_temp +LOG=${DATA_PATH}/test-mining.log +UNAME := $(shell uname) + +NODE_ENV=test +TEST=y + +ifndef SOURCE_PATH +SOURCE_PATH = ${HOME}/libra +endif +MAKE_FILE = ${SOURCE_PATH}/ol/integration-tests/test-autopay.mk + +# alice +ifndef PERSONA +PERSONA=alice +endif + +MNEM="talent sunset lizard pill fame nuclear spy noodle basket okay critic grow sleep legend hurry pitch blanket clerk impose rough degree sock insane purse" + +NUM_NODES = 2 + +START_TEXT = "To run the Libra CLI client" +SUCCESS_TEXT = "transaction executed" + +ifndef AUTOPAY_FILE +AUTOPAY_FILE = alice.autopay_batch.json +endif + +test: swarm check-swarm send-tx check-tx check-autopay check-transfer stop + +test-percent-change: + AUTOPAY_FILE=alice.autopay_batch.json make -f ${MAKE_FILE} test + +test-fixed-once: + AUTOPAY_FILE=alice.fixed_once.autopay_batch.json make -f ${MAKE_FILE} test + +swarm: + @echo Building Swarm + rm -rf ${SWARM_TEMP} + mkdir ${SWARM_TEMP} + cd ${SOURCE_PATH} && cargo build -p libra-node -p cli + cd ${SOURCE_PATH} && cargo run -p libra-swarm -- --libra-node ${SOURCE_PATH}/target/debug/libra-node -c ${SWARM_TEMP} -n ${NUM_NODES} &> ${LOG} & + +stop: + killall libra-swarm libra-node miner ol | true + +echo: + @echo hi &> ${LOG} & + +init: + cd ${SOURCE_PATH} && cargo r -p ol -- --swarm-path ${SWARM_TEMP} --swarm-persona ${PERSONA} init --source-path ${SOURCE_PATH} + +tx: + cd ${SOURCE_PATH} && NODE_ENV=test TEST=y cargo r -p txs -- --swarm-path ${SWARM_TEMP} --swarm-persona ${PERSONA} autopay-batch -f ${SOURCE_PATH}/ol/fixtures/autopay/${AUTOPAY_FILE} + +resources: + cd ${SOURCE_PATH} && cargo run -p ol -- --swarm-path ${SWARM_TEMP} --swarm-persona ${PERSONA} query --resources + +balance: + cd ${SOURCE_PATH} && cargo run -p ol -- --swarm-path ${SWARM_TEMP} --swarm-persona ${PERSONA} query --balance + +balance-bob: + cd ${SOURCE_PATH} && cargo run -p ol -- --account 88E74DFED34420F2AD8032148280A84B --swarm-path ${SWARM_TEMP} --swarm-persona ${PERSONA} query --balance + + +check-swarm: + @while [[ ${NOW} -le ${END} ]] ; do \ + if grep -q ${START_TEXT} ${LOG} ; then \ + break; \ + else \ + echo . ; \ + fi ; \ + echo "Sleeping for 5 secs" ; \ + sleep 5 ; \ + done + +send-tx: + PERSONA=alice make -f ${MAKE_FILE} init + PERSONA=alice make -f ${MAKE_FILE} tx &>> ${LOG} & + +check-tx: + @while [[ ${NOW} -le ${END} ]] ; do \ + if grep -q ${SUCCESS_TEXT} ${LOG} ; then \ + echo TX SUCCESS ; \ + break ; \ + else \ + echo . ; \ + fi ; \ + echo "Sleeping for 5 secs" ; \ + sleep 5 ; \ + done + +check-autopay: +# checks if there is any mention of BOB's account as a payee + PERSONA=alice make -f ${MAKE_FILE} resources | grep -e '88E74DFED34420F2AD8032148280A84B' -e 'payee' + + +check-transfer: +# swarm accounts start with a balance of 4 + @while [[ ${NOW} -le ${END} ]] ; do \ + if PERSONA=alice make -f ${MAKE_FILE} balance-bob | grep -e '5'; then \ + echo TX SUCCESS ; \ + break ; \ + else \ + echo . ; \ + fi ; \ + echo "Sleeping for 5 secs" ; \ + sleep 5 ; \ + done + \ No newline at end of file diff --git a/ol/util/test-mining.mk b/ol/integration-tests/test-mining.mk similarity index 97% rename from ol/util/test-mining.mk rename to ol/integration-tests/test-mining.mk index 79e851fe03..5ede3b826e 100644 --- a/ol/util/test-mining.mk +++ b/ol/integration-tests/test-mining.mk @@ -10,7 +10,7 @@ TEST=y ifndef SOURCE_PATH SOURCE_PATH = ${HOME}/libra endif -MAKE_FILE = ${SOURCE_PATH}/ol/util/test-mining.mk +MAKE_FILE = ${SOURCE_PATH}/ol/integration-tests/test-mining.mk # alice ifndef PERSONA diff --git a/ol/util/test-upgrade.mk b/ol/integration-tests/test-upgrade.mk similarity index 97% rename from ol/util/test-upgrade.mk rename to ol/integration-tests/test-upgrade.mk index 6367184975..730a6ca64f 100644 --- a/ol/util/test-upgrade.mk +++ b/ol/integration-tests/test-upgrade.mk @@ -46,7 +46,7 @@ prep: # save makefile outside of repo, since we'll need it across branches # mkdir ${HOME}/.0L/ | true mkdir -p ${UPGRADE_TEMP} | true - cp ${SOURCE_PATH}/ol/util/test-upgrade.mk ${SAFE_MAKE_FILE} + cp ${SOURCE_PATH}/ol/integration-tests/test-upgrade.mk ${SAFE_MAKE_FILE} get-prev: cd ${SOURCE_PATH} && git reset --hard && git fetch diff --git a/ol/txs/src/commands/autopay_batch_cmd.rs b/ol/txs/src/commands/autopay_batch_cmd.rs index e8911faa23..701c44efd0 100644 --- a/ol/txs/src/commands/autopay_batch_cmd.rs +++ b/ol/txs/src/commands/autopay_batch_cmd.rs @@ -39,52 +39,7 @@ pub fn process_instructions(instructions: Vec, starting_epoch: & instructions.into_iter().filter_map(|i| { assert!(i.type_move.unwrap() <= 3); - let warning = if i.type_move.unwrap() == 0 { - format!( - "Instruction {uid}: {note}\nSend {percent_balance:.2?}% of your total balance every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", - uid = &i.uid, - percent_balance = *&i.value_move.unwrap() as f64 /100f64, - count_epochs = &i.duration_epochs.unwrap_or_else(|| { - &i.end_epoch.unwrap() - starting_epoch - }), - note = &i.note.clone().unwrap(), - epoch_ending = &i.end_epoch.unwrap(), - destination = &i.destination, - ) - } else if i.type_move.unwrap() == 1 { - format!( - "Instruction {uid}: {note}\nSend {percent_balance:.2?}% new incoming funds every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", - uid = &i.uid, - percent_balance = *&i.value_move.unwrap() as f64 /100f64, - count_epochs = &i.duration_epochs.unwrap_or_else(|| { - &i.end_epoch.unwrap() - starting_epoch - }), - note = &i.note.clone().unwrap(), - epoch_ending = &i.end_epoch.unwrap(), - destination = &i.destination, - ) - } else if i.type_move.unwrap() == 2 { - format!( - "Instruction {uid}: {note}\nSend {total_val} every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", - uid = &i.uid, - total_val = *&i.value_move.unwrap() / 1_000_000, // scaling factor - count_epochs = &i.duration_epochs.unwrap_or_else(|| { - &i.end_epoch.unwrap() - starting_epoch - }), - note = &i.note.clone().unwrap(), - epoch_ending = &i.end_epoch.unwrap(), - destination = &i.destination, - ) - } else { - format!( - "Instruction {uid}: {note}\nSend {total_val} once to address: {destination}?", - uid = &i.uid, - note = &i.note.clone().unwrap(), - total_val = *&i.value_move.unwrap() / 1_000_000, // scaling factor - destination = &i.destination, - ) - }; - println!("{}", &warning); + println!("{}", i.text_instructions(starting_epoch)); // accept if CI mode. if *IS_CI { return Some(i) } diff --git a/ol/txs/src/commands/create_validator_cmd.rs b/ol/txs/src/commands/create_validator_cmd.rs index 99825b83ff..d1e516b0ae 100644 --- a/ol/txs/src/commands/create_validator_cmd.rs +++ b/ol/txs/src/commands/create_validator_cmd.rs @@ -9,14 +9,12 @@ use crate::{ submit_tx::{tx_params_wrapper, maybe_submit}, }; use abscissa_core::{Command, Options, Runnable}; +use dialoguer::Confirm; use libra_types::transaction::Script; +use ol::node::node::Node; use ol_types::{account::ValConfigs, config::TxType}; use reqwest::Url; -use std::{ - fs::{self, File}, - io::Write, - path::PathBuf, -}; +use std::{fs::{self, File}, io::Write, path::PathBuf, process::exit}; /// `CreateAccount` subcommand #[derive(Command, Debug, Options)] pub struct CreateValidatorCmd { @@ -28,9 +26,6 @@ pub struct CreateValidatorCmd { /// create validator account by submitting transaction on chain pub fn create_validator_script(new_account: &ValConfigs) -> Script { - // let file_two = fs::File::open(account_json_path).expect("file should open read only"); - // let account: ValConfigs = - // serde_json::from_reader(file_two).expect("file should be proper JSON"); let new_account = new_account.to_owned(); new_account.check_autopay().unwrap(); @@ -64,7 +59,7 @@ pub fn account_from_url(url: &mut Url, path: &PathBuf) -> PathBuf { impl Runnable for CreateValidatorCmd { fn run(&self) { - let cfg = app_config(); + let cfg = app_config().clone(); let entry_args = entrypoint::get_args(); let tmp; if self.account_file.is_none() && self.url.is_none() { @@ -83,6 +78,15 @@ impl Runnable for CreateValidatorCmd { let file = fs::File::open(account_json_path).expect("file should open read only"); let new_account: ValConfigs = serde_json::from_reader(file).expect("file should be proper JSON"); + + let node = Node::default_from_cfg(cfg); + let epoch_now = match node.vitals.chain_view { + Some(c) => c.epoch, + None => { + println!("Could not connect to chain to fetch epoch. Exiting"); + exit(1); + }, + }; match new_account.check_autopay() { Ok(_) => { @@ -95,9 +99,19 @@ impl Runnable for CreateValidatorCmd { .unwrap(); // submit autopay if there are any - if let Some(signed_autopay_batch) = new_account.autopay_signed { - relay::relay_batch(&signed_autopay_batch, &tx_params).unwrap(); - } + new_account.autopay_instructions.unwrap() + .into_iter() + .for_each(|i|{ + println!("{}", i.text_instructions(&epoch_now)); + match Confirm::new().with_prompt("").interact().unwrap() { + true => {}, + _ => { + panic!("Autopay configuration aborted. Check batch configuration file or template"); + } + } + }); + + relay::relay_batch(&new_account.autopay_signed.unwrap(), &tx_params).unwrap(); } Err(_) => { println!( @@ -107,9 +121,3 @@ impl Runnable for CreateValidatorCmd { } } } - -// #[test] -// fn test_create_val() { -// let path = ol_fixtures::get_persona_account_json("alice").1; -// create_validator_script(&path); -// } diff --git a/ol/types/src/autopay.rs b/ol/types/src/autopay.rs index f199dc7efc..e60e2ee7b6 100644 --- a/ol/types/src/autopay.rs +++ b/ol/types/src/autopay.rs @@ -166,6 +166,60 @@ impl PayInstruction { ); Ok(()) } + + /// provide text information on the instruction + pub fn text_instructions(&self, starting_epoch: &u64) -> String { + match self.type_of { + InstructionType::PercentOfBalance => { + format!( + "Instruction {uid}: {note}\nSend {percent_balance:.2?}% of your total balance every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", + uid = &self.uid, + percent_balance = *&self.value_move.unwrap() as f64 /100f64, + count_epochs = &self.duration_epochs.unwrap_or_else(|| { + &self.end_epoch.unwrap() - starting_epoch + }), + note = &self.note.clone().unwrap(), + epoch_ending = &self.end_epoch.unwrap(), + destination = &self.destination, + ) + }, + InstructionType::PercentOfChange => { + format!( + "Instruction {uid}: {note}\nSend {percent_balance:.2?}% new incoming funds every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", + uid = &self.uid, + percent_balance = *&self.value_move.unwrap() as f64 /100f64, + count_epochs = &self.duration_epochs.unwrap_or_else(|| { + &self.end_epoch.unwrap() - starting_epoch + }), + note = &self.note.clone().unwrap(), + epoch_ending = &self.end_epoch.unwrap(), + destination = &self.destination, + ) + }, + InstructionType::FixedRecurring => { + format!( + "Instruction {uid}: {note}\nSend {total_val} every day {count_epochs} times (until epoch {epoch_ending}) to address: {destination}?", + uid = &self.uid, + total_val = *&self.value_move.unwrap() / 1_000_000, // scaling factor + count_epochs = &self.duration_epochs.unwrap_or_else(|| { + &self.end_epoch.unwrap() - starting_epoch + }), + note = &self.note.clone().unwrap(), + epoch_ending = &self.end_epoch.unwrap(), + destination = &self.destination, + ) + }, + InstructionType::FixedOnce => { + format!( + "Instruction {uid}: {note}\nSend {total_val} once to address: {destination}?", + uid = &self.uid, + note = &self.note.clone().unwrap(), + total_val = *&self.value_move.unwrap() / 1_000_000, // scaling factor + destination = &self.destination, + ) + } + } + } } /// save a batch file of instructions @@ -211,6 +265,10 @@ fn scale_percent(fract_percent: f64) -> Option { } } + + + + #[test] fn parse_file() { let path = ol_fixtures::get_demo_autopay_json().1;