Skip to content

Commit 5045593

Browse files
Merge pull request #1519 from mintlayer/fix/broken-test
Add optional destination for decommission stake pool
2 parents 0490149 + 17c3b8a commit 5045593

File tree

12 files changed

+241
-35
lines changed

12 files changed

+241
-35
lines changed

test/functional/test_framework/wallet_rpc_controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ async def create_stake_pool(self,
245245
return "The transaction was submitted successfully"
246246

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

251251
async def list_pool_ids(self) -> List[PoolData]:

wallet/src/account/mod.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -536,16 +536,26 @@ impl Account {
536536
db_tx: &mut impl WalletStorageWriteUnlocked,
537537
pool_id: PoolId,
538538
pool_balance: Amount,
539+
output_address: Option<Destination>,
539540
current_fee_rate: FeeRate,
540541
) -> WalletResult<PartiallySignedTransaction> {
542+
let output_destination = if let Some(dest) = output_address {
543+
dest
544+
} else {
545+
self.get_new_address(db_tx, KeyPurpose::ReceiveFunds)?
546+
.1
547+
.decode_object(&self.chain_config)
548+
.expect("already checked")
549+
};
550+
541551
let pool_data = self.output_cache.pool_data(pool_id)?;
542552
let best_block_height = self.best_block().1;
543553
let tx_input = TxInput::Utxo(pool_data.utxo_outpoint.clone());
544554

545555
let network_fee: Amount = {
546556
let output = make_decommission_stake_pool_output(
547557
self.chain_config.as_ref(),
548-
pool_data.decommission_key.clone(),
558+
output_destination.clone(),
549559
pool_balance,
550560
best_block_height,
551561
)?;
@@ -563,7 +573,7 @@ impl Account {
563573

564574
let output = make_decommission_stake_pool_output(
565575
self.chain_config.as_ref(),
566-
pool_data.decommission_key.clone(),
576+
output_destination,
567577
(pool_balance - network_fee)
568578
.ok_or(WalletError::NotEnoughUtxo(network_fee, pool_balance))?,
569579
best_block_height,
@@ -580,10 +590,16 @@ impl Account {
580590
db_tx: &mut impl WalletStorageWriteUnlocked,
581591
pool_id: PoolId,
582592
pool_balance: Amount,
593+
output_address: Option<Destination>,
583594
current_fee_rate: FeeRate,
584595
) -> WalletResult<SignedTransaction> {
585-
let result =
586-
self.decommission_stake_pool_impl(db_tx, pool_id, pool_balance, current_fee_rate)?;
596+
let result = self.decommission_stake_pool_impl(
597+
db_tx,
598+
pool_id,
599+
pool_balance,
600+
output_address,
601+
current_fee_rate,
602+
)?;
587603
result
588604
.into_signed_tx()
589605
.map_err(|_| WalletError::PartiallySignedTransactionInDecommissionCommand)
@@ -594,10 +610,16 @@ impl Account {
594610
db_tx: &mut impl WalletStorageWriteUnlocked,
595611
pool_id: PoolId,
596612
pool_balance: Amount,
613+
output_address: Option<Destination>,
597614
current_fee_rate: FeeRate,
598615
) -> WalletResult<PartiallySignedTransaction> {
599-
let result =
600-
self.decommission_stake_pool_impl(db_tx, pool_id, pool_balance, current_fee_rate)?;
616+
let result = self.decommission_stake_pool_impl(
617+
db_tx,
618+
pool_id,
619+
pool_balance,
620+
output_address,
621+
current_fee_rate,
622+
)?;
601623
if result.is_fully_signed() {
602624
return Err(WalletError::FullySignedTransactionInDecommissionReq);
603625
}

wallet/src/wallet/mod.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,10 +1329,17 @@ impl<B: storage::Backend> Wallet<B> {
13291329
account_index: U31,
13301330
pool_id: PoolId,
13311331
pool_balance: Amount,
1332+
output_address: Option<Destination>,
13321333
current_fee_rate: FeeRate,
13331334
) -> WalletResult<SignedTransaction> {
13341335
self.for_account_rw_unlocked_and_check_tx(account_index, |account, db_tx| {
1335-
account.decommission_stake_pool(db_tx, pool_id, pool_balance, current_fee_rate)
1336+
account.decommission_stake_pool(
1337+
db_tx,
1338+
pool_id,
1339+
pool_balance,
1340+
output_address,
1341+
current_fee_rate,
1342+
)
13361343
})
13371344
}
13381345

@@ -1341,10 +1348,17 @@ impl<B: storage::Backend> Wallet<B> {
13411348
account_index: U31,
13421349
pool_id: PoolId,
13431350
pool_balance: Amount,
1351+
output_address: Option<Destination>,
13441352
current_fee_rate: FeeRate,
13451353
) -> WalletResult<PartiallySignedTransaction> {
13461354
self.for_account_rw_unlocked(account_index, |account, db_tx, _| {
1347-
account.decommission_stake_pool_request(db_tx, pool_id, pool_balance, current_fee_rate)
1355+
account.decommission_stake_pool_request(
1356+
db_tx,
1357+
pool_id,
1358+
pool_balance,
1359+
output_address,
1360+
current_fee_rate,
1361+
)
13481362
})
13491363
}
13501364

wallet/src/wallet/tests.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,7 @@ fn create_stake_pool_and_list_pool_ids(#[case] seed: Seed) {
14031403
DEFAULT_ACCOUNT_INDEX,
14041404
*pool_id,
14051405
pool_amount,
1406+
None,
14061407
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
14071408
)
14081409
.unwrap();
@@ -3698,6 +3699,7 @@ fn decommission_pool_wrong_account(#[case] seed: Seed) {
36983699
acc_0_index,
36993700
pool_id,
37003701
pool_amount,
3702+
None,
37013703
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
37023704
);
37033705
assert_eq!(
@@ -3711,6 +3713,7 @@ fn decommission_pool_wrong_account(#[case] seed: Seed) {
37113713
acc_1_index,
37123714
pool_id,
37133715
pool_amount,
3716+
None,
37143717
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
37153718
)
37163719
.unwrap();
@@ -3799,6 +3802,7 @@ fn decommission_pool_request_wrong_account(#[case] seed: Seed) {
37993802
acc_1_index,
38003803
pool_id,
38013804
pool_amount,
3805+
None,
38023806
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
38033807
);
38043808
assert_eq!(
@@ -3811,6 +3815,7 @@ fn decommission_pool_request_wrong_account(#[case] seed: Seed) {
38113815
acc_0_index,
38123816
pool_id,
38133817
pool_amount,
3818+
None,
38143819
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
38153820
)
38163821
.unwrap();
@@ -3883,6 +3888,8 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
38833888
1,
38843889
);
38853890

3891+
assert_eq!(get_coin_balance(&wallet), Amount::ZERO);
3892+
38863893
let pool_ids = wallet.get_pool_ids(acc_0_index, WalletPoolsFilter::All).unwrap();
38873894
assert_eq!(pool_ids.len(), 1);
38883895

@@ -3892,6 +3899,7 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
38923899
acc_0_index,
38933900
pool_id,
38943901
pool_amount,
3902+
None,
38953903
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
38963904
)
38973905
.unwrap();
@@ -3915,20 +3923,11 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
39153923
.into_signed_tx()
39163924
.unwrap();
39173925

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

3920-
let currency_balances = wallet
3921-
.get_balance(
3922-
acc_1_index,
3923-
UtxoType::Transfer | UtxoType::LockThenTransfer | UtxoType::CreateStakePool,
3924-
UtxoState::Confirmed.into(),
3925-
WithLocked::Unlocked,
3926-
)
3927-
.unwrap();
3928-
assert_eq!(
3929-
currency_balances.get(&Currency::Coin).copied().unwrap_or(Amount::ZERO),
3930-
pool_amount,
3931-
);
3928+
// the pool amount is back after decommission
3929+
assert_eq!(get_coin_balance(&wallet), pool_amount);
3930+
assert_eq!(get_coin_balance_for_acc(&wallet, acc_1_index), Amount::ZERO);
39323931
}
39333932

39343933
#[rstest]
@@ -3994,6 +3993,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
39943993
DEFAULT_ACCOUNT_INDEX,
39953994
pool_id,
39963995
pool_amount,
3996+
None,
39973997
FeeRate::from_amount_per_kb(Amount::from_atoms(0)),
39983998
)
39993999
.unwrap();
@@ -4013,7 +4013,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
40134013
&mut hot_wallet,
40144014
vec![signed_tx],
40154015
Amount::ZERO,
4016-
1,
4016+
2,
40174017
);
40184018

40194019
let currency_balances = hot_wallet

wallet/wallet-cli-lib/src/commands/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,9 @@ pub enum WalletCommand {
478478
/// The pool id of the pool to be decommissioned.
479479
/// Notice that this only works if the selected account in this wallet owns the decommission key.
480480
pool_id: String,
481+
/// The address that will be receiving the staker's balance (both pledge and proceeds from staking).
482+
/// If not specified, a new receiving address will be created by this wallet's selected account
483+
output_address: Option<String>,
481484
},
482485

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

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

1532-
WalletCommand::DecommissionStakePool { pool_id } => {
1538+
WalletCommand::DecommissionStakePool {
1539+
pool_id,
1540+
output_address,
1541+
} => {
15331542
let selected_account = self.get_selected_acc()?;
15341543
let new_tx = self
15351544
.wallet_rpc
1536-
.decommission_stake_pool(selected_account, pool_id, self.config)
1545+
.decommission_stake_pool(selected_account, pool_id, output_address, self.config)
15371546
.await?;
15381547
Ok(Self::new_tx_submitted_command(new_tx))
15391548
}
15401549

1541-
WalletCommand::DecommissionStakePoolRequest { pool_id } => {
1550+
WalletCommand::DecommissionStakePoolRequest {
1551+
pool_id,
1552+
output_address,
1553+
} => {
15421554
let selected_account = self.get_selected_acc()?;
15431555
let result = self
15441556
.wallet_rpc
1545-
.decommission_stake_pool_request(selected_account, pool_id, self.config)
1557+
.decommission_stake_pool_request(
1558+
selected_account,
1559+
pool_id,
1560+
output_address,
1561+
self.config,
1562+
)
15461563
.await?;
15471564
let result_hex: HexEncoded<PartiallySignedTransaction> = result.into();
15481565

wallet/wallet-cli-lib/tests/basic.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
mod cli_test_framework;
1717

18+
use crypto::random::Rng;
19+
20+
use common::{address::Address, chain::PoolId, primitives::H256};
1821
use rstest::rstest;
1922
use test_utils::random::{make_seedable_rng, Seed};
2023

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

8386
test.shutdown().await;
8487
}
88+
89+
#[rstest]
90+
#[case(test_utils::random::Seed::from_entropy())]
91+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
92+
async fn produce_blocks_decommission_genesis_pool(#[case] seed: Seed) {
93+
let mut rng = make_seedable_rng(seed);
94+
95+
let test = CliTestFramework::setup(&mut rng).await;
96+
97+
test.create_genesis_wallet();
98+
99+
assert_eq!(test.exec("account-balance"), "Coins amount: 99960000");
100+
101+
// create a new pool
102+
let address = test.exec("address-new");
103+
assert!(test
104+
.exec(&format!(
105+
"staking-create-pool 40000 {} 0.{} {}",
106+
rng.gen_range(0..100),
107+
rng.gen_range(1..100),
108+
address,
109+
),)
110+
.starts_with("The transaction was submitted successfully with ID"));
111+
// create some blocks
112+
assert_eq!(test.exec("node-generate-blocks 20"), "Success");
113+
114+
// create a new account and a new pool
115+
assert_eq!(
116+
test.exec("account-create"),
117+
"Success, the new account index is: 1"
118+
);
119+
assert_eq!(test.exec("account-select 1"), "Success");
120+
let acc2_address = test.exec("address-new");
121+
assert_eq!(test.exec("account-select 0"), "Success");
122+
assert!(test
123+
.exec(&format!("address-send {} 50000", acc2_address))
124+
.starts_with("The transaction was submitted successfully with ID"));
125+
assert_eq!(test.exec("account-select 1"), "Success");
126+
assert!(test
127+
.exec(&format!(
128+
"staking-create-pool 40000 {} 0.{} {}",
129+
rng.gen_range(0..100),
130+
rng.gen_range(1..100),
131+
address,
132+
),)
133+
.starts_with("The transaction was submitted successfully with ID"));
134+
assert_eq!(test.exec("account-select 0"), "Success");
135+
136+
// create some blocks
137+
assert_eq!(test.exec("node-generate-blocks 1"), "Success");
138+
139+
// create some blocks with the other pool
140+
assert_eq!(test.exec("account-select 1"), "Success");
141+
assert_eq!(test.exec("node-generate-blocks 1"), "Success");
142+
143+
// create the decommission request
144+
assert_eq!(test.exec("account-select 0"), "Success");
145+
let pool_id: PoolId = H256::zero().into();
146+
let output = test.exec(&format!(
147+
"staking-decommission-pool-request {}",
148+
Address::new(&test.chain_config, &pool_id).unwrap()
149+
));
150+
let req = output.lines().nth(2).unwrap();
151+
152+
assert_eq!(test.exec("wallet-close"), "Successfully closed the wallet.");
153+
154+
test.create_genesis_cold_wallet();
155+
let output = test.exec(&format!("account-sign-raw-transaction {req}"));
156+
let signed_tx = output.lines().nth(2).unwrap();
157+
assert_eq!(test.exec("wallet-close"), "Successfully closed the wallet.");
158+
159+
// submit the tx
160+
test.create_genesis_wallet();
161+
assert_eq!(test.exec("wallet-sync"), "Success");
162+
assert_eq!(
163+
test.exec(&format!("node-submit-transaction {signed_tx}")),
164+
"The transaction was submitted successfully"
165+
);
166+
167+
// stake with the other acc
168+
assert_eq!(test.exec("account-select 1"), "Success");
169+
assert_eq!(test.exec("node-generate-blocks 10"), "Success");
170+
171+
// stake with the first acc
172+
assert_eq!(test.exec("account-select 0"), "Success");
173+
assert!(test.exec("account-balance").starts_with("Coins amount: 99869999"));
174+
assert!(test.exec("account-balance locked").starts_with("Coins amount: 44242"));
175+
assert_eq!(test.exec("node-generate-blocks 2"), "Success");
176+
177+
test.shutdown().await;
178+
}

0 commit comments

Comments
 (0)