-
Notifications
You must be signed in to change notification settings - Fork 72
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
Encode extrinsic call. fix #505 #507
Conversation
16c0210
to
a3c6000
Compare
25c2fc7
to
b7ba184
Compare
)?; | ||
|
||
// Tranform the call into a runtime call and encode it. | ||
let call: <T as crate::Config>::RuntimeCall = Call::schedule_xcmp_task { |
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.
Tranform the call into a runtime call and encode it.
_ => None, | ||
}; | ||
|
||
Self::deposit_event(Event::<T>::TaskScheduled { who: owner_id, task_id, schedule_as }); |
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.
Move TaskScheduled
event out.
/// Validate and schedule task. | ||
/// This will also charge the execution fee. | ||
pub fn validate_and_schedule_task( | ||
action: ActionOf<T>, | ||
owner_id: AccountOf<T>, | ||
schedule: Schedule, | ||
abort_errors: Vec<Vec<u8>>, | ||
) -> DispatchResult { | ||
) -> Result<TaskIdV2, DispatchError> { |
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.
Return TaskIdV2
or DispatchError
.
pallets/automation-time/src/lib.rs
Outdated
|
||
let schedule = schedule.validated_into::<T>()?; | ||
Self::deposit_event(Event::<T>::TaskScheduled { |
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.
Deposit TaskScheduled
event.
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.
Before this change validate_and_schedule_task does 2 things:
- write the task into storage
- generate the event
so the caller just need to call it, and never have to worry about manually make the the TaskSchedule event manually. But after this change, we have to remember to also call generate TaskSchedule event whenever we call validate_and_schedule_task
I had a feeling we will eventually make a mistake and forgot the second call deposit_event.
I think we should find a way to just need to write one task schedule function and it handle both for us.
maybe create a new helper function for that? and validate_and_schedule_task
can be make private.
open to idea but i think it's very useful to just call that function and it does all the setup.
on thsi new approach you can see that we have to add the extra TaskSchedule everywhere after that.
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.
If we need to throw an event in the validate_and_schedule_task
function, we should pass the pre-constructed encoded_call
into the validate_and_schedule_task
function.
Because the encoded_call
for schedule_xcmp_task
needs to be constructed using the original function parameters and cannot be built within the validate_and_schedule_task
function by using the action
parameter passed to it.
That's why I opted to split Self::deposit_event(Event::<T>::TaskScheduled { ... })
out this function.
Hi @chrisli30 , what are your thoughts on this?
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, I understand it.
What I mean is the reason the previous dev wrote it that way is to ensure we don't forgot.
Now with this approach, everytime we want to schedule a task, we will need to always make 2 call:
- validated_and_schedule_task
- deposit_event(TaskSchedule)
Therefore I think it make sense to introduce a new helper function that does:
- take the right input
- call validated_and_schedule_task
- call deposit_event(TaskSchedule)
Make it work in a way where we cannot make mistake.
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 wrote the helper function called schedule_task_with_event
. What are your thoughts on it? @v9n
Pseudocode:
pub fn schedule_task_with_event(
action: ActionOf<T>,
owner_id: AccountOf<T>,
schedule: Schedule,
abort_errors: Vec<Vec<u8>>,
encoded_call: Option<Vec<u8>>,
) -> DispatchResult {
// Schedule the task.
let task_id: TaskIdV2 = Self::validate_and_schedule_task(
action.clone(),
who.clone(),
schedule_value,
vec![],
)?;
Self::deposit_event(Event::<T>::TaskScheduled {
who,
task_id,
schedule_as,
encoded_call: Some(encoded_call),
});
Ok(())
}
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.
Looks good.
I would call it just schedule_task
though. But leave that to your to decide.
One last request can you make validate_and_schedule_task to not public, we don't want anyone to call it directly. (inside they can still call it obviously) and instead everyone will just call schedule_task
moving forward and this function will handle all the setup.
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.
Okay!
However, the name "schedule_task" has already been used.
@@ -1034,6 +1035,62 @@ fn schedule_xcmp_works() { | |||
}) | |||
} | |||
|
|||
#[test] | |||
fn schedule_xcmp_task_and_check_encoded_call_success() { |
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.
Add schedule_xcmp_task_and_check_encoded_call_success
test.
c7ec487
to
8aa3d7b
Compare
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo> | ||
+ GetDispatchInfo | ||
+ From<frame_system::Call<Self>> | ||
+ IsSubType<Call<Self>> | ||
+ IsType<<Self as frame_system::Config>::RuntimeCall>; | ||
+ IsType<<Self as frame_system::Config>::RuntimeCall> | ||
+ From<crate::Call<Self>>; |
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.
Specify that RuntimeCall
must implement the From<crate::Call<Self>>
trait, enabling the conversion of Pallet::Call
to RuntimeCall
.
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.
The screenshot of the encoded call looks legit. I have left one comment. @v9n , could you double check the code?
What is the reason of this type re-definition? In Substrate version 0.9.38, the definition of Related discussion: |
@@ -217,18 +217,18 @@ benchmarks! { | |||
let schedule = ScheduleParam::Fixed { execution_times: times }; | |||
|
|||
let caller: T::AccountId = account("caller", 0, SEED); | |||
let call: <T as Config>::Call = frame_system::Call::remark { remark: vec![] }.into(); | |||
let call: <T as Config>::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); |
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.
can you see if we need .into()
. I think Rust might be able to auto call this already (I saw similar suggestion by Clippy a while ago).
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 tried removing into() but encountered some errors.
error[E0308]: mismatched types
--> pallets/automation-time/src/benchmarking.rs:220:42
|
220 | let call: <T as Config>::RuntimeCall = frame_system::Call::remark { remark: vec![] };
| -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `Call<_>`
| |
| expected due to this
|
= note: expected associated type `<T as pallet::Config>::RuntimeCall`
found enum `frame_system::Call<_>`
= help: consider constraining the associated type `<T as pallet::Config>::RuntimeCall` to `frame_system::Call<_>` or calling a method that returns `<T as pallet::Config>::RuntimeCall`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
help: call `Into::into` on this expression to convert `frame_system::Call<_>` into `<T as pallet::Config>::RuntimeCall`
|
220 | let call: <T as Config>::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into();
| +++++++
For more information about this error, try `rustc --explain E0308`.
error: could not compile `pallet-automation-time` (lib) due to previous error
What do you think the correct way to write it should be?
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.
That's fine. I was just asking.
Because I saw before in a similar PR https://github.com/OAK-Foundation/OAK-blockchain/pull/421/files this tool remove all the .into()
so that's why I was just asking.
If Rust cannot infer it for this case we will need to explicitly call it. no problem.
pallets/automation-time/src/lib.rs
Outdated
Self::deposit_event(Event::<T>::TaskScheduled { | ||
who, | ||
task_id, | ||
schedule_as: Self::get_schedule_as_from_action(action), |
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.
why do we need to call get_schedule_as_from_action
? shouldn't we just access schedule_as
variable on line 461 directly?
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, You're right. 👍
Fixed!
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 think the code can be improved. it's a bit repetivei and there is something I'm not clear.
a41fe75
to
1789887
Compare
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.
lgtm
Update the TaskScheduled event by incorporating the encodedCall and excluding it from the TaskTriggered event.
Use the call parameter of scheduleDynamicDispatch as encodedCall.
Use the entire extrinsic of scheduleXcmpTask as encodedCall.
Tests:
Add
schedule_xcmp_task_and_check_encoded_call_success
testManual testing:
TaskTriggered
event:Decoded call: