Skip to content
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

feat: simulator #209

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

feat: simulator #209

wants to merge 6 commits into from

Conversation

m30m
Copy link
Collaborator

@m30m m30m commented Nov 3, 2024

No description provided.


tx = VersionedTransaction.from_bytes(base64.b64decode(data["params"][0]))
sig = tx.signatures[0]
resposne = {"jsonrpc": "2.0", "result": str(sig), "id": data["id"]}
Copy link
Contributor

Choose a reason for hiding this comment

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

typo :D

svm.set_account(*key, account.clone()).unwrap();
}
for (key, account) in self.programs.iter() {
svm.add_program(
Copy link
Contributor

Choose a reason for hiding this comment

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

how does this work with program upgrades? why not just set account data for the program and its executable as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

tried that first, litesvm didn't support it very well. But we can create a PR for that in litesvm package

pub async fn fetch_pending_and_remove_old_txs(&self) -> Vec<VersionedTransaction> {
let now = Instant::now();
let mut pending_txs = self.pending_txs.write().await;
pending_txs.retain(|(_, time)| now.duration_since(*time).as_secs() < 5);
Copy link
Contributor

Choose a reason for hiding this comment

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

is the 5 seconds here a proxy for whether the state change has been processed on-chain? why not just check the commitment statuses of the transactions? that may be easier and more robust via getSignatureStatuses

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, once we have a definite status we can remove it from this array. This will probably be handled by a separate thread that's either polling or subscribing

) -> solana_client::client_error::Result<Signature> {
let now = Instant::now();
self.pending_txs.write().await.push((tx.clone(), now));
self.sender
Copy link
Contributor

Choose a reason for hiding this comment

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

why not simulate the tx here optimistically? you're anyways going to simulate it later, so why not do so here and poll regularly until the tx either hits processed or doesn't show up on-chain after some buffer time (in which case you revert to the RPC's view of state)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

didn't understand what you mean. We simulate it just before calling this function, why should we simulate it again?

context: accounts_config_with_context.context,
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

one way i was thinking of structuring this is the following:

  • you have an rpc client that informs your view of state of all accounts except for a list of accounts which txs that you have submitted have altered (i.e. writable accounts in txs submitted by searchers)
  • for each of those writable accounts, you pull the state of the account when you submit the tx and log that as well as the state of the account post simulating your tx
  • you regularly poll the state of the accounts in your list as well as listen for commitment updates on the transactions you submitted. as soon as you observe either a change in the RPC's view of an account state or get a commitment update on a transaction, you drop your simulated view of the account from your list
  • when simulating transactions, you check if any of the transaction's accounts are in your list. if so, you don't fetch those accounts' data and instead use your stored accounts; you fetch all other accounts.
  • this allows an easy fallback where if the original transaction you submitted fails or doesn't reach processed within enough time, then you revert to on-chain state. but for a short period of time after you submit, you will definitely retain a future view of state so you can simulate new txs more intelligently

Copy link
Contributor

Choose a reason for hiding this comment

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

of course, the key is in how you poll and balance btwn keeping ahead of future tx inclusion and fallback behavior in case a transaction doesn't reach processed or fails on-chain. if another tx changes the state of an account that your submitted tx touches before it is processed you should probably pessimistically drop your simulated forward state bc your tx may not succeed any longer. practically speaking, for limo orders, this shouldn't happen too often, but it's worth thinking about the tradeoffs here in case of other accounts that users may interact with outside of this context

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.

2 participants