-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Add isBlockhashValid method to web3.js #25888
Conversation
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.
Thanks, @zhe-t!
Now all this PR needs is some tests. Use the ‘get block time’ test in connection.test.ts
as a starting point. Run both yarn test
and yarn:test-live-with-test-validator
. You can turn on only the test you're working on by adding .only
to the end of it
or describe
.
Write tests that cover:
- the RPC returning a value when you supply a blockhash
- the RPC returning a value when you supply a blockhash and a min slot
- (LIVE mode only) getting the recent blockhash then asking if it's valid (expect to be true)
- (LIVE mode only) getting the recent blockhash and slot then asking if it's valid with a min slot one slot higher (expect to be false)
- (LIVE mode only) supplying a junk blockhash then asking if it's valid (expect to be false)
Pull request has been modified.
Thanks @steveluscher - working on tests now. |
@steveluscher could you help me with the
test please? The test is called I must have over looked something. The recent slot is always 0 when using |
For sure! In cases where it's the first test you run, this will be the case. Just loop, waiting for a minimum of slots to pass. solana/web3.js/test/connection.test.ts Lines 2969 to 2971 in ed5fcde
|
Tests added
I've tried using the slot returned by |
Sorry for the delay here! I don't really know, but here are some thoughts:
I don't really know what the effect of |
Block height and slot are two totally different things fyi |
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.
Great to see minContextSlot
being used here :)
web3.js/src/connection.ts
Outdated
const unsafeRes = await this._rpcRequest('isBlockhashValid', args); | ||
const res = create(unsafeRes, jsonRpcResultAndContext(boolean())); | ||
if ('error' in res) { | ||
throw new Error( |
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 think we should have special handling for when the min context slot isn't met. It can be detected from its error code:
pub const JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED: i64 = -32016;
We could retry a few times (configurable in IsBlockhashValidConfig
). What do you think? I wouldn't mind this change coming later in a separate PR too. So maybe we just ensure that the thrown error object includes the error code as an integer
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.
Neat. Two questions come to mind:
- Should we check for this error code in
res
and retry a configurable amount of times before bailing? - Should we return the error code be propagated in the response object of
IsBlockhashValid
?
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.
- yup, that's what I had in mind
- no, it should be abstracted away
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.
Shall I include this in the current PR? @jstarry @steveluscher
Oof. Of course. Sorry for the misdirection @zhe-t. |
web3.js/test/connection.test.ts
Outdated
it('is blockhash valid - blockhash only and mint slot (live)', async () => { | ||
const blockhash = await connection.getLatestBlockhashAndContext('finalized'); | ||
|
||
const isValid = await connection.isBlockhashValid( | ||
blockhash.value.blockhash, | ||
{ | ||
commitment: 'finalized', | ||
minContextSlot: blockhash.context.slot+1 | ||
}); | ||
expect(isValid.value).to.be.false; | ||
}); |
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.
Do you have any advice on how to write a test that both exercises minContextSlot
and fails, @jstarry? I'm missing the plot here.
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.
How about setting it to the max safe integer?
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.
Setting to MAX_SAFE_INTEGER gives the same result 🤔 validation result is returning as true
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.
It's because your code isn't actually sending minContextSlot
in the rpc request
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 love it when writing tests pays off right away.
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.
Pull request has been modified.
Updated the PR to resolve the config params not being parsed/passed correctly and now all tests are passing 🎉 thanks @jstarry @steveluscher for the guidance. Ready to review if we do not want to include the special handling for when the min context slot is not met. |
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 pushed up a few commits to finish this up, but could you take a look at the tests @zhe-t? Write one set of tests that works in both live mode and mock mode. The key is that mockRpcResponse
is a no-op in LIVE
mode. Write the tests so that they would pass whether mockRpcResponse
takes effect or not.
web3.js/src/connection.ts
Outdated
blockhash: string, | ||
config?: IsBlockhashValidConfig | ||
): Promise<RpcResponseAndContext<boolean>> { | ||
const extra: Pick<IsBlockhashValidConfig, 'minContextSlot'> = {}; |
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.
In general, you want to take an Omit
approach rather than a Pick
approach.
const extra = Omit<IsBlockhashValidConfig, 'commitment'> = {};
web3.js/src/connection.ts
Outdated
let commitment; | ||
if (config) { | ||
if (config.minContextSlot) { | ||
extra.minContextSlot = config.minContextSlot; | ||
} | ||
|
||
if (config.commitment) { | ||
commitment = config.commitment; | ||
} else { | ||
commitment = this._commitment || 'finalized'; | ||
} | ||
} else { | ||
commitment = this._commitment || 'finalized'; | ||
} |
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.
Since you wrote this PR, we created a helper for this!
const {commitment, config} = extractCommitmentFromConfig(...);
web3.js/src/connection.ts
Outdated
const unsafeRes = await this._rpcRequest('isBlockhashValid', args); | ||
const res = create(unsafeRes, jsonRpcResultAndContext(boolean())); | ||
if ('error' in res) { | ||
console.log(res.error.message); |
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.
web3.js/src/connection.ts
Outdated
const res = create(unsafeRes, jsonRpcResultAndContext(boolean())); | ||
if ('error' in res) { | ||
console.log(res.error.message); | ||
throw new Error( |
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.
Since you made this PR, we introduced SolanaJSONRPCError
.
web3.js/test/connection.test.ts
Outdated
await mockRpcResponse({ | ||
method: 'isBlockhashValid', | ||
params: [blockhash], | ||
value: true, | ||
withContext: true | ||
}); |
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 mockRpcResponse
helper actually skips when you're in live mode, so that you only have to write the tests once.
Codecov Report
@@ Coverage Diff @@
## master solana-labs/solana#25888 +/- ##
=========================================
- Coverage 76.0% 76.0% -0.1%
=========================================
Files 40 40
Lines 2370 2377 +7
Branches 343 344 +1
=========================================
+ Hits 1803 1808 +5
- Misses 449 450 +1
- Partials 118 119 +1 |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Problem
Attempting to resolve solana-labs/solana-web3.js#1113 -
Add isBlockhashValid support
Summary of Changes
Added
isBlockhashValid
method to web3.js sdkFixes #