Skip to content

Commit

Permalink
Merge pull request #1519 from mintlayer/fix/broken-test
Browse files Browse the repository at this point in the history
Add optional destination for decommission stake pool
  • Loading branch information
TheQuantumPhysicist authored Jan 29, 2024
2 parents 0490149 + 17c3b8a commit 5045593
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 35 deletions.
2 changes: 1 addition & 1 deletion test/functional/test_framework/wallet_rpc_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ async def create_stake_pool(self,
return "The transaction was submitted successfully"

async def decommission_stake_pool(self, pool_id: str) -> str:
self._write_command("staking_decommission_pool", [self.account, pool_id, {'in_top_x_mb': 5}])['result']
self._write_command("staking_decommission_pool", [self.account, pool_id, None, {'in_top_x_mb': 5}])['result']
return "The transaction was submitted successfully"

async def list_pool_ids(self) -> List[PoolData]:
Expand Down
34 changes: 28 additions & 6 deletions wallet/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,16 +536,26 @@ impl Account {
db_tx: &mut impl WalletStorageWriteUnlocked,
pool_id: PoolId,
pool_balance: Amount,
output_address: Option<Destination>,
current_fee_rate: FeeRate,
) -> WalletResult<PartiallySignedTransaction> {
let output_destination = if let Some(dest) = output_address {
dest
} else {
self.get_new_address(db_tx, KeyPurpose::ReceiveFunds)?
.1
.decode_object(&self.chain_config)
.expect("already checked")
};

let pool_data = self.output_cache.pool_data(pool_id)?;
let best_block_height = self.best_block().1;
let tx_input = TxInput::Utxo(pool_data.utxo_outpoint.clone());

let network_fee: Amount = {
let output = make_decommission_stake_pool_output(
self.chain_config.as_ref(),
pool_data.decommission_key.clone(),
output_destination.clone(),
pool_balance,
best_block_height,
)?;
Expand All @@ -563,7 +573,7 @@ impl Account {

let output = make_decommission_stake_pool_output(
self.chain_config.as_ref(),
pool_data.decommission_key.clone(),
output_destination,
(pool_balance - network_fee)
.ok_or(WalletError::NotEnoughUtxo(network_fee, pool_balance))?,
best_block_height,
Expand All @@ -580,10 +590,16 @@ impl Account {
db_tx: &mut impl WalletStorageWriteUnlocked,
pool_id: PoolId,
pool_balance: Amount,
output_address: Option<Destination>,
current_fee_rate: FeeRate,
) -> WalletResult<SignedTransaction> {
let result =
self.decommission_stake_pool_impl(db_tx, pool_id, pool_balance, current_fee_rate)?;
let result = self.decommission_stake_pool_impl(
db_tx,
pool_id,
pool_balance,
output_address,
current_fee_rate,
)?;
result
.into_signed_tx()
.map_err(|_| WalletError::PartiallySignedTransactionInDecommissionCommand)
Expand All @@ -594,10 +610,16 @@ impl Account {
db_tx: &mut impl WalletStorageWriteUnlocked,
pool_id: PoolId,
pool_balance: Amount,
output_address: Option<Destination>,
current_fee_rate: FeeRate,
) -> WalletResult<PartiallySignedTransaction> {
let result =
self.decommission_stake_pool_impl(db_tx, pool_id, pool_balance, current_fee_rate)?;
let result = self.decommission_stake_pool_impl(
db_tx,
pool_id,
pool_balance,
output_address,
current_fee_rate,
)?;
if result.is_fully_signed() {
return Err(WalletError::FullySignedTransactionInDecommissionReq);
}
Expand Down
18 changes: 16 additions & 2 deletions wallet/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,10 +1329,17 @@ impl<B: storage::Backend> Wallet<B> {
account_index: U31,
pool_id: PoolId,
pool_balance: Amount,
output_address: Option<Destination>,
current_fee_rate: FeeRate,
) -> WalletResult<SignedTransaction> {
self.for_account_rw_unlocked_and_check_tx(account_index, |account, db_tx| {
account.decommission_stake_pool(db_tx, pool_id, pool_balance, current_fee_rate)
account.decommission_stake_pool(
db_tx,
pool_id,
pool_balance,
output_address,
current_fee_rate,
)
})
}

Expand All @@ -1341,10 +1348,17 @@ impl<B: storage::Backend> Wallet<B> {
account_index: U31,
pool_id: PoolId,
pool_balance: Amount,
output_address: Option<Destination>,
current_fee_rate: FeeRate,
) -> WalletResult<PartiallySignedTransaction> {
self.for_account_rw_unlocked(account_index, |account, db_tx, _| {
account.decommission_stake_pool_request(db_tx, pool_id, pool_balance, current_fee_rate)
account.decommission_stake_pool_request(
db_tx,
pool_id,
pool_balance,
output_address,
current_fee_rate,
)
})
}

Expand Down
28 changes: 14 additions & 14 deletions wallet/src/wallet/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,7 @@ fn create_stake_pool_and_list_pool_ids(#[case] seed: Seed) {
DEFAULT_ACCOUNT_INDEX,
*pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
)
.unwrap();
Expand Down Expand Up @@ -3698,6 +3699,7 @@ fn decommission_pool_wrong_account(#[case] seed: Seed) {
acc_0_index,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
);
assert_eq!(
Expand All @@ -3711,6 +3713,7 @@ fn decommission_pool_wrong_account(#[case] seed: Seed) {
acc_1_index,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
)
.unwrap();
Expand Down Expand Up @@ -3799,6 +3802,7 @@ fn decommission_pool_request_wrong_account(#[case] seed: Seed) {
acc_1_index,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
);
assert_eq!(
Expand All @@ -3811,6 +3815,7 @@ fn decommission_pool_request_wrong_account(#[case] seed: Seed) {
acc_0_index,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
)
.unwrap();
Expand Down Expand Up @@ -3883,6 +3888,8 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
1,
);

assert_eq!(get_coin_balance(&wallet), Amount::ZERO);

let pool_ids = wallet.get_pool_ids(acc_0_index, WalletPoolsFilter::All).unwrap();
assert_eq!(pool_ids.len(), 1);

Expand All @@ -3892,6 +3899,7 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
acc_0_index,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
)
.unwrap();
Expand All @@ -3915,20 +3923,11 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
.into_signed_tx()
.unwrap();

let _ = create_block(&chain_config, &mut wallet, vec![signed_tx], Amount::ZERO, 1);
let _ = create_block(&chain_config, &mut wallet, vec![signed_tx], Amount::ZERO, 2);

let currency_balances = wallet
.get_balance(
acc_1_index,
UtxoType::Transfer | UtxoType::LockThenTransfer | UtxoType::CreateStakePool,
UtxoState::Confirmed.into(),
WithLocked::Unlocked,
)
.unwrap();
assert_eq!(
currency_balances.get(&Currency::Coin).copied().unwrap_or(Amount::ZERO),
pool_amount,
);
// the pool amount is back after decommission
assert_eq!(get_coin_balance(&wallet), pool_amount);
assert_eq!(get_coin_balance_for_acc(&wallet, acc_1_index), Amount::ZERO);
}

#[rstest]
Expand Down Expand Up @@ -3994,6 +3993,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
DEFAULT_ACCOUNT_INDEX,
pool_id,
pool_amount,
None,
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
)
.unwrap();
Expand All @@ -4013,7 +4013,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
&mut hot_wallet,
vec![signed_tx],
Amount::ZERO,
1,
2,
);

let currency_balances = hot_wallet
Expand Down
25 changes: 21 additions & 4 deletions wallet/wallet-cli-lib/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ pub enum WalletCommand {
/// The pool id of the pool to be decommissioned.
/// Notice that this only works if the selected account in this wallet owns the decommission key.
pool_id: String,
/// The address that will be receiving the staker's balance (both pledge and proceeds from staking).
/// If not specified, a new receiving address will be created by this wallet's selected account
output_address: Option<String>,
},

/// Create a request to decommission a pool. This assumes that the decommission key is owned
Expand All @@ -488,6 +491,9 @@ pub enum WalletCommand {
DecommissionStakePoolRequest {
/// The pool id of the pool to be decommissioned.
pool_id: String,
/// The address that will be receiving the staker's balance (both pledge and proceeds from staking).
/// If not specified, a new receiving address will be created by this wallet's selected account
output_address: Option<String>,
},

/// Rescan the blockchain and re-detect all operations related to the selected account in this wallet
Expand Down Expand Up @@ -1529,20 +1535,31 @@ where
Ok(Self::new_tx_submitted_command(new_tx))
}

WalletCommand::DecommissionStakePool { pool_id } => {
WalletCommand::DecommissionStakePool {
pool_id,
output_address,
} => {
let selected_account = self.get_selected_acc()?;
let new_tx = self
.wallet_rpc
.decommission_stake_pool(selected_account, pool_id, self.config)
.decommission_stake_pool(selected_account, pool_id, output_address, self.config)
.await?;
Ok(Self::new_tx_submitted_command(new_tx))
}

WalletCommand::DecommissionStakePoolRequest { pool_id } => {
WalletCommand::DecommissionStakePoolRequest {
pool_id,
output_address,
} => {
let selected_account = self.get_selected_acc()?;
let result = self
.wallet_rpc
.decommission_stake_pool_request(selected_account, pool_id, self.config)
.decommission_stake_pool_request(
selected_account,
pool_id,
output_address,
self.config,
)
.await?;
let result_hex: HexEncoded<PartiallySignedTransaction> = result.into();

Expand Down
94 changes: 94 additions & 0 deletions wallet/wallet-cli-lib/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

mod cli_test_framework;

use crypto::random::Rng;

use common::{address::Address, chain::PoolId, primitives::H256};
use rstest::rstest;
use test_utils::random::{make_seedable_rng, Seed};

Expand Down Expand Up @@ -82,3 +85,94 @@ async fn produce_blocks(#[case] seed: Seed) {

test.shutdown().await;
}

#[rstest]
#[case(test_utils::random::Seed::from_entropy())]
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn produce_blocks_decommission_genesis_pool(#[case] seed: Seed) {
let mut rng = make_seedable_rng(seed);

let test = CliTestFramework::setup(&mut rng).await;

test.create_genesis_wallet();

assert_eq!(test.exec("account-balance"), "Coins amount: 99960000");

// create a new pool
let address = test.exec("address-new");
assert!(test
.exec(&format!(
"staking-create-pool 40000 {} 0.{} {}",
rng.gen_range(0..100),
rng.gen_range(1..100),
address,
),)
.starts_with("The transaction was submitted successfully with ID"));
// create some blocks
assert_eq!(test.exec("node-generate-blocks 20"), "Success");

// create a new account and a new pool
assert_eq!(
test.exec("account-create"),
"Success, the new account index is: 1"
);
assert_eq!(test.exec("account-select 1"), "Success");
let acc2_address = test.exec("address-new");
assert_eq!(test.exec("account-select 0"), "Success");
assert!(test
.exec(&format!("address-send {} 50000", acc2_address))
.starts_with("The transaction was submitted successfully with ID"));
assert_eq!(test.exec("account-select 1"), "Success");
assert!(test
.exec(&format!(
"staking-create-pool 40000 {} 0.{} {}",
rng.gen_range(0..100),
rng.gen_range(1..100),
address,
),)
.starts_with("The transaction was submitted successfully with ID"));
assert_eq!(test.exec("account-select 0"), "Success");

// create some blocks
assert_eq!(test.exec("node-generate-blocks 1"), "Success");

// create some blocks with the other pool
assert_eq!(test.exec("account-select 1"), "Success");
assert_eq!(test.exec("node-generate-blocks 1"), "Success");

// create the decommission request
assert_eq!(test.exec("account-select 0"), "Success");
let pool_id: PoolId = H256::zero().into();
let output = test.exec(&format!(
"staking-decommission-pool-request {}",
Address::new(&test.chain_config, &pool_id).unwrap()
));
let req = output.lines().nth(2).unwrap();

assert_eq!(test.exec("wallet-close"), "Successfully closed the wallet.");

test.create_genesis_cold_wallet();
let output = test.exec(&format!("account-sign-raw-transaction {req}"));
let signed_tx = output.lines().nth(2).unwrap();
assert_eq!(test.exec("wallet-close"), "Successfully closed the wallet.");

// submit the tx
test.create_genesis_wallet();
assert_eq!(test.exec("wallet-sync"), "Success");
assert_eq!(
test.exec(&format!("node-submit-transaction {signed_tx}")),
"The transaction was submitted successfully"
);

// stake with the other acc
assert_eq!(test.exec("account-select 1"), "Success");
assert_eq!(test.exec("node-generate-blocks 10"), "Success");

// stake with the first acc
assert_eq!(test.exec("account-select 0"), "Success");
assert!(test.exec("account-balance").starts_with("Coins amount: 99869999"));
assert!(test.exec("account-balance locked").starts_with("Coins amount: 44242"));
assert_eq!(test.exec("node-generate-blocks 2"), "Success");

test.shutdown().await;
}
Loading

0 comments on commit 5045593

Please sign in to comment.