Skip to content

Commit 21b59b8

Browse files
committed
taurus compatibility
1 parent ba7edac commit 21b59b8

File tree

4 files changed

+128
-32
lines changed

4 files changed

+128
-32
lines changed

crates/pallet-domains/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,21 @@ mod pallet {
777777
pub type DeregisteredOperators<T: Config> =
778778
StorageMap<_, Identity, DomainId, BTreeSet<OperatorId>, ValueQuery>;
779779

780+
pub struct AllowedMissingSharePriceEpoch;
781+
782+
impl Get<DomainEpoch> for AllowedMissingSharePriceEpoch {
783+
fn get() -> DomainEpoch {
784+
(DomainId::new(0), 23_347).into()
785+
}
786+
}
787+
788+
/// Storage that hold a domain epoch, for epoch that happen before it, the share price may
789+
/// be missing due to https://github.com/autonomys/subspace/pull/3661, in this case, we
790+
/// use the current share price as the default.
791+
#[pallet::storage]
792+
pub type AllowedDefaultSharePriceEpoch<T> =
793+
StorageValue<_, DomainEpoch, ValueQuery, AllowedMissingSharePriceEpoch>;
794+
780795
#[derive(TypeInfo, Encode, Decode, PalletError, Debug, PartialEq)]
781796
pub enum BundleError {
782797
/// Can not find the operator for given operator id.

crates/pallet-domains/src/nominator_position.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
33
use crate::pallet::{Config, Deposits, DomainStakingSummary, Operators, Withdrawals};
44

5-
use crate::staking::{do_convert_previous_epoch_deposits, do_convert_previous_epoch_withdrawal};
5+
use crate::staking::{
6+
SharePrice, do_convert_previous_epoch_deposits, do_convert_previous_epoch_withdrawal,
7+
};
68
use crate::{BalanceOf, DomainBlockNumberFor, ReceiptHashFor};
79
use alloc::vec::Vec;
810
use sp_domains::{EpochIndex, OperatorId};
@@ -77,6 +79,7 @@ fn process_deposit<T: Config>(
7779
operator_id,
7880
&mut deposit,
7981
position_data.current_epoch_index,
82+
None,
8083
);
8184

8285
// Extract results
@@ -123,6 +126,7 @@ fn process_withdrawals<T: Config>(
123126
nominator_account: &T::AccountId,
124127
current_share_price: &crate::staking::SharePrice,
125128
current_epoch_index: EpochIndex,
129+
maybe_share_price: Option<SharePrice>,
126130
) -> Vec<sp_domains::PendingWithdrawal<BalanceOf<T>, DomainBlockNumberFor<T>>> {
127131
let Some(withdrawal) = Withdrawals::<T>::get(operator_id, nominator_account) else {
128132
return Vec::new();
@@ -136,6 +140,7 @@ fn process_withdrawals<T: Config>(
136140
operator_id,
137141
&mut withdrawal,
138142
current_epoch_index,
143+
maybe_share_price,
139144
);
140145

141146
let mut pending_withdrawals = Vec::with_capacity(
@@ -216,6 +221,7 @@ pub fn nominator_position<T: Config>(
216221
&nominator_account,
217222
&position_data.current_share_price,
218223
position_data.current_epoch_index,
224+
Some(position_data.current_share_price.clone()),
219225
);
220226

221227
Some(NominatorPosition {

crates/pallet-domains/src/staking.rs

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use crate::pallet::{
1212
};
1313
use crate::staking_epoch::{mint_funds, mint_into_treasury};
1414
use crate::{
15-
BalanceOf, Config, DepositOnHold, DeregisteredOperators, DomainBlockNumberFor,
16-
DomainHashingFor, Event, ExecutionReceiptOf, HoldIdentifier, InvalidBundleAuthors, NominatorId,
17-
OperatorEpochSharePrice, OperatorHighestSlot, Pallet, ReceiptHashFor, SlashedReason,
15+
AllowedDefaultSharePriceEpoch, BalanceOf, Config, DepositOnHold, DeregisteredOperators,
16+
DomainBlockNumberFor, DomainHashingFor, Event, ExecutionReceiptOf, HoldIdentifier,
17+
InvalidBundleAuthors, NominatorId, OperatorEpochSharePrice, OperatorHighestSlot, Pallet,
18+
ReceiptHashFor, SlashedReason,
1819
};
1920
use frame_support::traits::fungible::{Inspect, MutateHold};
2021
use frame_support::traits::tokens::{Fortitude, Precision, Preservation};
@@ -423,6 +424,7 @@ pub fn do_register_operator<T: Config>(
423424
current_domain_epoch,
424425
new_deposit,
425426
None,
427+
None,
426428
)?;
427429

428430
Ok((operator_id, domain_stake_summary.current_epoch_index))
@@ -439,10 +441,16 @@ pub(crate) fn do_calculate_previous_epoch_deposit_shares_and_add_new_deposit<T:
439441
current_domain_epoch: DomainEpoch,
440442
new_deposit: NewDeposit<BalanceOf<T>>,
441443
required_minimum_nominator_stake: Option<BalanceOf<T>>,
444+
maybe_share_price: Option<SharePrice>,
442445
) -> Result<(), Error> {
443446
Deposits::<T>::try_mutate(operator_id, nominator_id, |maybe_deposit| {
444447
let mut deposit = maybe_deposit.take().unwrap_or_default();
445-
do_convert_previous_epoch_deposits::<T>(operator_id, &mut deposit, current_domain_epoch.1)?;
448+
do_convert_previous_epoch_deposits::<T>(
449+
operator_id,
450+
&mut deposit,
451+
current_domain_epoch.1,
452+
maybe_share_price,
453+
)?;
446454

447455
// add or create new pending deposit
448456
let pending_deposit = match deposit.pending {
@@ -483,19 +491,27 @@ pub(crate) fn do_convert_previous_epoch_deposits<T: Config>(
483491
operator_id: OperatorId,
484492
deposit: &mut Deposit<T::Share, BalanceOf<T>>,
485493
current_domain_epoch_index: EpochIndex,
494+
maybe_share_price: Option<SharePrice>,
486495
) -> Result<(), Error> {
487496
// if it is one of the previous domain epoch, then calculate shares for the epoch and update known deposit
488497
let epoch_share_price = match deposit.pending {
489498
None => return Ok(()),
490499
Some(pending_deposit) => {
500+
if pending_deposit.effective_domain_epoch.1 >= current_domain_epoch_index {
501+
return Ok(());
502+
}
503+
491504
match get_share_price::<T>(operator_id, pending_deposit.effective_domain_epoch) {
492505
Some(p) => p,
493506
None => {
494-
ensure!(
495-
pending_deposit.effective_domain_epoch.1 >= current_domain_epoch_index,
496-
Error::MissingOperatorEpochSharePrice
497-
);
498-
return Ok(());
507+
match allowed_default_share_price::<T>(
508+
operator_id,
509+
pending_deposit.effective_domain_epoch.1,
510+
maybe_share_price,
511+
) {
512+
Some(p) => p,
513+
None => return Err(Error::MissingOperatorEpochSharePrice),
514+
}
499515
}
500516
}
501517
}
@@ -523,6 +539,25 @@ pub(crate) fn do_convert_previous_epoch_deposits<T: Config>(
523539
Ok(())
524540
}
525541

542+
pub(crate) fn allowed_default_share_price<T: Config>(
543+
operator_id: OperatorId,
544+
domain_epoch_index: EpochIndex,
545+
maybe_share_price: Option<SharePrice>,
546+
) -> Option<SharePrice> {
547+
let DomainEpoch(allowed_domain_id, allowed_epoch_index) =
548+
AllowedDefaultSharePriceEpoch::<T>::get();
549+
let operator = Operators::<T>::get(operator_id)?;
550+
551+
// The default share price is only allowed if the requested `domain_epoch_index` is happen
552+
// before (or is the same as) the `AllowedDefaultSharePriceEpoch`
553+
if allowed_domain_id == operator.current_domain_id && allowed_epoch_index >= domain_epoch_index
554+
{
555+
maybe_share_price
556+
} else {
557+
None
558+
}
559+
}
560+
526561
/// Converts any epoch withdrawals into balance using the operator epoch share price.
527562
///
528563
/// If there is withdrawal happened in the current epoch (thus share price is unavailable),
@@ -532,6 +567,7 @@ pub(crate) fn do_convert_previous_epoch_withdrawal<T: Config>(
532567
operator_id: OperatorId,
533568
withdrawal: &mut Withdrawal<BalanceOf<T>, T::Share, DomainBlockNumberFor<T>>,
534569
current_domain_epoch_index: EpochIndex,
570+
maybe_share_price: Option<SharePrice>,
535571
) -> Result<(), Error> {
536572
let epoch_share_price = match withdrawal.withdrawal_in_shares.as_ref() {
537573
None => return Ok(()),
@@ -543,7 +579,16 @@ pub(crate) fn do_convert_previous_epoch_withdrawal<T: Config>(
543579

544580
match get_share_price::<T>(operator_id, withdraw.domain_epoch) {
545581
Some(p) => p,
546-
None => return Err(Error::MissingOperatorEpochSharePrice),
582+
None => {
583+
match allowed_default_share_price::<T>(
584+
operator_id,
585+
withdraw.domain_epoch.1,
586+
maybe_share_price,
587+
) {
588+
Some(p) => p,
589+
None => return Err(Error::MissingOperatorEpochSharePrice),
590+
}
591+
}
547592
}
548593
}
549594
};
@@ -595,6 +640,8 @@ pub(crate) fn do_nominate_operator<T: Config>(
595640
let domain_stake_summary = DomainStakingSummary::<T>::get(operator.current_domain_id)
596641
.ok_or(Error::DomainNotInitialized)?;
597642

643+
let share_price = current_share_price::<T>(operator_id, operator, &domain_stake_summary)?;
644+
598645
// Reserve for the bundle storage fund
599646
let new_deposit = deposit_reserve_for_storage_fund::<T>(operator_id, &nominator_id, amount)
600647
.map_err(Error::BundleStorageFund)?;
@@ -630,6 +677,7 @@ pub(crate) fn do_nominate_operator<T: Config>(
630677
current_domain_epoch,
631678
new_deposit,
632679
Some(operator.minimum_nominator_stake),
680+
Some(share_price),
633681
)?;
634682

635683
Ok(())
@@ -770,13 +818,15 @@ pub(crate) fn do_withdraw_stake<T: Config>(
770818
)
771819
.into();
772820

821+
let share_price = current_share_price::<T>(operator_id, operator, &domain_stake_summary)?;
773822
let known_shares =
774823
Deposits::<T>::try_mutate(operator_id, nominator_id.clone(), |maybe_deposit| {
775824
let deposit = maybe_deposit.as_mut().ok_or(Error::UnknownNominator)?;
776825
do_convert_previous_epoch_deposits::<T>(
777826
operator_id,
778827
deposit,
779828
domain_stake_summary.current_epoch_index,
829+
Some(share_price.clone()),
780830
)?;
781831
Ok(deposit.known.shares)
782832
})?;
@@ -787,6 +837,7 @@ pub(crate) fn do_withdraw_stake<T: Config>(
787837
operator_id,
788838
withdrawal,
789839
domain_stake_summary.current_epoch_index,
840+
Some(share_price.clone()),
790841
)?;
791842
if withdrawal.withdrawals.len() as u32 >= T::WithdrawalLimit::get() {
792843
return Err(Error::TooManyWithdrawals);
@@ -816,9 +867,6 @@ pub(crate) fn do_withdraw_stake<T: Config>(
816867

817868
(remaining_shares, to_withdraw)
818869
} else {
819-
let share_price =
820-
current_share_price::<T>(operator_id, operator, &domain_stake_summary)?;
821-
822870
let remaining_storage_fee =
823871
Perquintill::from_rational(remaining_shares.into(), known_shares.into())
824872
.mul_floor(deposit.known.storage_fee_deposit);
@@ -948,16 +996,18 @@ pub(crate) fn do_unlock_funds<T: Config>(
948996
Error::OperatorNotRegistered
949997
);
950998

951-
let current_domain_epoch_index = DomainStakingSummary::<T>::get(operator.current_domain_id)
952-
.ok_or(Error::DomainNotInitialized)?
953-
.current_epoch_index;
999+
let stake_summary = DomainStakingSummary::<T>::get(operator.current_domain_id)
1000+
.ok_or(Error::DomainNotInitialized)?;
1001+
let current_domain_epoch_index = stake_summary.current_epoch_index;
1002+
let share_price = current_share_price::<T>(operator_id, &operator, &stake_summary)?;
9541003

9551004
Withdrawals::<T>::try_mutate_exists(operator_id, nominator_id.clone(), |maybe_withdrawal| {
9561005
let withdrawal = maybe_withdrawal.as_mut().ok_or(Error::MissingWithdrawal)?;
9571006
do_convert_previous_epoch_withdrawal::<T>(
9581007
operator_id,
9591008
withdrawal,
9601009
current_domain_epoch_index,
1010+
Some(share_price),
9611011
)?;
9621012

9631013
ensure!(!withdrawal.withdrawals.is_empty(), Error::MissingWithdrawal);
@@ -1145,6 +1195,7 @@ pub(crate) fn do_unlock_nominator<T: Config>(
11451195
operator_id,
11461196
&mut deposit,
11471197
current_domain_epoch_index,
1198+
Some(share_price.clone()),
11481199
)?;
11491200

11501201
// if there are any withdrawals from this operator, account for them
@@ -1163,6 +1214,7 @@ pub(crate) fn do_unlock_nominator<T: Config>(
11631214
operator_id,
11641215
&mut withdrawal,
11651216
current_domain_epoch_index,
1217+
Some(share_price.clone()),
11661218
)?;
11671219
Ok((
11681220
withdrawal.total_withdrawal_amount,
@@ -1569,8 +1621,8 @@ pub(crate) mod tests {
15691621
use crate::staking_epoch::{do_finalize_domain_current_epoch, do_slash_operator};
15701622
use crate::tests::{ExistentialDeposit, MinOperatorStake, RuntimeOrigin, Test, new_test_ext};
15711623
use crate::{
1572-
BalanceOf, Error, MAX_NOMINATORS_TO_SLASH, NominatorId, OperatorEpochSharePrice,
1573-
SlashedReason, bundle_storage_fund,
1624+
AllowedDefaultSharePriceEpoch, BalanceOf, Error, MAX_NOMINATORS_TO_SLASH, NominatorId,
1625+
OperatorEpochSharePrice, SlashedReason, bundle_storage_fund,
15741626
};
15751627
use frame_support::traits::Currency;
15761628
use frame_support::traits::fungible::Mutate;
@@ -2318,6 +2370,9 @@ pub(crate) mod tests {
23182370
}
23192371

23202372
// Export the macro for use in other modules (and earlier in this file).
2373+
use crate::staking_epoch::tests::{
2374+
get_current_epoch, operator_share_price_does_not_exist, operator_share_price_exists,
2375+
};
23212376
pub(crate) use prop_assert_approx;
23222377

23232378
/// Rounding down factor for property tests to account for arithmetic precision errors.
@@ -3310,6 +3365,7 @@ pub(crate) mod tests {
33103365
operator_id,
33113366
withdrawal,
33123367
domain_stake_summary.current_epoch_index,
3368+
None,
33133369
)
33143370
.unwrap();
33153371
assert_eq!(
@@ -3427,6 +3483,7 @@ pub(crate) mod tests {
34273483
operator_id,
34283484
maybe_withdrawal.as_mut().unwrap(),
34293485
domain_stake_summary.current_epoch_index,
3486+
None,
34303487
)
34313488
})
34323489
.unwrap();
@@ -3560,8 +3617,13 @@ pub(crate) mod tests {
35603617
Default::default(),
35613618
BTreeMap::from_iter(nominators),
35623619
);
3620+
assert_eq!(get_current_epoch(domain_id), 1);
3621+
operator_share_price_exists(domain_id, vec![0], 0);
35633622

35643623
do_finalize_domain_current_epoch::<Test>(domain_id).unwrap();
3624+
assert_eq!(get_current_epoch(domain_id), 2);
3625+
operator_share_price_exists(domain_id, vec![0], 1);
3626+
35653627
let domain_stake_summary = DomainStakingSummary::<Test>::get(domain_id).unwrap();
35663628
assert_eq!(domain_stake_summary.current_total_stake, init_total_stake);
35673629

@@ -3585,6 +3647,8 @@ pub(crate) mod tests {
35853647
)
35863648
.unwrap();
35873649
do_finalize_domain_current_epoch::<Test>(domain_id).unwrap();
3650+
assert_eq!(get_current_epoch(domain_id), 3);
3651+
operator_share_price_exists(domain_id, vec![0], 2);
35883652

35893653
// Manually convert previous withdrawal in share to balance
35903654
let domain_stake_summary = DomainStakingSummary::<Test>::get(domain_id).unwrap();
@@ -3594,6 +3658,7 @@ pub(crate) mod tests {
35943658
operator_id,
35953659
maybe_withdrawal.as_mut().unwrap(),
35963660
domain_stake_summary.current_epoch_index,
3661+
None,
35973662
)
35983663
})
35993664
.unwrap();
@@ -3649,6 +3714,8 @@ pub(crate) mod tests {
36493714
.unwrap();
36503715

36513716
do_finalize_domain_current_epoch::<Test>(domain_id).unwrap();
3717+
assert_eq!(get_current_epoch(domain_id), 4);
3718+
operator_share_price_does_not_exist(domain_id, vec![0], 3);
36523719

36533720
let domain_stake_summary = DomainStakingSummary::<Test>::get(domain_id).unwrap();
36543721
assert!(!domain_stake_summary.next_operators.contains(&operator_id));
@@ -3996,6 +4063,7 @@ pub(crate) mod tests {
39964063

39974064
let mut ext = new_test_ext();
39984065
ext.execute_with(|| {
4066+
AllowedDefaultSharePriceEpoch::<Test>::set((domain_id, 0).into());
39994067
let (operator_id, _) = register_operator(
40004068
domain_id,
40014069
operator_account,

0 commit comments

Comments
 (0)