-
Notifications
You must be signed in to change notification settings - Fork 113
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
change(rpc): Provide and parse a long poll ID, but don't use it yet #5796
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #5796 +/- ##
==========================================
- Coverage 78.82% 78.75% -0.07%
==========================================
Files 308 308
Lines 38742 38747 +5
==========================================
- Hits 30539 30517 -22
- Misses 8203 8230 +27 |
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's the advantage of this design over tip hash + mempool version?
Alternative proposal: we could generate the template with a uuid in a different task when there's a tip change or mempool update then return the uuid as the longpollid. |
This is a partial implementation of a tip hash + mempool design, without the part where we check if the long poll id is the same, and wait to return the result.
We might want to have exactly 69 digits, or we might want fewer, so our IDs can't be confused. I've gone for fewer here, we can always pad later if we find out that's needed during testing. A block hash is 64 hex digits, but we also want to include the max time, so we can send a new template if there are no transaction changes in the mempool, and the template expires. We also need to fit some kind of mempool transaction content marker into the 69 digits. There can be multiple transactions in the mempool, so we need some way of condensing their hashes into a smaller number of bytes. And once we have that, we might as well use it on the block hash. The tip height and mempool transaction count are optional, but they are useful for avoiding duplicate checksums, and for debugging. We have space to write these fields and the time as decimal, which makes them more readable. |
I think I see how this could work, but how would we avoid generating templates when there were no requests? This also adds concurrency, which increases the complexity of this change. So if we can do it without concurrency, I'd like to try that first. |
I need to handle parsing the long poll id correctly, it should be valid here:
https://github.com/ZcashFoundation/zebra/actions/runs/3625573409/jobs/6114169640#step:3:3563 |
Tower service driven by polling!
I see your point. We could also do a uuid with a cached template and check the max_time there. |
I'd like to try for the simplest working implementation first, and then make it more efficient. |
1b49343
to
dc7f482
Compare
dc7f482
to
edec86c
Compare
Just a rebase and some minor tidy-ups. |
aa11aa3
to
518ff24
Compare
And finally a fix to the config file and its tests. |
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.
Looks good, I like that you used a checksum of the tip hash instead of the full hash.
…es, but don't use it yet
… efficient long polling
518ff24
to
7f0a612
Compare
Does it? The only restriction I see is that it must be encoded as a JSON string. A long poll ID is effectively an identifier for the returned template, so the next call can know what you are currently using, and therefore what template state to measure "is updated" against. It therefore only makes sense in the context of the node instance that generated it, because only that instance can remember what the template was given the current API. Long poll IDs aren't even portable across different instances of the same implementation ( So unless there's something else in (Bitcoin Core's partial implementation of) BIP 22 that constrains it (which appears to not be the case; in fact "clients must not assume the long poll ID has any specific meaning" is stated) then you can do whatever you want 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.
The only restriction I see is that it must be encoded as a JSON string.
That's my understanding as well, I don't think it could be used as anything besides an id.
This should work either way.
While this is technically true according to the spec, there is nothing stopping client implementations:
So if we want to be maximally compatible with existing clients, we should avoid going over 69 bytes, and avoid using non-hex characters. |
There's also no guarantee that any incompatibilities will reliably cause errors. In a memory-unsafe language, it's possible to write a few bytes past a 69 byte array without detecting it, depending on the allocator and memory pressure. |
Motivation
We want to implement long polling support in Zebra.
Depends-On: #5772
Specifications
getblocktemplate request:
getblocktemplate response:
https://en.bitcoin.it/wiki/BIP_0022#Optional:_Long_Polling
Designs
Add a
LongPollInput
type which contains all the data long polling can depend on.Lossily convert it into a
LongPollId
type, which almost always changes when theLongPollInput
changes.Convert the
LongPollId
type to and from a string in thegetblocktemplate
RPC.Solution
RPC request:
RPC server:
This is part of #5720.
Review
I'd like an initial review of the design and the data we're using, before I add long polling waits and tests in the next PR.
Reviewer Checklist
Follow Up Work
submit_old
fieldjsonrpc_core
blocks when a RPC waits