-
Notifications
You must be signed in to change notification settings - Fork 38.7k
mining: add applySolution() to interface #33374
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
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/33374. 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. LLM Linter (✨ experimental)Possible typos and grammar issues:
drahtbot_id_5_m |
1025446 to
9b8d95f
Compare
|
Fixed typo. |
ajtowns
left a comment
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 like this better than just logging stuff, for whatever that's worth.
ryanofsky
left a comment
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, this does seem like a more general solution than 33372.
|
On second thought I don't think mutating the block is a problem.
IIUC only the This has been a source of confusion:
So far the SRI software has been giving us a complete coinbase, including the coinbase witness. But this involved a hardcoded assumption about its value. The current ambition is to have the Template Provider communicate this value (eventually, no rush). But it seems the approach in RPC land was different: we don't communicate the coinbase witness to pool software and just fix it when they submit the solution. The description of says "This is safe for submitted blocks.", but that's only true if the pool took our SegWit The latter is not unreasonable, but I would prefer that we pick one approach:
I prefer (1). cc @plebhash.
I rebased this on #33380 and added a test on regtest. This checks that dropping the coinbase witness has an effect. You can verify this test by modifying AddMerkleRootAndCoinbase(m_block_template->block, std::move(coinbase), version, timestamp, nonce);
LOCK(cs_main);
# yolo
chainman().UpdateUncommittedBlockStructures(m_block_template->block, chainman().ActiveTip());
return m_block_template->block; |
9b8d95f to
e3f0686
Compare
this would require a change to the Sv2 spec so that but unfortunately, changing Sv2 spec is usually received with resistance from the current players. if/when a softfork happens and we start committing stuff to the coinbases' but until that day comes, this spec change would be merely motivated for making Sv2 "future-proof" with regards to this hypothetical soft fork. so this is all to put some extra emphasis on the (eventually, no rush) quoted above.
In Sv2 terms, option 2. would incur in extra round trips ( So I'd prefer 1 as well. Even if Bitcoin Core continues to redundantly provide So whenever we get consensus a Sv2 spec change (either preemptively or forced by a soft-fork), the Sv2 TP would already have means to fill But AFAIU, that's somewhat different from the proposal on this PR, right? IIUC this PR is only adding a new |
|
@plebhash indeed this PR just introduces the extra method and clarifies in the documentation that |
Unlike the submitblock RPC which takes a fully serialized block, when a block solution is received via IPC the client only provides the nonce, coinbase and a few other fields. It may not have all the information it needs to reconstruct the block. This makes debugging difficult when the block is invalid. This commit adds applySolution() which returns the reconstructed block and can be used by the client for debugging. It can also be used by the client for an alternative broadcast mechanism.
e3f0686 to
7249cbf
Compare
|
Rebased after #33380 landed and updated the PR description. |
|
Have a few questions and comments:
|
This is a great point. Let's just embrace the fact that I'll extract some of the documentation improvements, and add some based on your comments, and PR those later. Ditto for the extra test coverage. |
|
@ryanofsky wrote:
It turns out we accept such an invalid block. The reason for that is a cached |
PR bitcoin#33374 proposed a new Mining IPC method applySolution() which could be used by clients to obtain the reconstructed block for inspection, especially in the case of a rejected block. However it was pointed out during review that submitBlock() modified the template CBlock in place, so the client can just call getBlock() and no new method is needed. This commit adds a test to document that (now intentional) behavior.
|
Github (not the moderators) completely disappeared the (very useful) earlier feedback from Plebhash. Hopefully his account gets restored, but meanwhile see the @0xB10C backup: https://mirror.b10c.me/bitcoin-bitcoin/33374#issuecomment-3299309843 |
|
Note that the @plebhash comments were actually remove from the archive (as it just pulls the GitHub API. Gone from the GitHub API means gone from the latest version of the archive and mirroring) and might thus be missing from the mirroring after the next rebuild..
|
|
@plebhash's account has been restored and his comments and issues came back. |
6eaa00f test: clarify submitBlock() mutates the template (Sjors Provoost) 862bd43 mining: ensure witness commitment check in submitBlock (Sjors Provoost) 00d1b6e doc: clarify UpdateUncommittedBlockStructures (Sjors Provoost) Pull request description: When an IPC client requests a new block template via the Mining interface, we hold on to its `CBlock`. That way when they call `submitSolution()` we can modify it in place, rather than having to reconstruct the full block like the `submitblock` RPC does. Before this commit however we forgot to invalidate `m_checked_witness_commitment`, which we should since the client brings a new coinbase. This would cause us to accept an invalid chaintip. Fix this and add a test to confirm that we now reject such a block. As a sanity check, we add a second node to the test and confirm that will accept our mined block. As first noticed in #33374 the IPC code takes the coinbase as provided, unlike the `submitblock` RPC which calls `UpdateUncommittedBlockStructures()` and adds witness commitment to the coinbase if it was missing. Although that could have been an alternative fix, we instead document that IPC clients are expected to provide the full coinbase including witness commitment. Patch to produce the original issue: ```diff diff --git a/src/node/miner.cpp b/src/node/miner.cpp index b988e28..28e9048 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -450,15 +450,10 @@ void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t } block.nVersion = version; block.nTime = timestamp; block.nNonce = nonce; block.hashMerkleRoot = BlockMerkleRoot(block); - - // Reset cached checks - block.m_checked_witness_commitment = false; - block.m_checked_merkle_root = false; - block.fChecked = false; } std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainman, KernelNotifications& kernel_notifications, CTxMemPool* mempool, diff --git a/test/functional/interface_ipc.py b/test/functional/interface_ipc.py index cce56e3..bf1b7048ab 100755 --- a/test/functional/interface_ipc.py +++ b/test/functional/interface_ipc.py @@ -216,22 +216,22 @@ class IPCInterfaceTest(BitcoinTestFramework): assert_equal(res.result, True) # The remote template block will be mutated, capture the original: remote_block_before = await self.parse_and_deserialize_block(template, ctx) - self.log.debug("Submitted coinbase must include witness") + self.log.debug("Submitted coinbase with missing witness is accepted") assert_not_equal(coinbase.serialize_without_witness().hex(), coinbase.serialize().hex()) res = await template.result.submitSolution(ctx, block.nVersion, block.nTime, block.nNonce, coinbase.serialize_without_witness()) - assert_equal(res.result, False) + assert_equal(res.result, True) self.log.debug("Even a rejected submitBlock() mutates the template's block") # Can be used by clients to download and inspect the (rejected) # reconstructed block. remote_block_after = await self.parse_and_deserialize_block(template, ctx) assert_not_equal(remote_block_before.serialize().hex(), remote_block_after.serialize().hex()) - self.log.debug("Submit again, with the witness") + self.log.debug("Submit again, with the witness - does not replace the invalid block") res = await template.result.submitSolution(ctx, block.nVersion, block.nTime, block.nNonce, coinbase.serialize()) assert_equal(res.result, True) self.log.debug("Block should propagate") assert_equal(self.nodes[1].getchaintips()[0]["height"], current_block_height + 1) ``` ACKs for top commit: ryanofsky: Code review ACK 6eaa00f. Just documentation updates and test clarifications since last review, also splitting up a commit. TheCharlatan: Re-ACK 6eaa00f ismaelsadeeq: Code review and tested ACK 6eaa00f Tree-SHA512: 3a6280345b0290fe8300ebc63c13ad4058d24ceb35b7d7a784b974d5f04f420860ac03a9bf2fc6a799ef3fc55552ce033e879fa369298f976b9a01d72bd55d9e

Unlike the
submitblockRPC which takes a fully serialized block, when a block solution is received via IPC the client only provides the nonce, coinbase and a few other fields. It may not have all the information it needs to reconstruct the block. This makes debugging difficult when the block is invalid.This PR adds
applySolution()which returns the reconstructed block and can be used by the client for debugging. It's assigned@11in the.capfile, and will not break existing client software.It can also be used by the client for an alternative broadcast mechanism.
The tests cover both mainnet (unit tests) and regtest (functional tests), because the latter has SegWit active.
The second commit documents the fact that
applySolution()as well as the (already existing)submitSolutionare slightly different from thesubmitsolutionRPC in that they expect a complete coinbase transaction and will not automatically add a witness. This behavior is also covered in the functional test of the first commit.This is alternative or complimentary approach to: