-
Notifications
You must be signed in to change notification settings - Fork 11.7k
rest: introduce transaction resolve and simulation endpoints #19029
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
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
3 Skipped Deployments
|
|
@bmwill is attempting to deploy a commit to the Mysten Labs Team on Vercel. A member of the Team first needs to authorize it. |
hayes-mysten
left a comment
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 examples of the JSON format somewhere I can look at? I can't recall where we landed on standardizing the JSON format. I know we definitely wanted to align the JSON format between the GraphQL API and the TS SDK, but were less sure about how this would work for the rest API. I think it would be good to check in about what differences we have now that there is an actual implementation, and see if we want to align things more before releasing this. Using this will be a bit more complicated if the formats are different between the GraphQL/TS SDK and the rest API
| initial_shared_version: None, | ||
| mutable: None, | ||
| }, | ||
| UnresolvedInputArgument::ImmutableOrOwned(UnresolvedObjectReference { |
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 was trying to track down our original conversations around modeling these inputs, but something thats missing here is the ability to model inputs where we don't know if they are Immutable/Owned/Shared/Receiving, which will be important to support before this can be used by the sdk
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.
Yeah i do how notes from our previous conversation about just wanting to provide the objectid and no other info. we can definitely do that. Do you see there being value in being able to specify these other options? as in allowing you to hint that this should be an owned object/shared objects or would it be simpler to not carry that information and have the server handle it entirely?
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.
What we do in the typescript SDK is to just use a single type that supports providing some of the data: https://sdk.mystenlabs.com/typedoc/interfaces/_mysten_wallet_standard.UnresolvedObjectArg.html
amnn
left a comment
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 is looking great, thanks @bmwill -- sorry it took so long for me to get around to reviewing it. High level thoughts:
- Do we need both
resolveandsimulateat the REST level? It seems likesimulateis offering a strict subset of the features thatresolveoffers today. - There are some tweaks required to get input resolution working w.r.t. shared object deletion. Hayes pointed out one (commands other than
MoveCall) and I pointed out the other (shared object can be passed by value now). - Recording that we had a conversation about a form of input resolution that does basic type inference and BCS serialization where necessary.
| ) -> Result<ResponseContent<TransactionSimulationResponse>> { | ||
| let executor = state.ok_or_else(|| anyhow::anyhow!("No Transaction Executor"))?; | ||
|
|
||
| if transaction.gas_payment.objects.is_empty() { |
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 it necessarily an issue to simulate a transaction without a gas payment? I thought I saw the authority codebase handled that by generating a mock gas object.
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, so the main reason to support a simulate_transaction api thats different from the resolve one is that the input format is different. Resolve takes a json payload that may have holes in it while this one takes a fully formed Transaction and explicitly doesn't try to fill in any holes. I'll add documentation to that affect.
| { | ||
| let package = reader | ||
| .inner() | ||
| .get_object(&(move_call.package.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.
Will this read objects from RocksDB serially, or is it doing something more clever behind the scenes? If the latter, is there a way we can perform all the fetches concurrently, and is that even worth doing?
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 reads are done sequentially I'm not overly concerned with perf on this part though, but we can easily optimize later
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 can look at integrating sui-package-resolver here if we want to improve this. I think we will need to do something like that anyway to handle type inference on pure types etc.
crates/sui-core/src/authority.rs
Outdated
| if transaction.kind().is_system_tx() { | ||
| return Err(SuiError::UnsupportedFeatureError { | ||
| error: "simulate does not support system transactions".to_string(), | ||
| }); | ||
| } |
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 this be the first condition in the function, before loading the epoch?
| .ok_or_else(|| { | ||
| RestError::new( | ||
| axum::http::StatusCode::BAD_REQUEST, | ||
| "unable to find function", |
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.
would it be useful to specify which function is not found in which command?
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 a good point, i'll see what i can do about errors
|
|
||
| /// Given an particular input argument, find all of its uses. | ||
| /// | ||
| /// The returned iterator contains all commands where the arguement is used an an optional index |
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 returned iterator contains all commands where the arguement is used an an optional index | |
| /// The returned iterator contains all commands where the argument is used and an optional index |
| .ok() | ||
| .map(|coin| (object.compute_object_reference(), coin.value())) | ||
| }) | ||
| .take(max_gas_payment_objects as usize); |
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 the gas coins with sufficient gas are above this threshold, wouldn't this condition potentially miss them?
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 if your account is just full of dust this could be an issue, but i did want to try to have some bound on how many objects we'd read in the db, at least to start. This is something we could definitely tweak if needed
|
|
||
| // If the user didn't provide a budget we need to run a quick simulation in order to calculate | ||
| // a good estimated budget to use | ||
| let budget = if let Some(user_provided_budget) = user_provided_budget { |
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.
Should have a check that the provided budget is > than the gas price?
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 now we can assume if someone set a budget themselves they know what they are doing. If they request a simulation they'd get the out of gas error as well.
| reference_gas_price: u64, | ||
| max_gas_budget: u64, | ||
| unresolved_transaction: UnresolvedTransaction, | ||
| ) -> Result<TransactionData> { |
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.
Noob question: could we have an API that returns sui-sdk-types::types::Transaction as well, or would be better to convert this TransactionData into a Transaction where I'd need this, just bcs-serialize-deserialize the types?
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 function is an internal implementation detail so i wouldn't worry about the type here. If you look at the REST entry point you'll find that it does return the the sdk types version of things
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, that's why I was a bit confused 😅
| self.get_backing_package_store().as_ref(), | ||
| )?; | ||
|
|
||
| let (input_objects, receiving_objects) = self.input_loader.read_objects_for_signing( |
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.
Naive question: we want this read_objects_for_signing and not read_objects_for_execution because at signing step a lot of checks are being done?
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 and the other one requires locks and is actually used for real execution, not simulation.
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.
Had a pass, overall looks good to me and it was incredibly useful to put some pieces together in my mind regarding going from a unresolved tx to a resolved one, including seeing how the Unresolved_[X] types are being used.
I hope @amnn has some good feedback as well.
amnn
left a comment
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 too -- most of my comments are reserved for the follow-ups!
#6929) # Description of change - Upstream range: [v1.35.4, v1.36.2) - Port the following Sui's commits which are contained in the single PR MystenLabs/sui#19029 - MystenLabs/sui@bf9ac99 - MystenLabs/sui@ea27dff - MystenLabs/sui@066a6b6 - Descriptions from commits - transaction-executor: add simulate_transaction trait method - rest: introduce transaction simulation endpoint - rest: introduce transaction resolve endpoint - Notes - The extra field `trace_builder_opt` of `execute_transaction_to_effects` was introduced in #6354 - Because the `iota-sdk-types` does not exit, use `iota-sdk2` instead - Remove stable/unstable description in openapi.json from #6922 ## Links to any relevant issues Part of #3990 ## Type of change - Enhancement (a non-breaking change which adds functionality) --------- Co-authored-by: jkrvivian <[email protected]>
#6929) # Description of change - Upstream range: [v1.35.4, v1.36.2) - Port the following Sui's commits which are contained in the single PR MystenLabs/sui#19029 - MystenLabs/sui@bf9ac99 - MystenLabs/sui@ea27dff - MystenLabs/sui@066a6b6 - Descriptions from commits - transaction-executor: add simulate_transaction trait method - rest: introduce transaction simulation endpoint - rest: introduce transaction resolve endpoint - Notes - The extra field `trace_builder_opt` of `execute_transaction_to_effects` was introduced in #6354 - Because the `iota-sdk-types` does not exit, use `iota-sdk2` instead - Remove stable/unstable description in openapi.json from #6922 ## Links to any relevant issues Part of #3990 ## Type of change - Enhancement (a non-breaking change which adds functionality) --------- Co-authored-by: jkrvivian <[email protected]>
#6929) # Description of change - Upstream range: [v1.35.4, v1.36.2) - Port the following Sui's commits which are contained in the single PR MystenLabs/sui#19029 - MystenLabs/sui@bf9ac99 - MystenLabs/sui@ea27dff - MystenLabs/sui@066a6b6 - Descriptions from commits - transaction-executor: add simulate_transaction trait method - rest: introduce transaction simulation endpoint - rest: introduce transaction resolve endpoint - Notes - The extra field `trace_builder_opt` of `execute_transaction_to_effects` was introduced in #6354 - Because the `iota-sdk-types` does not exit, use `iota-sdk2` instead - Remove stable/unstable description in openapi.json from #6922 ## Links to any relevant issues Part of #3990 ## Type of change - Enhancement (a non-breaking change which adds functionality) --------- Co-authored-by: jkrvivian <[email protected]>
Description
This stack of commits introduces a transaction resolve and simulation endpoint to the REST api service.
More documentation, usage examples as well as a stabilized format for an unresolved transaction JSON payload still need to be done/decided.
At a high level the resolve api will allow someone to provide a partially filled in PTB and have the Fullnode:
Test plan
How did you test the new or updated feature?
Release notes
Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.
For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates.