Skip to content

Commit 41c24ec

Browse files
authored
fix: 🐛 Use Proofs Dealer tick when requesting last proof submitters in Payment Streams pallet (#217)
* fix: 🐛 Use Proofs Dealer tick when requesting last proof submitters in Payment Streams pallet * test: ✅ Add test case where Proof Submitters tick stops * chore: 🏷️ Update `api-augment`
1 parent 8806cc2 commit 41c24ec

File tree

13 files changed

+140
-10
lines changed

13 files changed

+140
-10
lines changed

api-augment/dist/types/interfaces/augment-api-query.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,15 @@ declare module "@polkadot/api-base/types/storage" {
10671067
[H256]
10681068
> &
10691069
QueryableStorageEntry<ApiType, [H256]>;
1070+
/**
1071+
* The last tick from the Providers Proof Submitters pallet that was registered.
1072+
*
1073+
* This is used to keep track of the last tick from the Providers Proof Submitters pallet, that this pallet
1074+
* registered. For the tick in this storage element, this pallet already knows the Providers that submitted
1075+
* a valid proof.
1076+
**/
1077+
lastSubmittersTickRegistered: AugmentedQuery<ApiType, () => Observable<u32>, []> &
1078+
QueryableStorageEntry<ApiType, []>;
10701079
/**
10711080
* A counter of blocks for which Providers can charge their streams.
10721081
*

api-augment/src/interfaces/augment-api-query.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,15 @@ declare module "@polkadot/api-base/types/storage" {
10531053
[H256]
10541054
> &
10551055
QueryableStorageEntry<ApiType, [H256]>;
1056+
/**
1057+
* The last tick from the Providers Proof Submitters pallet that was registered.
1058+
*
1059+
* This is used to keep track of the last tick from the Providers Proof Submitters pallet, that this pallet
1060+
* registered. For the tick in this storage element, this pallet already knows the Providers that submitted
1061+
* a valid proof.
1062+
**/
1063+
lastSubmittersTickRegistered: AugmentedQuery<ApiType, () => Observable<u32>, []> &
1064+
QueryableStorageEntry<ApiType, []>;
10561065
/**
10571066
* A counter of blocks for which Providers can charge their streams.
10581067
*

api-augment/storagehub.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

pallets/bucket-nfts/src/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ impl ProofSubmittersInterface for MockSubmittingProviders {
361361
None
362362
}
363363

364+
fn get_current_tick() -> Self::TickNumber {
365+
System::block_number()
366+
}
367+
364368
fn get_accrued_failed_proof_submissions(_provider_id: &Self::ProviderId) -> Option<u32> {
365369
None
366370
}

pallets/file-system/src/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ impl ProofSubmittersInterface for MockSubmittingProviders {
295295
None
296296
}
297297

298+
fn get_current_tick() -> Self::TickNumber {
299+
System::block_number()
300+
}
301+
298302
fn get_accrued_failed_proof_submissions(_provider_id: &Self::ProviderId) -> Option<u32> {
299303
None
300304
}

pallets/payment-streams/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ pub mod pallet {
160160
ValueQuery,
161161
>;
162162

163+
/// The last tick from the Providers Proof Submitters pallet that was registered.
164+
///
165+
/// This is used to keep track of the last tick from the Providers Proof Submitters pallet, that this pallet
166+
/// registered. For the tick in this storage element, this pallet already knows the Providers that submitted
167+
/// a valid proof.
168+
#[pallet::storage]
169+
pub type LastSubmittersTickRegistered<T: Config> =
170+
StorageValue<_, BlockNumberFor<T>, ValueQuery>;
171+
163172
/// The mapping from a user to if it has been flagged for not having enough funds to pay for its requested services.
164173
///
165174
/// This is used to flag users that do not have enough funds to pay for their requested services, so other Providers

pallets/payment-streams/src/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ impl ProofSubmittersInterface for MockSubmittingProviders {
255255
Some(set)
256256
}
257257

258+
fn get_current_tick() -> Self::TickNumber {
259+
System::block_number()
260+
}
261+
258262
fn get_accrued_failed_proof_submissions(_provider_id: &Self::ProviderId) -> Option<u32> {
259263
None
260264
}

pallets/payment-streams/src/tests.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,7 @@ mod fixed_rate_streams {
16541654
);
16551655

16561656
// Set the last valid proof of the payment stream from Bob to Alice to block 123 (represented by Alice's account ID)
1657-
// Since we are using the mocked ReadProofSubmittersInterface, we can pass the account ID as the
1657+
// Since we are using the mocked ProofSubmittersInterface, we can pass the account ID as the
16581658
// block number to the `on_poll` hook and it will consider that Provider as one that submitted a proof
16591659
run_to_block(alice_on_poll);
16601660

@@ -1665,7 +1665,62 @@ mod fixed_rate_streams {
16651665
// The payment stream should be updated with the correct last valid proof
16661666
assert_eq!(
16671667
alice_last_chargeable_info.last_chargeable_tick,
1668-
System::block_number() - 1 // We subtract one since the chargeable info is set for the previous block always
1668+
System::block_number()
1669+
);
1670+
});
1671+
}
1672+
1673+
#[test]
1674+
fn update_last_chargeable_tick_with_submitters_paused_works() {
1675+
ExtBuilder::build().execute_with(|| {
1676+
let alice_on_poll: AccountId = 123;
1677+
let bob: AccountId = 1;
1678+
1679+
// Register Alice as a MSP with 100 units of data and get her MSP ID
1680+
register_account_as_msp(alice_on_poll, 100);
1681+
let alice_msp_id =
1682+
<StorageProviders as ReadProvidersInterface>::get_provider_id(alice_on_poll)
1683+
.unwrap();
1684+
1685+
// Create a payment stream from Bob to Alice of 10 units per block
1686+
let rate: BalanceOf<Test> = 10;
1687+
assert_ok!(
1688+
<PaymentStreams as PaymentStreamsInterface>::create_fixed_rate_payment_stream(
1689+
&alice_msp_id,
1690+
&bob,
1691+
rate
1692+
)
1693+
);
1694+
1695+
// Set the last valid proof of the payment stream from Bob to Alice to block 123 (represented by Alice's account ID)
1696+
// Since we are using the mocked ProofSubmittersInterface, we can pass the account ID as the
1697+
// block number to the `on_poll` hook and it will consider that Provider as one that submitted a proof.
1698+
// We advance to one block before Alice's turn.
1699+
run_to_block(alice_on_poll - 1);
1700+
1701+
// Mock blocks advancing where the Proofs Submitters' tick is stopped.
1702+
let tick_before = crate::OnPollTicker::<Test>::get();
1703+
for _ in 0..10 {
1704+
// For that, we run `on_poll` hooks of this Payment Stream's pallet, without actually advancing blocks.
1705+
PaymentStreams::on_poll(System::block_number(), &mut WeightMeter::new());
1706+
}
1707+
let tick_after = crate::OnPollTicker::<Test>::get();
1708+
assert!(tick_before == tick_after - 10);
1709+
1710+
// Now the Proof Submitters pallet "resumes", so we advance one more block to when
1711+
// it is Alice's turn to be in the valid proofs submitters set.
1712+
run_to_block(alice_on_poll);
1713+
1714+
// Get Alice's last chargeable information
1715+
let alice_last_chargeable_info =
1716+
PaymentStreams::get_last_chargeable_info(&alice_msp_id);
1717+
let current_tick = crate::OnPollTicker::<Test>::get();
1718+
1719+
// The payment stream should be updated and considering that the last chargeable tick
1720+
// is the current tick for the Payment Streams pallet.
1721+
assert_eq!(
1722+
alice_last_chargeable_info.last_chargeable_tick,
1723+
current_tick
16691724
);
16701725
});
16711726
}

pallets/payment-streams/src/utils.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -967,25 +967,47 @@ where
967967
Ok(())
968968
}
969969

970-
/// This function gets the Providers that submitted a valid proof in the last tick using the `ReadProofSubmittersInterface`,
970+
/// This function gets the Providers that submitted a valid proof in the last tick using the `ProofSubmittersInterface`,
971971
/// and updates the last chargeable tick and last chargeable price index of those Providers.
972972
pub fn do_update_last_chargeable_info(
973973
n: BlockNumberFor<T>,
974974
weight: &mut frame_support::weights::WeightMeter,
975975
) {
976-
// Get last tick's number
977-
let n = n.saturating_sub(One::one());
978-
// Get the Providers that submitted a valid proof in the last tick, if there are any
976+
// Get the previous tick from the Providers Proof Submitters pallet.
977+
let submitters_prev_tick =
978+
<T::ProvidersProofSubmitters as ProofSubmittersInterface>::get_current_tick()
979+
.saturating_sub(One::one());
980+
weight.consume(T::DbWeight::get().reads(1));
981+
982+
// Check if we already registered this tick from the Providers Proof Submitters pallet.
983+
let last_submitters_tick_registered = LastSubmittersTickRegistered::<T>::get();
984+
weight.consume(T::DbWeight::get().reads(1));
985+
986+
// If we already registered this tick from the Providers Proof Submitters pallet, we don't need to do anything.
987+
if submitters_prev_tick <= last_submitters_tick_registered {
988+
return;
989+
}
990+
991+
// Update the last submitters tick registered.
992+
LastSubmittersTickRegistered::<T>::set(submitters_prev_tick);
993+
weight.consume(T::DbWeight::get().writes(1));
994+
995+
// Get the Providers that submitted a valid proof in the last tick from the Providers Proof Submitters pallet,
996+
// if there's any
979997
let proof_submitters =
980-
<T::ProvidersProofSubmitters as ProofSubmittersInterface>::get_proof_submitters_for_tick(&n);
998+
<T::ProvidersProofSubmitters as ProofSubmittersInterface>::get_proof_submitters_for_tick(&submitters_prev_tick);
981999
weight.consume(T::DbWeight::get().reads(1));
9821000

983-
// If there are any proof submitters in the last tick
1001+
// If there are any proof submitters in the last tick...
9841002
if let Some(proof_submitters) = proof_submitters {
9851003
// Update all Providers
9861004
// Iterate through the proof submitters and update their last chargeable tick and last chargeable price index
9871005
for provider_id in proof_submitters {
988-
// Update the last chargeable tick and last chargeable price index of the Provider
1006+
// Update the last chargeable tick and last chargeable price index of the Provider.
1007+
// The last chargeable tick is set to the current tick of THIS PALLET. That means, if the tick from
1008+
// the Providers Proof Submitters pallet is stalled for some time, and this pallet continues to increment
1009+
// its tick, when the Providers Proof Submitters pallet continues to increment its tick, this pallet will
1010+
// allow Providers to charge for the time that the Providers Proof Submitters pallet has been stalled.
9891011
let accumulated_price_index = AccumulatedPriceIndex::<T>::get();
9901012
LastChargeableInfo::<T>::mutate(provider_id, |provider_info| {
9911013
provider_info.last_chargeable_tick = n;

pallets/proofs-dealer/src/mock.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ impl ProofSubmittersInterface for MockSubmittingProviders {
196196
None
197197
}
198198

199+
fn get_current_tick() -> Self::TickNumber {
200+
System::block_number()
201+
}
202+
199203
fn get_accrued_failed_proof_submissions(_provider_id: &Self::ProviderId) -> Option<u32> {
200204
None
201205
}

0 commit comments

Comments
 (0)