-
Notifications
You must be signed in to change notification settings - Fork 36.6k
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 checkblock RPC and checkBlock() to Mining interface #31564
base: master
Are you sure you want to change the base?
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31564. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsNo conflicts as of last run. |
I wrote on IRC:
To which @sipa responded:
This PR omits |
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 newly introduced CheckNewBlock()
looks very similar to the existing TestBlockValidity()
which was just removed from the mining interface in bfc4e02 - it just seems to be a bit more verbose and allows the multiplier for the PoW. Did you consider merging these functions, so that we don't have multiple functions in validation that basically do the same thing?
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.
Concept ACK
Really liking the idea of facilitating these type of systems.
Instead of a multiplier I could also allow a custom target. This would give weak block systems more flexibility on how to derive their difficulty.
I'd be in favor of this. It's more flexible, could prevent interface churn, and if the user wishes to create the custom target from a simple multiplication they could do the multiplication on their end.
src/pow.cpp
Outdated
@@ -161,3 +161,19 @@ bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Par | |||
|
|||
return true; | |||
} | |||
|
|||
bool CheckWeakProofOfWork(uint256 hash, unsigned int nBits, unsigned int multiplier, const Consensus::Params& params) |
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.
Feel free to ignore before more concept acks arrive.
CheckWeakProofOfWork()
seems really similar to CheckProofOfWorkImpl()
. Maybe I'm missing something simple. What was the rationale for creating the new function vs adding an argument?
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.
Just that I didn't want to touch CheckProofOfWorkImpl
.
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.
This also applies to the new DeriveTarget
method. I added the motivation for not changing CheckProofOfWorkImpl
to the commit message in: d3710b0
It looks like I ended up with a similar design after a long detour. I'll look into combining these.
@instagibbs is there any reason you went for a multiplier? |
442f27a
to
0182812
Compare
nothing off the top of my head |
I refactored I then dropped the original If people prefer I could rewrite the git history to directly refactor I split the test changes out into #31581, so will mark this PR as draft for now. While working on that I noticed a rather big difference between the original |
0182812
to
5ae0c47
Compare
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
c961e83
to
2985291
Compare
I might make a separate PR to consider whether to drop If that ends up rejected, then I'll keep the existing Related: #31563
Update: I was confused, |
2985291
to
ed301f0
Compare
0424968 test: use Mining interface in miner_tests (Sjors Provoost) Pull request description: Needed for both #31283 and #31564. By using the Mining interface in `miner_tests.cpp` we increase its coverage in unit tests. ACKs for top commit: achow101: ACK 0424968 ryanofsky: Code review ACK 0424968, just minor suggested changes (renames, comments, BOOST_REQUIREs) since last review and some more extra clarifications and checks added to the CreateNewBlock_validity test. The CreateNewBlock_validity changes seem clear and easy to understand now. vasild: ACK 0424968 tdb3: ACK 0424968 Tree-SHA512: 2761cb7555d759670e40d8f37b96a079f8e12a588ac43313b9e63c69afd478321515873a8896ea56784f0100dac4476b0c0e0ef8b5418f8aea24d9965cace4d4
The new RPC interface is redundant with the existing BIP 23 block proposals support. P.S. DATUM does not provide a way for the pool to reject valid blocks. There is no approval of templates. |
Split CheckProofOfWorkImpl() to introduce a helper function DeriveTarget() which converts the nBits value to the target. The function takes pow_limit as an argument so later commits can avoid having to pass ChainstateManager through the call stack. Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
ed301f0
to
37c73dc
Compare
Rebased after #31581 landed. I also cherry-picked the latest relevant commits from #31583. @luke-jr I dropped DATUM from the description, since there's still no spec it's hard to understand what it actually does. The My long term goal for this new method is to make it more powerful. It could optionally add new transactions to the mempool to improve compact block relay. It could perform small reorgs to validate forks, which can be useful for (stale) share accounting (and perhaps uncle and DAG schemes). An alternative approach could be drop the But I think it's nice to offer weak block checking support for mining pool projects that want to experiment with it, without forcing them to use IPC. The new RPC method is short and test covered. (in the above I'm assuming that |
37c73dc
to
26b505a
Compare
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
26b505a
to
1705adf
Compare
Delete the original TestBlockValidity and rename CheckNewBlock. Have the generateblock and getblocktemplate RPC calls, as well as BlockAssembler::CreateNewBlock use the new method.
1705adf
to
8cd4e51
Compare
What would use the "weak block" check that doesn't need the ability to do it independently from proposals anyway? While the existing GBT BIPs are Final, the protocol was designed to allow for extensions. If there's a use case for this feature, doing it that way seems fine |
@luke-jr do you mean that every client that wants to call What would an extension look like to pass |
Rationale
Verifying block templates (no PoW)
Stratum v2 allows miners to generate their own block template. Pools may wish (or need) to verify these templates. This typically involves comparing mempools, asking miners to providing missing transactions and then reconstructing the proposed block.1 This is not sufficient to ensure a proposed block is actually valid. In some schemes miners could take advantage of incomplete validation2.
The Stratum Reference Implementation (SRI), currently the only Stratum v2 implementation, collects all missing mempool transactions, but does not yet fully verify the block.3 There's currently no way for it to do so, short of re-implementing Bitcoin Core validation code.
(although SRI could use this PR, the Template Provider role doesn't need it, so this is not part of #31098)
Verifying weak blocks (reduced PoW)
Stratum v2 decentralises block template generation, but still hinge on a centralised entity to approve these templates.
There used to be a decentralised mining protocol P2Pool4 which relied on (what we would today call) weak blocks. In such a system all participants perform verification and there is no privileged pool operator (that can reject a template).
IIUC only the header and coinbase of these shares / weak blocks were distributed amongst all pool participants and verified. This was sufficient at the time because fees were negligible, so payouts could simply be distributed based on work.
However, if P2Pool were to be resurrected today5, it would need to account for fees in a similar manner as PPLNS2 above. In that case the share chain should include the full weak blocks6. The client software would need a way to verify those weak blocks.
A similar argument applies to Braidpool.
Enter
checkblock
and its IPC counterpartcheckBlock()
Given a serialised block, it performs the same checks as
submitblock
, but without updating the block index, chainstate, etc. The proof-of-work check can be bypassed entirely, for the first use of verifying block templates. Alternatively a customtarget
can be provided for the use case of weak blocks.When called with
check_pow=false
thecheckblock
RPC is (almost) the same asgetblocktemplate
inproposal
mode, and indeed they both callcheckBlock()
on the Mining interface.Implementation details:
Builds on:
The
ChainstateManager::CheckNewBlock()
implementation is based onProcessNewBlock()
, but refactored in a number of ways (see Sjors#75 for previous incarnations):StateCatcher
CheckWeakProofOfWork
before the other checksAcceptBlock()
it performs a (documented) subset of that functionCCoinsViewCache
on top of the tip on which it connects the block (needed for full transaction verification)This
CheckNewBlock()
method is then called from the Mining interfacecreateBlock()
method. This in turn is called from the RPCcheckblock
code, which is a simplified clone ofsubmitblock
.This method ended up being very similar to
TestBlockValidity
, so the last commit replaces the latter entirely (renamingCheckNewBlock
).This PR contains a simple unit test and a more elaborate functional test.
Potential followups:
Footnotes
https://github.com/stratum-mining/sv2-spec/blob/main/06-Job-Declaration-Protocol.md ↩
https://delvingbitcoin.org/t/pplns-with-job-declaration/1099/45?u=sjors ↩ ↩2
https://github.com/stratum-mining/stratum/blob/v1.1.0/roles/jd-server/src/lib/job_declarator/message_handler.rs#L196 ↩
https://en.bitcoin.it/wiki/P2Pool ↩
this improves compact block relay once the real block comes in ↩ ↩2
The share chain client software could use compact block encoding to reduce its orphan / uncle rate. To make that easier, we could provide a
reconstructblock
RPC (reconstructBlock
IPC) that takes the header and short ids, fills in aCBlock
from the mempool (and jail) and returns a list of missing items. The share chain client then goes and fetches missing items and calls the method again. It then passes the complete block tocheckblock
. This avoids the need for others to fully implement compact block relay. Note that even if we implemented p2p weak block relay, it would not be useful for share chain clients, because they need to relay additional pool-specific data. ↩https://delvingbitcoin.org/t/second-look-at-weak-blocks/805 ↩