Skip to content

Conversation

@bmwill
Copy link
Contributor

@bmwill bmwill commented Aug 19, 2024

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:

  • select versions
  • mutability of the objects
  • budget determination
  • fill in reference gas price
  • basic gas selection/gas smashing

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.

  • Protocol:
  • Nodes (Validators and Full nodes):
  • Indexer:
  • JSON-RPC:
  • GraphQL:
  • CLI:
  • Rust SDK:
  • REST API:

@vercel
Copy link

vercel bot commented Aug 19, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sui-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 10, 2024 1:00am
3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Oct 10, 2024 1:00am
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Oct 10, 2024 1:00am
sui-typescript-docs ⬜️ Ignored (Inspect) Visit Preview Oct 10, 2024 1:00am

@vercel
Copy link

vercel bot commented Aug 19, 2024

@bmwill is attempting to deploy a commit to the Mysten Labs Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@hayes-mysten hayes-mysten left a 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 {
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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

Copy link
Contributor

@amnn amnn left a 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 resolve and simulate at the REST level? It seems like simulate is offering a strict subset of the features that resolve offers 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() {
Copy link
Contributor

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.

Copy link
Contributor Author

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()))?
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor

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.

Comment on lines 1976 to 1980
if transaction.kind().is_system_tx() {
return Err(SuiError::UnsupportedFeatureError {
error: "simulate does not support system transactions".to_string(),
});
}
Copy link
Contributor

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",
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// 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);
Copy link
Contributor

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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> {
Copy link
Contributor

@stefan-mysten stefan-mysten Oct 10, 2024

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?

Copy link
Contributor Author

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

Copy link
Contributor

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(
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@stefan-mysten stefan-mysten left a 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.

@bmwill bmwill merged commit 066a6b6 into MystenLabs:main Oct 10, 2024
45 checks passed
@bmwill bmwill deleted the rest branch October 10, 2024 02:00
Copy link
Contributor

@amnn amnn left a 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!

muXxer pushed a commit to iotaledger/iota that referenced this pull request Jun 10, 2025
#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]>
muXxer pushed a commit to iotaledger/iota that referenced this pull request Jun 10, 2025
#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]>
filipdulic pushed a commit to iotaledger/iota that referenced this pull request Jul 16, 2025
#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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants