From 87ee970817f16e744e7bd76c1aeb257a4ef18272 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli Date: Mon, 21 Oct 2024 17:50:41 +0200 Subject: [PATCH 1/2] add redelgate batch --- src/checks/balance.rs | 2 +- src/checks/bonds.rs | 2 +- src/gen/main.rs | 6 +- src/gen/state.rs | 10 +- src/gen/step.rs | 42 ++- src/gen/steps/mod.rs | 1 + src/gen/steps/redelegate.rs | 2 +- src/gen/steps/redelegate_batch.rs | 85 ++++++ src/queries/account.rs | 2 +- src/queries/balance.rs | 2 +- src/queries/proposals.rs | 2 +- src/queries/validators.rs | 2 +- src/scenario.rs | 15 ++ src/sdk/namada.rs | 2 +- src/tasks/bond_batch.rs | 8 +- src/tasks/mod.rs | 1 + src/tasks/redelegate.rs | 24 +- src/tasks/redelegate_batch.rs | 341 ++++++++++++++++++++++++ src/tasks/transparent_transfer_batch.rs | 8 +- src/waits/epoch.rs | 2 +- src/waits/height.rs | 2 +- 21 files changed, 520 insertions(+), 41 deletions(-) create mode 100644 src/gen/steps/redelegate_batch.rs create mode 100644 src/tasks/redelegate_batch.rs diff --git a/src/checks/balance.rs b/src/checks/balance.rs index 6b22dee..6f71a06 100644 --- a/src/checks/balance.rs +++ b/src/checks/balance.rs @@ -2,8 +2,8 @@ use std::str::FromStr; use async_trait::async_trait; +use namada_sdk::rpc; use namada_sdk::token::Amount; -use namada_sdk::{rpc}; use serde::{Deserialize, Serialize}; use crate::entity::address::{AccountIndentifier, ADDRESS_PREFIX}; diff --git a/src/checks/bonds.rs b/src/checks/bonds.rs index d178ef2..02a4044 100644 --- a/src/checks/bonds.rs +++ b/src/checks/bonds.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use crate::entity::address::{AccountIndentifier, ADDRESS_PREFIX}; diff --git a/src/gen/main.rs b/src/gen/main.rs index 7121338..4f2b73b 100644 --- a/src/gen/main.rs +++ b/src/gen/main.rs @@ -88,7 +88,7 @@ struct Args { withdraw: u64, #[arg(long, default_value_t = 0)] vote_proposal: u64, - #[arg(long, default_value_t = 4)] + #[arg(long, default_value_t = 0)] redelegate: u64, #[arg(long, default_value_t = 0)] init_default_proposal: u64, @@ -110,6 +110,8 @@ struct Args { transparent_transfer_batch: u64, #[arg(long, default_value_t = 6)] bond_batch: u64, + #[arg(long, default_value_t = 6)] + redelegate_batch: u64, } fn main() { @@ -165,6 +167,7 @@ fn main() { args.transparent_transfer_batch.into(), ), (TaskType::BondBatch, args.bond_batch.into()), + (TaskType::RedelegateBatch, args.redelegate_batch.into()), ]); let mut scenario_builder = ScenarioBuilder::new( @@ -190,7 +193,6 @@ fn main() { #[cfg(test)] mod test { - use super::*; diff --git a/src/gen/state.rs b/src/gen/state.rs index 9566e9d..ab77a5c 100644 --- a/src/gen/state.rs +++ b/src/gen/state.rs @@ -95,7 +95,7 @@ impl State { if alias.to_string().ends_with("-pa") { return acc; } - if blacklist.contains(&alias) { + if blacklist.contains(alias) { return acc; } if let Some(balance) = token_balances.get(&Alias::native_token()) { @@ -414,9 +414,9 @@ impl State { return acc; } if alias.to_string().contains("-enst") { - return acc + return acc; } - if blacklist.contains(&alias) { + if blacklist.contains(alias) { return acc; } if let Some(balance) = token_balances.get(&Alias::native_token()) { @@ -436,8 +436,8 @@ impl State { amount: u64, blacklist: Vec, ) -> Account { - let all_implicit_addresses_with_native_token_balance = - self.implicit_addresses_with_at_least_native_token_balance_and_blacklist(amount, blacklist); + let all_implicit_addresses_with_native_token_balance = self + .implicit_addresses_with_at_least_native_token_balance_and_blacklist(amount, blacklist); all_implicit_addresses_with_native_token_balance .choose(&mut rand::thread_rng()) .unwrap() diff --git a/src/gen/step.rs b/src/gen/step.rs index dfb438a..903b878 100644 --- a/src/gen/step.rs +++ b/src/gen/step.rs @@ -14,7 +14,8 @@ use crate::{ init_default_proposal::InitDefaultProposalBuilder, init_funding_proposal::InitPgfFundingProposalBuilder, init_steward_proposal::InitPgfStewardProposalBuilder, new_wallet_key::NewWalletStepBuilder, - redelegate::RedelegateBuilder, shielding_transfer::ShieldingTransferBuilder, + redelegate::RedelegateBuilder, redelegate_batch::RedelegateBatchBuilder, + shielding_transfer::ShieldingTransferBuilder, transparent_transfer::TransparentTransferBuilder, transparent_transfer_batch::TransparentTransferBatchBuilder, unbond::UnbondBuilder, unshielding_transfer::UnshieldingTransferBuilder, update_account::UpdateAccountBuilder, @@ -53,6 +54,7 @@ pub enum TaskType { ClaimRewards, TransparentTransferBatch, BondBatch, + RedelegateBatch, } impl TaskType { @@ -187,6 +189,13 @@ impl TaskType { .len() > 2 } + TaskType::RedelegateBatch => { + !state.any_bond().is_empty() + && !state.any_active_validator_address().is_empty() + && !state + .implicit_addresses_with_at_least_native_token_balance(MIN_FEE * 6) + .is_empty() + } } } @@ -834,6 +843,37 @@ impl TaskType { Box::new(step) } + TaskType::RedelegateBatch => { + let total_batched_txs = utils::random_between(2, 4); + + let bond = state.random_bond(); + let account = state.get_account_from_alias(&bond.source); + let bond_amount = bond.amount; + + let gas_payer = state + .random_implicit_account_with_at_least_native_token_balance(MIN_FEE * 6) + .alias; + + let tx_settings = TxSettings { + signers: account.implicit_addresses, + broadcast_only: false, + gas_limit: MIN_FEE * 6, + gas_payer, + }; + + let step = RedelegateBatchBuilder::default() + .sources(vec![bond.source; total_batched_txs as usize]) + .source_validators(vec![bond.step_id; total_batched_txs as usize]) + .amounts(vec![ + bond_amount / 2 / total_batched_txs; + total_batched_txs as usize + ]) + .tx_settings(tx_settings) + .build() + .unwrap(); + + Box::new(step) + } } } } diff --git a/src/gen/steps/mod.rs b/src/gen/steps/mod.rs index 3b785b3..e38415c 100644 --- a/src/gen/steps/mod.rs +++ b/src/gen/steps/mod.rs @@ -12,6 +12,7 @@ pub mod init_funding_proposal; pub mod init_steward_proposal; pub mod new_wallet_key; pub mod redelegate; +pub mod redelegate_batch; pub mod shielding_transfer; pub mod transparent_transfer; pub mod transparent_transfer_batch; diff --git a/src/gen/steps/redelegate.rs b/src/gen/steps/redelegate.rs index 438eb1e..01c6695 100644 --- a/src/gen/steps/redelegate.rs +++ b/src/gen/steps/redelegate.rs @@ -27,7 +27,7 @@ impl Step for Redelegate { source: Value::v(self.source.to_string()), src_validator: Value::r(self.source_validator, "validator-0-address".to_string()), dest_validator: Value::f(Some(step_index - 1)), - amount: Value::r(self.source_validator, "amount-0".to_string()), + amount: Value::v(self.amount.to_string()), // amount: Value::r(self.source_validator, "amount-0".to_string()), }, settings: Some(self.tx_settings.clone().into()), } diff --git a/src/gen/steps/redelegate_batch.rs b/src/gen/steps/redelegate_batch.rs new file mode 100644 index 0000000..d933909 --- /dev/null +++ b/src/gen/steps/redelegate_batch.rs @@ -0,0 +1,85 @@ +use std::fmt::Display; + +use derive_builder::Builder; +use namada_scenario_tester::{ + scenario::StepType, tasks::redelegate_batch::TxRedelegateBatchParametersDto, + utils::value::Value, +}; + +use crate::{ + entity::{Alias, TxSettings}, + hooks::{check_step::CheckStep, query_validators::QueryValidatorSet}, + state::State, + step::Step, +}; + +#[derive(Clone, Debug, PartialEq, Eq, Builder)] +pub struct RedelegateBatch { + pub sources: Vec, + pub source_validators: Vec, // step id of a bond step + pub amounts: Vec, + pub tx_settings: TxSettings, +} + +impl Step for RedelegateBatch { + fn to_step_type(&self, step_index: u64) -> StepType { + StepType::RedelegateBatch { + parameters: TxRedelegateBatchParametersDto { + sources: self + .sources + .iter() + .map(|source| Value::v(source.to_string())) + .collect(), + src_validators: self + .source_validators + .iter() + .map(|source| Value::r(*source, "validator-0-address".to_string())) + .collect(), + dest_validators: self + .sources + .iter() + .map(|_| Value::f(Some(step_index - 1))) + .collect(), + amounts: self + .amounts + .iter() + .map(|amount| Value::v(amount.to_string())) + .collect(), + }, + settings: Some(self.tx_settings.clone().into()), + } + } + + fn update_state(&self, state: &mut crate::state::State) { + for idx in 0..self.sources.len() { + state.insert_redelegation_and_update_bonds( + &self.sources[idx], + self.source_validators[idx], + self.amounts[idx], + ); + } + state.decrease_account_fees(&self.tx_settings); + } + + fn post_hooks(&self, step_index: u64, _state: &State) -> Vec> { + vec![Box::new(CheckStep::new(step_index))] + } + + fn pre_hooks(&self, _state: &State) -> Vec> { + vec![Box::new(QueryValidatorSet::new())] + } + + fn total_post_hooks(&self) -> u64 { + 1 + } + + fn total_pre_hooks(&self) -> u64 { + 1 + } +} + +impl Display for RedelegateBatch { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "bond batch of size {}", self.sources.len()) + } +} diff --git a/src/queries/account.rs b/src/queries/account.rs index 2d13827..8453196 100644 --- a/src/queries/account.rs +++ b/src/queries/account.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use crate::{ diff --git a/src/queries/balance.rs b/src/queries/balance.rs index 0eb2540..5e65588 100644 --- a/src/queries/balance.rs +++ b/src/queries/balance.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use crate::{ diff --git a/src/queries/proposals.rs b/src/queries/proposals.rs index ea53eca..b67ba15 100644 --- a/src/queries/proposals.rs +++ b/src/queries/proposals.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use crate::{ diff --git a/src/queries/validators.rs b/src/queries/validators.rs index 3410ff6..ad64bdb 100644 --- a/src/queries/validators.rs +++ b/src/queries/validators.rs @@ -2,7 +2,7 @@ use std::collections::BTreeSet; use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use crate::{ diff --git a/src/scenario.rs b/src/scenario.rs index ffc3a2b..f97fd10 100644 --- a/src/scenario.rs +++ b/src/scenario.rs @@ -40,6 +40,7 @@ use crate::{ }, reactivate_validator::{ReactivateValidatorParametersDto, TxReactivateValidator}, redelegate::{TxRedelegate, TxRedelegateParametersDto}, + redelegate_batch::{TxRedelegateBatch, TxRedelegateBatchParametersDto}, reveal_pk::{RevealPkParametersDto, TxRevealPk}, shielded_sync::{ShieldedSync, ShieldedSyncParametersDto}, transparent_transfer_batch::{ @@ -233,6 +234,11 @@ pub enum StepType { parameters: TxBondBatchParametersDto, settings: Option, }, + #[serde(rename = "tx-redelegate-batch")] + RedelegateBatch { + parameters: TxRedelegateBatchParametersDto, + settings: Option, + }, } impl Display for StepType { @@ -276,6 +282,7 @@ impl Display for StepType { StepType::CheckRevealPk { .. } => write!(f, "check-reveal-pk"), StepType::TransparentTransferBatch { .. } => write!(f, "transparent-transfer-batch"), StepType::BondBatch { .. } => write!(f, "bond-batch"), + StepType::RedelegateBatch { .. } => write!(f, "redelegate-batch"), } } } @@ -523,6 +530,14 @@ impl Step { .run(sdk, parameters, settings, storage) .await } + StepType::RedelegateBatch { + parameters, + settings, + } => { + TxRedelegateBatch::default() + .run(sdk, parameters, settings, storage) + .await + } } } } diff --git a/src/sdk/namada.rs b/src/sdk/namada.rs index 871262a..b2e479b 100644 --- a/src/sdk/namada.rs +++ b/src/sdk/namada.rs @@ -6,7 +6,7 @@ use namada_sdk::{ chain::ChainId, io::NullIo, key::common::{PublicKey, SecretKey}, - masp::{fs::FsShieldedUtils}, + masp::fs::FsShieldedUtils, rpc, wallet::{fs::FsWalletUtils, Wallet}, Namada, NamadaImpl, ShieldedWallet, diff --git a/src/tasks/bond_batch.rs b/src/tasks/bond_batch.rs index 6fbd593..424935d 100644 --- a/src/tasks/bond_batch.rs +++ b/src/tasks/bond_batch.rs @@ -33,7 +33,9 @@ impl ToString for TxBondBatchStorageKeys { fn to_string(&self) -> String { match self { TxBondBatchStorageKeys::SourceAddress(entry) => format!("source-{}-address", entry), - TxBondBatchStorageKeys::ValidatorAddress(entry) => format!("validator-{}-address", entry), + TxBondBatchStorageKeys::ValidatorAddress(entry) => { + format!("validator-{}-address", entry) + } TxBondBatchStorageKeys::Amount(entry) => format!("amount-{}", entry), TxBondBatchStorageKeys::BatchSize => "batch-size".to_string(), TxBondBatchStorageKeys::AtomicBatch => "batch-atomic".to_string(), @@ -110,6 +112,10 @@ impl Task for TxBondBatch { .filter_map(|res| res.ok()) .collect::>(); + if txs.is_empty() { + return Ok(StepResult::no_op()); + } + let tx_args = Self::default_tx_arg(sdk).await; let gas_payer = settings.clone().gas_payer.unwrap().to_public_key(sdk).await; let tx_args = tx_args.gas_limit(GasLimit::from( diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 253da79..9b84b56 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -34,6 +34,7 @@ pub mod init_pgf_funding_proposal; pub mod init_pgf_steward_proposal; pub mod reactivate_validator; pub mod redelegate; +pub mod redelegate_batch; pub mod reveal_pk; pub mod shielded_sync; pub mod transparent_transfer_batch; diff --git a/src/tasks/redelegate.rs b/src/tasks/redelegate.rs index 8a1025c..c8edb12 100644 --- a/src/tasks/redelegate.rs +++ b/src/tasks/redelegate.rs @@ -26,11 +26,11 @@ impl ToString for TxRedelegateStorageKeys { fn to_string(&self) -> String { match self { TxRedelegateStorageKeys::SourceValidatorAddress => { - "source-validator-address".to_string() + "source-validator-0-address".to_string() } - TxRedelegateStorageKeys::DestValidatorAddress => "validator-address".to_string(), // keep this the same as bonds.rs so we can reuse the bond check - TxRedelegateStorageKeys::SourceAddress => "source-address".to_string(), - TxRedelegateStorageKeys::Amount => "amount".to_string(), + TxRedelegateStorageKeys::DestValidatorAddress => "validator-0-address".to_string(), // keep this the same as bonds.rs so we can reuse the bond check + TxRedelegateStorageKeys::SourceAddress => "source-0-address".to_string(), + TxRedelegateStorageKeys::Amount => "amount-0".to_string(), } } } @@ -118,7 +118,7 @@ impl Task for TxRedelegate { } _ => { println!("no-op reason: {}", e); - return Ok(StepResult::no_op()) + return Ok(StepResult::no_op()); } }, _ => { @@ -292,25 +292,11 @@ impl TaskParam for TxRedelegateParameters { .to_string() .as_str(), ); - // let validator_state = state.get_step_item( - // &step_id, - // ValidatorsQueryStorageKeys::State(validator_idx) - // .to_string() - // .as_str(), - // ); - let dest_validator = AccountIndentifier::Address(validator_address); if dest_validator != src_validator { break Some(dest_validator); } - - // if dest_validator != src_validator - // && validator_state != ValidatorState::Inactive.to_string() - // && validator_state != ValidatorState::Jailed.to_string() - // { - // break Some(dest_validator); - // } } } } diff --git a/src/tasks/redelegate_batch.rs b/src/tasks/redelegate_batch.rs new file mode 100644 index 0000000..dff4cc3 --- /dev/null +++ b/src/tasks/redelegate_batch.rs @@ -0,0 +1,341 @@ +use async_trait::async_trait; +use namada_sdk::{ + args::TxBuilder, + error::TxSubmitError, + signing::{default_sign, SigningTxData}, + token::Amount, + tx::{self, data::GasLimit, Tx}, + Namada, DEFAULT_GAS_LIMIT, +}; +use rand::Rng; +use serde::{Deserialize, Serialize}; + +use crate::{ + entity::address::{AccountIndentifier, ADDRESS_PREFIX}, + queries::validators::ValidatorsQueryStorageKeys, + scenario::StepResult, + sdk::namada::Sdk, + state::state::{StepStorage, Storage}, + utils::{settings::TxSettings, value::Value}, +}; + +use super::{Task, TaskError, TaskParam}; + +pub enum TxRedelegateBatchStorageKeys { + SourceValidatorAddress(usize), + DestValidatorAddress(usize), + SourceAddress(usize), + Amount(usize), + BatchSize, + AtomicBatch, +} + +impl ToString for TxRedelegateBatchStorageKeys { + fn to_string(&self) -> String { + match self { + TxRedelegateBatchStorageKeys::SourceAddress(entry) => { + format!("source-{}-address", entry) + } + TxRedelegateBatchStorageKeys::DestValidatorAddress(entry) => { + format!("validator-{}-address", entry) + } + TxRedelegateBatchStorageKeys::SourceValidatorAddress(entry) => { + format!("source-validator-{}-address", entry) + } + TxRedelegateBatchStorageKeys::Amount(entry) => format!("amount-{}", entry), + TxRedelegateBatchStorageKeys::BatchSize => "batch-size".to_string(), + TxRedelegateBatchStorageKeys::AtomicBatch => "batch-atomic".to_string(), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct TxRedelegateBatch {} + +impl TxRedelegateBatch { + pub fn new() -> Self { + Self {} + } +} + +#[async_trait(?Send)] +impl Task for TxRedelegateBatch { + type P = TxRedelegateBatchParameters; + type B = namada_sdk::args::Redelegate; + + async fn execute( + &self, + sdk: &Sdk, + parameters: Self::P, + settings: TxSettings, + _state: &Storage, + ) -> Result { + let mut storage = StepStorage::default(); + + let batch_size = parameters.sources.len(); + + let mut txs = vec![]; + + for param_idx in 0..batch_size { + let source_address = parameters.sources[param_idx].to_namada_address(sdk).await; + let validator_src = parameters.src_validators[param_idx] + .to_namada_address(sdk) + .await; + let validator_target = + if let Some(address) = parameters.dest_validators[param_idx].clone() { + address.to_namada_address(sdk).await + } else { + return Ok(StepResult::no_op()); + }; + + let bond_amount = Amount::from(parameters.amounts[param_idx]); + + let redelegate_tx_builder = sdk.namada.new_redelegation( + source_address.clone(), + validator_src.clone(), + validator_target.clone(), + bond_amount, + ); + + let redelegate_tx_builder = self + .add_settings(sdk, redelegate_tx_builder, settings.clone()) + .await; + + let res = redelegate_tx_builder + .build(&sdk.namada) + .await + .map_err(|e| TaskError::Build(e.to_string())); + + if res.is_ok() { + storage.add( + TxRedelegateBatchStorageKeys::SourceAddress(param_idx).to_string(), + source_address.to_string(), + ); + storage.add( + TxRedelegateBatchStorageKeys::SourceValidatorAddress(param_idx).to_string(), + validator_src.to_string(), + ); + storage.add( + TxRedelegateBatchStorageKeys::DestValidatorAddress(param_idx).to_string(), + validator_target.to_string(), + ); + storage.add( + TxRedelegateBatchStorageKeys::Amount(param_idx).to_string(), + bond_amount.raw_amount().to_string(), + ); + txs.push(res); + } + } + + let txs = txs + .into_iter() + .filter_map(|res| res.ok()) + .collect::>(); + + if txs.is_empty() { + return Ok(StepResult::no_op()); + } + + let tx_args = Self::default_tx_arg(sdk).await; + let gas_payer = settings.clone().gas_payer.unwrap().to_public_key(sdk).await; + let tx_args = tx_args.gas_limit(GasLimit::from( + settings.clone().gas_limit.unwrap_or(DEFAULT_GAS_LIMIT), + )); + let tx_args = tx_args.wrapper_fee_payer(gas_payer); + let is_atomic = true; + + let (mut batch_tx, signing_datas) = + tx::build_batch(txs.clone()).map_err(|e| TaskError::Build(e.to_string()))?; + batch_tx.header.atomic = is_atomic; + + for signing_data in signing_datas { + sdk.namada + .sign(&mut batch_tx, &tx_args, signing_data, default_sign, ()) + .await + .expect("unable to sign tx"); + } + + let tx = sdk.namada.submit(batch_tx.clone(), &tx_args).await; + + self.fetch_info(sdk, &mut storage).await; + + if Self::is_tx_rejected(&batch_tx, &tx) { + match tx { + Ok(tx) => { + let errors = Self::get_tx_errors(&batch_tx, &tx).unwrap_or_default(); + return Ok(StepResult::fail(errors)); + } + Err(e) => match e { + namada_sdk::error::Error::Tx(TxSubmitError::AppliedTimeout) => { + return Err(TaskError::Timeout) + } + _ => return Ok(StepResult::fail(e.to_string())), + }, + } + } + + storage.add( + TxRedelegateBatchStorageKeys::BatchSize.to_string(), + txs.len().to_string(), + ); + storage.add( + TxRedelegateBatchStorageKeys::AtomicBatch.to_string(), + is_atomic.to_string(), + ); + + Ok(StepResult::success(storage)) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct TxRedelegateBatchParametersDto { + pub sources: Vec, + pub src_validators: Vec, + pub dest_validators: Vec, + pub amounts: Vec, +} + +#[derive(Clone, Debug)] +pub struct TxRedelegateBatchParameters { + pub sources: Vec, + pub src_validators: Vec, + pub dest_validators: Vec>, + pub amounts: Vec, +} + +impl TaskParam for TxRedelegateBatchParameters { + type D = TxRedelegateBatchParametersDto; + + fn parameter_from_dto(dto: Self::D, state: &Storage) -> Option { + let batch_size = dto.sources.len(); + let batch = (0..batch_size) + .filter_map(|i| { + let source = match dto.sources[i].clone() { + Value::Ref { value, field } => { + let was_step_successful = state.is_step_successful(&value); + if !was_step_successful { + return None; + } + let data = state.get_step_item(&value, &field); + match field.to_lowercase().as_str() { + "alias" => AccountIndentifier::Alias(data), + "public-key" => AccountIndentifier::PublicKey(data), + "state" => AccountIndentifier::StateAddress(state.get_address(&data)), + _ => AccountIndentifier::Address(data), + } + } + Value::Value { value } => { + if value.starts_with(ADDRESS_PREFIX) { + AccountIndentifier::Address(value) + } else { + AccountIndentifier::Alias(value) + } + } + Value::Fuzz { .. } => unimplemented!(), + }; + let src_validator = match dto.src_validators[i].clone() { + Value::Ref { value, field } => { + let was_step_successful = state.is_step_successful(&value); + if !was_step_successful { + return None; + } + let data = state.get_step_item(&value, &field); + match field.to_lowercase().as_str() { + "alias" => AccountIndentifier::Alias(data), + "public-key" => AccountIndentifier::PublicKey(data), + "state" => AccountIndentifier::StateAddress(state.get_address(&data)), + _ => AccountIndentifier::Address(data), + } + } + Value::Value { value } => { + if value.starts_with(ADDRESS_PREFIX) { + AccountIndentifier::Address(value) + } else { + AccountIndentifier::Alias(value) + } + } + Value::Fuzz { .. } => unimplemented!(), + }; + let dest_validator = match dto.dest_validators[i].clone() { + Value::Ref { value, field } => { + let was_step_successful = state.is_step_successful(&value); + if !was_step_successful { + return None; + } + let data = state.get_step_item(&value, &field); + match field.to_lowercase().as_str() { + "alias" => Some(AccountIndentifier::Alias(data)), + "public-key" => Some(AccountIndentifier::PublicKey(data)), + "state" => Some(AccountIndentifier::StateAddress(state.get_address(&data))), + _ => Some(AccountIndentifier::Address(data)), + } + } + Value::Value { value } => { + if value.starts_with(ADDRESS_PREFIX) { + Some(AccountIndentifier::Address(value)) + } else { + Some(AccountIndentifier::Alias(value)) + } + } + Value::Fuzz { value } => { + let step_id = value.expect("Redelgate task requires fuzz for dest valdidator to define the step id to a validator query step"); + let total_validators = state + .get_step_item( + &step_id, + ValidatorsQueryStorageKeys::TotalValidator + .to_string() + .as_str(), + ) + .parse::() + .unwrap(); + + if total_validators < 2 { + None + } else { + loop { + let validator_idx = rand::thread_rng().gen_range(0..total_validators); + let validator_address = state.get_step_item( + &step_id, + ValidatorsQueryStorageKeys::Validator(validator_idx) + .to_string() + .as_str(), + ); + let dest_validator = AccountIndentifier::Address(validator_address); + + if dest_validator != src_validator { + break Some(dest_validator); + } + } + } + } + }; + let amount = match dto.amounts[i].clone() { + Value::Ref { value, field } => { + let was_step_successful = state.is_step_successful(&value); + if !was_step_successful { + return None; + } + let amount = state.get_step_item(&value, &field); + amount.parse::().unwrap() + } + Value::Value { value } => value.parse::().unwrap(), + Value::Fuzz { .. } => unimplemented!(), + }; + + Some((source, src_validator, dest_validator, amount)) + }) + .collect::, + u64, + )>>(); + + Some(Self { + sources: batch.iter().map(|t| t.0.clone()).collect(), + src_validators: batch.iter().map(|t| t.1.clone()).collect(), + dest_validators: batch.iter().map(|t| t.2.clone()).collect(), + amounts: batch.iter().map(|t| t.3).collect(), + }) + } +} diff --git a/src/tasks/transparent_transfer_batch.rs b/src/tasks/transparent_transfer_batch.rs index 841bf16..0a8d869 100644 --- a/src/tasks/transparent_transfer_batch.rs +++ b/src/tasks/transparent_transfer_batch.rs @@ -7,7 +7,6 @@ use namada_sdk::{ tx::{self, data::GasLimit, Tx}, Namada, DEFAULT_GAS_LIMIT, }; -use rand::Rng; use serde::{Deserialize, Serialize}; use crate::{ @@ -111,9 +110,8 @@ impl Task for TxTransparentTransferBatch { TxTransparentTransferBatchStorageKeys::Amount(param_idx).to_string(), token_amount.raw_amount().to_string(), ); + txs.push(res); } - - txs.push(res); } let txs = txs @@ -121,6 +119,10 @@ impl Task for TxTransparentTransferBatch { .filter_map(|res| res.ok()) .collect::>(); + if txs.is_empty() { + return Ok(StepResult::no_op()); + } + let tx_args = Self::default_tx_arg(sdk).await; let gas_payer = settings.clone().gas_payer.unwrap().to_public_key(sdk).await; let tx_args = tx_args.gas_limit(GasLimit::from( diff --git a/src/waits/epoch.rs b/src/waits/epoch.rs index ecb141b..04de32d 100644 --- a/src/waits/epoch.rs +++ b/src/waits/epoch.rs @@ -1,7 +1,7 @@ use std::time::Duration; use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use tokio::time::sleep; diff --git a/src/waits/height.rs b/src/waits/height.rs index 8818647..561f487 100644 --- a/src/waits/height.rs +++ b/src/waits/height.rs @@ -1,7 +1,7 @@ use std::time::Duration; use async_trait::async_trait; -use namada_sdk::{rpc}; +use namada_sdk::rpc; use serde::{Deserialize, Serialize}; use tokio::time::sleep; From 494b7e45f5ed10ec6c35ef140129d5f04d7cfcda Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli Date: Tue, 22 Oct 2024 12:56:43 +0200 Subject: [PATCH 2/2] add redelgate batch --- src/gen/step.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gen/step.rs b/src/gen/step.rs index 903b878..0dee178 100644 --- a/src/gen/step.rs +++ b/src/gen/step.rs @@ -848,7 +848,6 @@ impl TaskType { let bond = state.random_bond(); let account = state.get_account_from_alias(&bond.source); - let bond_amount = bond.amount; let gas_payer = state .random_implicit_account_with_at_least_native_token_balance(MIN_FEE * 6) @@ -865,7 +864,7 @@ impl TaskType { .sources(vec![bond.source; total_batched_txs as usize]) .source_validators(vec![bond.step_id; total_batched_txs as usize]) .amounts(vec![ - bond_amount / 2 / total_batched_txs; + 1; total_batched_txs as usize ]) .tx_settings(tx_settings)