-
Notifications
You must be signed in to change notification settings - Fork 38.7k
RPC/txoutproof: Support including (and verifying) proofs of wtxid #32844
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
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/32844. 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. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. LLM Linter (✨ experimental)Possible typos and grammar issues:
No other typos were found. drahtbot_id_4_m |
Wow, thank you for working on this! I was meaning to open an issue to ask for this, but did not even get to that yet. The request I would like an electrum server, assuming txindex=1, to be able to serve is:
return a dict containing:
Obviously the electrum server can act as middleware and transform the response, assuming the necessary fields are available or obtainable. As far as I can tell, but I haven't tried yet, the RPC response from this PR can be transformed to what I describe above. So the RPC looks to be doing what I need. :) I think it is non-trivial, so let me detail how an electrum/light client would then use
|
|
Concept ACK. @SomberNight it's still useful if you open an issue to track the reason you need this, just in case this implementation PR doesn't make. |
Sjors
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.
Took an initial look at the code, but got a bit confused. Will check again later.
3abfd6d to
e826ffd
Compare
…saction (not a CBlock)
e95981b to
4b3a33a
Compare
|
Reworked this to cover @SomberNight 's requirements and address feedback. Test is now passing. |
4b3a33a to
23edd3d
Compare
|
🐙 This pull request conflicts with the target branch and needs rebase. |
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.
Transaction proofs are an interoperability feature, I don't think it makes much sense to implement this without also documenting it and providing test vectors via a BIP.
Concept ACK
| /** Public only for unit testing */ | ||
| CBlockHeader header; | ||
| CPartialMerkleTree txn; | ||
| /** Only used by subclass WtxidInBlockMerkleProof */ |
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.
There is no such subclass?
I think all this logic should entirely be in a separate class though. For efficiency probably two paths:
- if the generation tx has no witness commitment; provde all (w)txids and the generation tx via the block partial merkle tree.
- if the generation tx does have a witness commitment; provide just the generation tx's merkle path back to the block header, and prove all wtxids via a partial merkle tree back to the witness commitment
| {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"}, | ||
| {"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", | ||
| { | ||
| {"verify_witness", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, also verifies the associated wtxid/hash of the specified transactions (if included in proof)"}, |
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 this should probably be automatic, with the current "array of txids" result being stuck behind a -deprecatedrpc option.
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 that makes sense and we could even do the same for gettxoutproof I think (if that wasn't already intended with the comment as well).
| {RPCResult::Type::STR_HEX, "blockhash", "The block hash this proof links to"}, | ||
| {RPCResult::Type::NUM, "blockheight", "The height of the block this proof links to"}, | ||
| {RPCResult::Type::NUM, "confirmations", /*optional=*/true, "Number of blocks (including the one with the transactions) confirming these transactions"}, | ||
| {RPCResult::Type::NUM, "confirmations_assumed", /*optional=*/true, "The number of unverified blocks confirming these transactions (eg, in an assumed-valid UTXO set)"}, |
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 information (height, confirmations, assumeutxo info) seems better obtained via getblockheader on the blockhash to me.
| if (merkleBlock.m_gentx->GetHash() != vMatch[0]) return res; | ||
| if (!merkleBlock.m_gentx->IsCoinBase()) return res; | ||
| witness_commit_outidx = GetWitnessCommitmentIndex(*merkleBlock.m_gentx); | ||
| if (witness_commit_outidx == NO_WITNESS_COMMITMENT) { |
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 would have expected this logic to be in merkleblock.cpp as a standard part of verifying a proof (eg so that it could be included in kernel), not in the RPC code.
|
|
||
| const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(merkleBlock.header.GetHash()); | ||
| const auto& active_chain = chainman.ActiveChain(); | ||
| if (!pindex || !active_chain.Contains(pindex) || pindex->nTx == 0) { |
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.
Being able to easily prove/verify that a tx was included in a reorged block seems fine?
fjahr
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
Is there something special about the naming "generation tx" here? It seems to be just an older alias for the coinbase transaction without any other special meaning. I can not recall seeing it used anywhere in the code base or online discourse. If I am not overlooking something it would probably be better to just call it coinbase tx instead which should be less confusing to newer contributors that haven't heard this term before.
| expected_proven['confirmations'] = 1 | ||
| del expected_proven['tx'][0]['txid'] | ||
| del expected_proven['tx'][1]['txid'] | ||
| assert_equal(self.nodes[0].verifytxoutproof(proofres['proof'], verify_witness=True), expected_proven) |
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.
Should also cover an invalid proof here
| {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"}, | ||
| {"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", | ||
| { | ||
| {"verify_witness", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, also verifies the associated wtxid/hash of the specified transactions (if included in proof)"}, |
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 that makes sense and we could even do the same for gettxoutproof I think (if that wasn't already intended with the comment as well).
Feature requested by @SomberNight for Electrum's Lightning stuff. (Please confirm this does what you need)
Unfortunately WIP because the wtxid merkle root calculation doesn't match and I don't have time to figure out why not yet (maybe after concept ACK? or if anyone else wants to take a look...)
Mostly backward compatible, but a segwit-enabled proof will verify the generation tx in old versions.