-
Notifications
You must be signed in to change notification settings - Fork 248
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
Extrinsic Params Refinement #1439
Extrinsic Params Refinement #1439
Conversation
/// Note: This function will **not** refine the params to use the latest account nonce and the latest block hash/number. | ||
/// Instead your call will get default values of nonce = 0 and mortality = Immortal for the signed extensions, if the params | ||
/// have not been 'refined' before. | ||
pub fn create_partial_signed_offline<Call>( |
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 sure about the name here, maybe create_partial_signed_unrefined
? Ideally, we would have different implementations of create_partial_signed
for offline and online clients, but without specialization
I don't see how that would be possible.
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.
An alternative to specialization with stable rust is the autoref workaround. (James pointed this out a while ago and we ended up using it in substrate for metadata v15)
The default
implementation should be implemented on the &T
. Whenever users what to override that, they must implement it on T
. Then the compiler will add as many references as needed to T to find the method call. Not entirely sure if this is applicable 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.
Hehe it might be possible but we probably shouldn't go down that route for fear of over-complexifying :D
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 like the _offline
suffix too FWIW, and also this suffix plays nicely with my suggested comment tweak so that it is consistent that if we call an _offline
function we get worse defaults because it runs offline.
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.
Ah I remember reading dtolnays article about autoref specialization on stable rust a while ago, but it seemed like a weird workaround to me.
subxt/src/config/refine_params.rs
Outdated
pub trait RefineParams<T: Config> { | ||
/// Refine params to an extrinsic. There is usually some notion of 'the param is already set/unset' in types implementing this trait. | ||
/// The refinement should most likely not affect cases where a param is in a 'is already set by the user' state. | ||
fn refine(&mut self, _account_nonce: u64, _block_number: u64, _block_hash: T::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.
Are there currently other types that substrate/polkadot extensions take for constructing their state?
I'm thinking more about how we could easily extend this in the future without causing a breaking change
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.
One thing that we could do to maybe minimise the risk of breaking changes a little is to wrap these into a struct like:
pub struct RefinableParamsData<T: Config> {
account_nonce: u64,
block_number: u64,
block_hash: T::Hash
}
impl <T: Config> RefinableParamsData {
pub fn account_nonce(&self) -> u64 { ... }
pub fn block_number(&self) -> u64 { ... }
pub fn block_hash(&self) -> u64 { ... }
}
That way, we can add params without changing the existing interface :)
subxt/src/book/usage/transactions.rs
Outdated
//! // here, or can use `create_partial_signed` to fetch the correct nonce. | ||
//! let partial_tx = client.tx().create_partial_signed_with_nonce( | ||
//! // Construct the tx but don't sign it. The account nonce here defaults to 0. | ||
//! // You Can use `create_partial_signed` to fetch the correct nonce. |
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 Can use `create_partial_signed` to fetch the correct nonce. | |
//! // You can use `create_partial_signed` to fetch the correct nonce. |
subxt/src/config/extrinsic_params.rs
Outdated
client: Client, | ||
other_params: Self::OtherParams, | ||
other_params: Self::Params, |
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.
other_params: Self::Params, | |
params: Self::Params, |
subxt/src/config/mod.rs
Outdated
@@ -12,6 +12,7 @@ mod default_extrinsic_params; | |||
mod extrinsic_params; | |||
|
|||
pub mod polkadot; | |||
pub mod refine_params; |
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 wouldn't export this mod I reckon; there's no real need since the only item it exports is below anyway :)
subxt/src/tx/tx_client.rs
Outdated
/// Fetch the latest block header and account nonce from the backend and use them to refine [`ExtrinsicParams::Params`]. | ||
pub async fn refine_params( |
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 wouldn't publically expose this; I think in general that I don't want users to really know about "refining params". If they are offline, they can obtain the relevant data and configure the params exactly as they want, and if they are online then we will be smart and apply some sensible defaults for them is all :)
subxt/src/tx/tx_client.rs
Outdated
/// Note: This function will **not** refine the params to use the latest account nonce and the latest block hash/number. | ||
/// Instead your call will get default values of nonce = 0 and mortality = Immortal for the signed extensions, if the params | ||
/// have not been 'refined' before. |
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.
/// Note: This function will **not** refine the params to use the latest account nonce and the latest block hash/number. | |
/// Instead your call will get default values of nonce = 0 and mortality = Immortal for the signed extensions, if the params | |
/// have not been 'refined' before. | |
/// Note: if not provided, the default account nonce will be set to 0 and the default mortality will be _immortal_. | |
/// This is because this method runs offline, and so is unable to fetch the data needed for more appropriate values. |
Just to make it clear that because offline, we have to use worse defaults, and to avoid mentioning any new concept like "refining params"
subxt/src/tx/tx_client.rs
Outdated
/// Note: This function will **not** refine the params to use the latest account nonce and the latest block hash/number. | ||
/// Instead your call will get default values `nonce = 0` and `mortality = Immortal` for the signed extensions, if the | ||
/// params have not been manually set or 'refined' before. |
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.
/// Note: This function will **not** refine the params to use the latest account nonce and the latest block hash/number. | |
/// Instead your call will get default values `nonce = 0` and `mortality = Immortal` for the signed extensions, if the | |
/// params have not been manually set or 'refined' before. | |
/// Note: if not provided, the default account nonce will be set to 0 and the default mortality will be _immortal_. | |
/// This is because this method runs offline, and so is unable to fetch the data needed for more appropriate values. |
As above
Some small suggestions and such but overall this looks really good, and doesn't feel like it adds too much complexity in the end while giving us the ability to set some great defaults! It's sortof a shame that we have to ask for the block hash and account nonce etc now every time, but I'm ok with it for now! (if we think this perf hit is an issue here then we can potentially as an optimisation we could expand the |
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 looks great to me; good job Tadeo!
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.
Nice job here!
Follow-Up PR to #1432, see discussion between James and me there to get some background information.
This PR introduces a new trait
RefineParams
that theOtherParams
(renamed toParams
) of signed extensions must implement:The 'refinement' of params is executed by an online client before creating an extrinsic and can automatically configure the newest account nonce for
CheckNonce
and the latest block hash forCheckMortality
.