-
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
Subscribe to Runtime upgrades for proper extrinsic construction #513
Conversation
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
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 found the API a little hard to use for end-users.
Basically, I was kind of expecting subxt to spawn a separate task that does the runtime subscription for the user and update the runtime version under the hood. Is that too opinionated?
After the a runtime upgrade the subxt client
is mostly useless anyway (e.g. the spec version gets bumped)
Otherwise, the code looks good
This is an interesting point! I was also expecting subxt to spawn something under the hood and do this transparently, but as @lexnv points out, Let's have a think about this and try to find the simplest API possible to update the runtime version appropriately that keeps subxt agnostic of the runtime used. Now that the metadata validation PR is in, I'd hope that after a runtime upgrade subxt is still mostly using the correct types, and as long as we make sure to pull new metadata from the node on a runtime update, we can continue to properly validate calls. I note that we are pulling in Tokio from |
A random stab at what an API could look like: // spawn a background task to keep subxt up to date w.r.t node runtime updates.
tokio::spawn(async move {
api.client.perform_automatic_runtime_updates().await // awaits forever.
});
// use the api however you like in the meantime, and know it'll be kept uptodate in the background...
api.tx().balances()... How this would work roughly is that the background update task would subscribe to runtime updates, and when it receives one, do something like:
The idea is that as soon as we know an update has happened, block any pending requests until we have new runtime + metadata and can send them with the correct versions and validate them against the correct metadata. It'll require a bit of care to do properly (need to handle errors while locked and such). |
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
This revision adds an alternative to those described above. Unfortunately, the client cannot be moved inside the tokio task and reutilized further. Having usability in mind as a first step, an appropriate solution to this would be exposing a wrapper of the
For the first case, the This basically would translate into the following interaction with the API let update_client = api.client.updates();
tokio::spawn(async move {
update_client.perform_runtime_updates().await;
});
// Use API further for the main use-case
api.tx().balances()... |
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Revert "Fix test deadlock" This reverts commit 4a79933. Revert "Update examples and integration-tests" This reverts commit 5423f6e. Revert "Remove unused dependencies" This reverts commit e8ecbab. Revert "codegen: Use async API to handle async locking" This reverts commit ced4646. Revert "subxt: Block executor while decoding dynamic events" This reverts commit 8b3ba4a. Revert "subxt: Switch to async::Mutex" This reverts commit f5bde9b.
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Left a couple of very minor comments, but otherwise I think this is great stuff, and am happy to see it merge :) |
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Co-authored-by: James Wilson <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
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 great,
I like the improved API
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.
Awesome stuff :)
There are cases when the subxt
Client
is connected to a substrate nodethat performs a Runtime update (forkless update).
The
RuntimeVersion
is populated when theClient
first connects to a node, but it was neverupdated to keep in sync with the node. The
spec_version
andtransaction_version
of theRuntimeVersion
are included in the transaction parameters. Having the values out of sync meansthat the subxt
Client
can no longer submit any extrinsics.This PR exposes the ability to subscribe to the runtime updates via
subscribe_runtime_version
andreceive notifications when the node performs certain updates.
Customers can easily subscribe to runtime updates utilizing a few lines of code
To keep
subxt
agnostic of the async runtime preferred by the customer, and to simplify thecode needed for providing the updates, the runtime update is handled entirely by the customer.
Furthermore, when a runtime update is detected the customer has the ability to set on the
subxt
Client
the newRuntimeVersion
andMetadata
which would allow for further extrinsics to be submitted.An example to illustrate the runtime update is introduced:
> RUST_LOG=debug cargo run --example subscribe_runtime_updates Balance transfer extrinsic submitted: 0xce5c…003a [2022-05-02T16:31:00Z INFO subxt::updates] Performing runtime update from 100 to 101 [2022-05-02T16:31:00Z DEBUG subxt::updates] Performing metadata update [2022-05-02T16:31:00Z DEBUG subxt::updates] Runtime update completed Balance transfer extrinsic submitted: 0x444e…a06c [2022-05-02T16:31:54Z INFO subxt::updates] Performing runtime update from 101 to 102 [2022-05-02T16:31:54Z DEBUG subxt::updates] Performing metadata update [2022-05-02T16:31:54Z DEBUG subxt::updates] Runtime update completed Balance transfer extrinsic submitted: 0xca0e…df24
Performing the same operations of updating the node, but without updating subxt
Client
itself:Next Steps
Closes #509.