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

RPC sendTransaction: be more liberal in determining and setting last_valid_block_height for skip_preflight case #483

Merged
merged 2 commits into from
Apr 3, 2024

Conversation

CriesofCarrots
Copy link

Problem

Transactions submitted to RPC sendTransaction with skipPreflight: true frequently aren't retried by the SendTransactionService (STS). This happens when the transaction's recent blockhash is newer than the RPC node's finalized bank, because unless preflightCommitment is speficied, the RPC handler uses the default finalized bank to find a last_valid_block_height to provide to the STS. If the blockhash cannot be found (as when too new), last_valid_block_height is set to 0, and the STS only broadcasts the transaction once.

Summary of Changes

  • If skip_preflight is set, use the processed commitment Bank to search for the recent blockhash.
  • If the last_valid_block_height still cannot be determined, use the durable-nonce logic to retry the transaction for an arbitrary, fixed number of blocks (skip_preflight being an indication that a client wants their transactions to be sprayed around regardless of likelihood of success).

Fixes #479

@codecov-commenter
Copy link

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.8%. Comparing base (e261e27) to head (213ec56).

Additional details and impacted files
@@            Coverage Diff            @@
##           master     #483     +/-   ##
=========================================
- Coverage    81.8%    81.8%   -0.1%     
=========================================
  Files         842      842             
  Lines      228436   228439      +3     
=========================================
- Hits       187063   187053     -10     
- Misses      41373    41386     +13     

@steveluscher
Copy link

steveluscher commented Apr 2, 2024

I put up a PR for the JavaScript clients that does what this PR is doing, but from the client side. Until this PR is deployed widely, the client-side patch should provide some relief in the meantime. solana-labs/solana-web3.js#2415

Copy link

@t-nelson t-nelson left a comment

Choose a reason for hiding this comment

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

lgtm. thanks!

let preflight_commitment =
preflight_commitment.map(|commitment| CommitmentConfig { commitment });
let preflight_commitment = if skip_preflight {
Some(CommitmentConfig::processed())
Copy link

Choose a reason for hiding this comment

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

on second thought, would confirmed be more reliable here? more likely to pick up ephemeral forks with processed

Copy link
Author

Choose a reason for hiding this comment

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

I can't see a drawback to picking up an ephemeral fork here. This is only being used to look for the recent_blockhash to determine last_valid_block_height. If the blockhash is from a confirmed or finalized block, it should appear in the ancestor tree of the fork.

Copy link
Author

@CriesofCarrots CriesofCarrots Apr 2, 2024

Choose a reason for hiding this comment

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

But I will hold off merging until you reply, in case you've thought of something I missed. @t-nelson

Copy link

Choose a reason for hiding this comment

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

was thinking something like...

C - 1' - 2'    - 3'(STS)
  \ 1  - 2(TX) - 3

Copy link
Author

@CriesofCarrots CriesofCarrots Apr 3, 2024

Choose a reason for hiding this comment

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

I mean, the bigger problem for the tx using a processed blockhash in that example is really that the transaction won't ever land if the leaders are on the same fork-prime as STS.
However, STS will still retry the transaction the fixed number of blocks (300) as per the logic at L3668 (edit) with this patch

Copy link
Author

Choose a reason for hiding this comment

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

...I'm going to merge this as-is, but there's no big risk in tweaking this later.

Choose a reason for hiding this comment

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

I'll similarly land solana-labs/solana-web3.js#2415. If you change your mind on the commitment, let's make the change in the client too!

@CriesofCarrots CriesofCarrots merged commit 65a24d5 into anza-xyz:master Apr 3, 2024
37 checks passed
steveluscher added a commit to solana-labs/solana-web3.js that referenced this pull request Apr 3, 2024
…eflight checks (#2415)

# Summary

There's a bug in the `sendTransaction` RPC method where, when bypassing preflight, we nevertheless materially use the value of `preflightCommitment` to determine how to behave when sending the transaction.

If you supply _nothing_ – as you might think appropriate when _skipping_ preflight – then the default of `finalized` will be used. Far from irrelevant, such a value can actually affect the retry behaviour of the send-transaction-service (STS). Read anza-xyz/agave#483 for more detail.

In this PR, we try to get ahead of anza-xyz/agave#483 by setting this value to `processed` in the client. Until the server PR is deployed widely, this should cover those who choose to upgrade

Addresses anza-xyz/agave#479

# Test plan

```
pnpm turbo test:unit:node test:unit:browser
```
@joncinque
Copy link

Has there been a discussion about backporting this to 1.17 and 1.18? It seems like it's a small fix that would be really useful to RPCs

@CriesofCarrots
Copy link
Author

Has there been a discussion about backporting this to 1.17 and 1.18? It seems like it's a small fix that would be really useful to RPCs

Not much discussion, no. In my opinion, this isn't so much a bug fix, per se, as it is extending how and when SendTransactionService retries transactions.
It does make some very counter-intuitive behavior more in line with user expectations, though. Given that, and the lack of risk to the cluster, I will propose this for v1.18 backport.

Copy link

mergify bot commented Apr 17, 2024

Backports to the beta branch are to be avoided unless absolutely necessary for fixing bugs, security issues, and perf regressions. Changes intended for backport should be structured such that a minimum effective diff can be committed separately from any refactoring, plumbing, cleanup, etc that are not strictly necessary to achieve the goal. Any of the latter should go only into master and ride the normal stabilization schedule. Exceptions include CI/metrics changes, CLI improvements and documentation updates on a case by case basis.

mergify bot pushed a commit that referenced this pull request Apr 17, 2024
…valid_block_height for skip_preflight case (#483)

* RPC sendTransaction: if skip_preflight, use processed-commitment Bank for last_valid_block_height and sanitization

* Use nonce retry logic for skip_preflight transactions if blockhash was not found

(cherry picked from commit 65a24d5)
CriesofCarrots added a commit that referenced this pull request Apr 18, 2024
…g last_valid_block_height for skip_preflight case (backport of #483) (#873)

RPC sendTransaction: be more liberal in determining and setting last_valid_block_height for skip_preflight case (#483)

* RPC sendTransaction: if skip_preflight, use processed-commitment Bank for last_valid_block_height and sanitization

* Use nonce retry logic for skip_preflight transactions if blockhash was not found

(cherry picked from commit 65a24d5)

Co-authored-by: Tyera <[email protected]>
anwayde pushed a commit to firedancer-io/agave that referenced this pull request Jul 23, 2024
…g last_valid_block_height for skip_preflight case (backport of anza-xyz#483) (anza-xyz#873)

RPC sendTransaction: be more liberal in determining and setting last_valid_block_height for skip_preflight case (anza-xyz#483)

* RPC sendTransaction: if skip_preflight, use processed-commitment Bank for last_valid_block_height and sanitization

* Use nonce retry logic for skip_preflight transactions if blockhash was not found

(cherry picked from commit 65a24d5)

Co-authored-by: Tyera <[email protected]>
lorisleiva added a commit to solana-labs/solana-web3.js that referenced this pull request Sep 10, 2024
This PR removes the temporary request transformer that was waiting for [this PR](anza-xyz/agave#483) to be merged and available on mainnet-beta.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Despite skip_preflight being true, preflight_commitment is nevertheless used
5 participants