-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add task to let MSP charge user every X blocks #268
base: main
Are you sure you want to change the base?
Conversation
if let Some(notify_period) = msp_charging_freq { | ||
self.with_notify_period(notify_period.clone()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not super happy for having to do this with all different setup
function. It is a bit redundant with the builder strategy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. In fact all the functions that are not storage-layer-or-provider-type-specific (i.e. that they don't need to have a special implementation for a provider type and storage layer), I'd leave them out of this setup
.
In other words, to make proper use of the builder pattern I would:
- Remove the use of
with_notify_period
from here, and call it inservice.rs
(ininit_sh_builder()
), in case the CLI parameter was passed. - Do the same with
with_max_storage_capacity
,with_jump_capacity
,with_retry_timeout
, as they seem to be called in the same way, regarless of what the provider type and storage layer is. Well almost, in the User is different. But anyway, these tiny initialisation differences are exactly what the builder pattern is meant to be good for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, I'd like to get @snowmead involved since he was heavily involved in this code.
.storage_hub_handler | ||
.blockchain | ||
.query_storage_provider_id(None) | ||
.await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't MSP task have access to their own msp id ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nicer to not have to do this, indeed.
But when starting up, the only known thing is the account - the provider id associated is known by the runtime.
} | ||
|
||
// Verify that the MSP charged the users after the notified | ||
await userApi.assert.eventPresent("paymentStreams", "PaymentStreamCharged"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably verify the amount charged to make sure it is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
} | ||
|
||
const txs = []; | ||
for (let i = 0; i < source.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for readability this can just be for (const file of source) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use ´i´ as the index for the destination too. In order to use a for of loop we would need to modify a bit more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, tests look lots better. Had some follow up comments but low priority
invariant(fileKeys2.length === 2, "Expected 2 file keys"); | ||
|
||
// Allow time for the MSP to update the local forest root | ||
await sleep(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an associated log line to wait on?
await userApi.sealBlock(txs, shUser); | ||
|
||
// Allow time for the MSP to receive and store the file from the user | ||
await sleep(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be better to wait for the log line: File upload complete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly great job! Just a handful of minor suggestions and comments.
fn check_for_notify(&self, block_number: &BlockNumber) { | ||
if let Some(np) = self.notify_period { | ||
if block_number % np == 0 { | ||
self.emit(NotifyPeriod {}); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fits better in utils.rs
node/src/cli.rs
Outdated
@@ -109,6 +109,12 @@ pub struct ProviderConfigurations { | |||
/// Extrinsic retry timeout in seconds. | |||
#[clap(long, default_value = "60")] | |||
pub extrinsic_retry_timeout: u64, | |||
|
|||
/// MSP charging fees frequency. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to add more info like the unit of this parameter. For example, is it in number of blocks? And if so, could be helpful to give some parameter like "Setting it to 600, with 6 seconds blocks, means charging every 1 hour".
Also, wouldn't this be a period instead of a frequency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes period is better. I changed every 'freq' with 'period'.
} | ||
|
||
// Verify that the MSP charged the users after the notified | ||
await userApi.assert.eventPresent("paymentStreams", "PaymentStreamCharged"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
node/src/tasks/msp_charge_fees.rs
Outdated
|
||
match charging_result { | ||
Ok(submitted_transaction) => { | ||
info!(target: LOG_TARGET, "Submitted extrinsic to charge users with debt: {}", submitted_transaction.hash()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to make this a debug
log.
let charging_result = self | ||
.storage_hub_handler | ||
.blockchain | ||
.send_extrinsic(call, Tip::from(0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to use watch_for_success
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For BSP, we are not watching for success. Do we want to have it there too ?
use crate::tasks::{FileStorageT, MspForestStorageHandlerT, StorageHubHandler}; | ||
|
||
const LOG_TARGET: &str = "msp-charge-fees-task"; | ||
const MIN_DEBT: Balance = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constants and the growing number of configuration parameters for BSPs/MSPs makes it increasingly compelling to have a way to configure them through a configuration file (like a .yml/.toml or similar). If you feel like that's something you'd like to do, setup a task with @santikaplan.
This PR add a
NotifyPeriod
event that would be triggered every X blocks. It helps notifyng the MSP task that X blocks has passed and that it can charge users for their service.The amount of blocks (aka the msp charging frequency) is a configurable value that can be passed through the CLI.