From d8d46ae83a6434860bdc65e7c2f361077e25ba76 Mon Sep 17 00:00:00 2001 From: Yotam Katznelson Date: Tue, 14 Nov 2023 00:38:40 +0000 Subject: [PATCH] [Tower] - Tower backlog, handle tower running over the limit (#97) Co-authored-by: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com> --- tools/query/src/chain_queries.rs | 16 ++++++++++++++- tools/query/src/query_type.rs | 13 +++--------- tools/tower/src/core/backlog.rs | 20 +++++++++++-------- tools/tower/src/core/next_proof.rs | 28 -------------------------- tools/tower/src/core/proof.rs | 32 ++++++++++++++++++++++++++++-- 5 files changed, 60 insertions(+), 49 deletions(-) diff --git a/tools/query/src/chain_queries.rs b/tools/query/src/chain_queries.rs index b40aaf02a..f48ea4602 100644 --- a/tools/query/src/chain_queries.rs +++ b/tools/query/src/chain_queries.rs @@ -1,10 +1,24 @@ //! chain queries -use crate::query_view; +use crate::query_view::{self, get_view}; use anyhow::Context; use diem_sdk::rest_client::{diem_api_types::ViewRequest, Client}; use libra_types::type_extensions::client_ext::entry_function_id; +pub async fn get_epoch(client: &Client) -> anyhow::Result { + let res = get_view( + client, + "0x1::reconfiguration::get_current_epoch", + None, + None, + ) + .await?; + + let value: Vec = serde_json::from_value(res)?; + let num = value.first().unwrap().parse::()?; + + Ok(num) +} /// helper to get libra balance at a SlowWalletBalance type which shows /// total balance and the unlocked balance. pub async fn get_tower_difficulty(client: &Client) -> anyhow::Result<(u64, u64)> { diff --git a/tools/query/src/query_type.rs b/tools/query/src/query_type.rs index 3ddf28f95..7d79c2f83 100644 --- a/tools/query/src/query_type.rs +++ b/tools/query/src/query_type.rs @@ -1,5 +1,6 @@ use crate::{ account_queries::{get_account_balance_libra, get_tower_state, get_val_config}, + chain_queries::get_epoch, query_view::get_view, }; use anyhow::{bail, Context, Result}; @@ -141,17 +142,9 @@ impl QueryType { Ok(json) } QueryType::Epoch => { - let res = get_view( - &client, - "0x1::reconfiguration::get_current_epoch", - None, - None, - ) - .await?; - - let num: Vec = serde_json::from_value(res)?; + let num = get_epoch(&client).await?; let json = json!({ - "epoch": num.first().unwrap().parse::()?, + "epoch": num, }); Ok(json) } diff --git a/tools/tower/src/core/backlog.rs b/tools/tower/src/core/backlog.rs index 5c9b4eb48..95105dd9d 100644 --- a/tools/tower/src/core/backlog.rs +++ b/tools/tower/src/core/backlog.rs @@ -3,7 +3,7 @@ use crate::core::{garbage_collection::gc_failed_proof, tower_error}; -use anyhow::{anyhow, bail, Error, Result}; +use anyhow::{bail, Error, Result}; use std::path::PathBuf; use libra_query::account_queries; @@ -18,9 +18,14 @@ use libra_types::{ }; const EPOCH_MINING_THRES_UPPER: u64 = 72; + +pub enum BacklogResult { + Success, + AboveLimit, +} /// Submit a backlog of blocks that may have been mined while network is offline. /// Likely not more than 1. -pub async fn process_backlog(config: &AppCfg) -> anyhow::Result<()> { +pub async fn process_backlog(config: &AppCfg) -> anyhow::Result { // Getting local state height let mut blocks_dir = config.workspace.node_home.clone(); blocks_dir.push(&config.get_block_dir(None)?); @@ -32,7 +37,8 @@ pub async fn process_backlog(config: &AppCfg) -> anyhow::Result<()> { println!("Local tower height: {:?}", current_proof_number); if current_proof_number == 0 { // if we are at genesis - return submit_or_delete(config, current_local_proof, current_block_path).await; + submit_or_delete(config, current_local_proof, current_block_path).await?; + return Ok(BacklogResult::Success); } let mut i = 0; @@ -50,12 +56,10 @@ pub async fn process_backlog(config: &AppCfg) -> anyhow::Result<()> { // use i64 for safety if proofs_in_epoch >= EPOCH_MINING_THRES_UPPER { println!( - "Backlog: Maximum number of proofs sent this epoch {}, exiting.", + "Backlog: Maximum number of proofs already sent this epoch {}", EPOCH_MINING_THRES_UPPER ); - return Err(anyhow!( - "cannot submit more proofs than allowed in epoch, aborting backlog." - )); + return Ok(BacklogResult::AboveLimit); } if proofs_in_epoch > 0 { @@ -78,7 +82,7 @@ pub async fn process_backlog(config: &AppCfg) -> anyhow::Result<()> { i += 1; submitted_now += 1; } - Ok(()) + Ok(BacklogResult::Success) } pub async fn submit_or_delete(config: &AppCfg, block: VDFProof, path: PathBuf) -> Result<()> { diff --git a/tools/tower/src/core/next_proof.rs b/tools/tower/src/core/next_proof.rs index 95dc8f941..5c4af3177 100644 --- a/tools/tower/src/core/next_proof.rs +++ b/tools/tower/src/core/next_proof.rs @@ -96,32 +96,4 @@ pub async fn get_next_proof_from_chain( }; Ok(p) - - // n.refresh_onchain_state(); - // // TODO: we are picking Client twice - // let diff = get_difficulty_from_chain(&n)?; - - // // get the user's tower state from chain. - // let ts = n.client - // .get_account_state(config.profile.account)? - // .get_miner_state()?; - - // if let Some(t) = tower_view { - // Ok() - // } else { - // bail!("cannot get tower resource for account") - // } } - -// /// Get the VDF difficulty from chain. -// pub fn get_difficulty_from_chain(n: &Node) -> anyhow::Result { - -// if let Some(a) = &n.chain_state { - -// if let Some(diff) = a.get_tower_params()? { -// return Ok(diff); -// } -// bail!("could not get this epoch's VDF params from chain.") -// } -// bail!("could not get account state for 0x0") -// } diff --git a/tools/tower/src/core/proof.rs b/tools/tower/src/core/proof.rs index fdac06d93..d7a4453e5 100644 --- a/tools/tower/src/core/proof.rs +++ b/tools/tower/src/core/proof.rs @@ -9,6 +9,7 @@ use crate::core::{ use anyhow::Error; use indicatif::ProgressBar; +use libra_query::chain_queries; use libra_types::{ exports::Client, legacy_types::app_cfg::AppCfg, type_extensions::client_ext::ClientExt, }; @@ -20,7 +21,7 @@ use libra_types::{ use std::{ fs, path::{Path, PathBuf}, - time::Instant, + time::{Duration, Instant}, }; // writes a JSON file with the first vdf proof @@ -111,7 +112,32 @@ pub async fn mine_and_submit( get_next_and_mine(config, &client, local_mode).await?; // submits backlog to client match backlog::process_backlog(config).await { - Ok(()) => println!("Success: Proof committed to chain"), + Ok(BacklogResult::Success) => { + println!("Success: Proof committed to chain"); + } + Ok(BacklogResult::AboveLimit) => { + // Speed demon, you're the very same one + // Who said the future's in your hands + // The life you save could be your own + // You're preachin' 'bout my life like you're the law + // Gonna live each day and hour like + // For me there's no tomorrow + println!( + "Speed demon, let's hang out here until the next epoch. Exit with ctrl+c." + ); + + // check the current epoch every 5 minutes. + // When we get to next epoch + let full_epoch = chain_queries::get_epoch(&client).await?; + let mut next_epoch = full_epoch; + while full_epoch >= next_epoch { + // in case next epoch returns 0 + let lets_wait = Duration::from_secs(5 * 60); // 5 mins + std::thread::sleep(lets_wait); + next_epoch = chain_queries::get_epoch(&client).await.unwrap_or(0); + // don't fail on intermittent API + } + } Err(e) => { // don't stop on tx errors println!("ERROR: Failed processing backlog, message: {:?}", e); @@ -221,6 +247,8 @@ use diem_temppath::TempPath; #[cfg(test)] use libra_types::legacy_types::vdf_difficulty::VDFDifficulty; +use super::backlog::BacklogResult; + #[test] fn test_mine_once() { // if no file is found, the block height is 0