-
Notifications
You must be signed in to change notification settings - Fork 38.8k
rpc: have verifytxoutproof check the number of txns in proof structure #13452
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
|
utACK 614fd8db3259b01e47d7b551ac389bd3137c8c5a. Looks like a nice belt-and-suspenders with no strings attached: I think it is reasonable for a node to fail here, in case it hasn't downloaded the transactions (and thus doesn't know the number of transactions). |
|
utACK |
|
utACK 614fd8db3259b01e47d7b551ac389bd3137c8c5a |
src/rpc/rawtransaction.cpp
Outdated
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.
Is it right to throw an RPC error here? This is more similar to being given an invalid proof (as opposed to an incorrectly formatted/unusable one), in which case Null is returned currently.
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.
deja vu: #11120 (comment)
(I can also just have it clear the return list)
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.
Yes, I feel there is a big difference between not having the block (which means being unable to validate) and being given an intentionally fraudulent proof.
Requiring software to deal and match RPC errors instead of being covered by dealing with the existing "invalid proof" case sounds much nicer.
I also think you need to check for nTx = 0 by the way (as it may mean a block for which we only have headers etc), and treat that as not having the block.
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.
@sipa Is it well-defined that a headers-only blockindex will have nTx==0? The comments say nTx simply is unreliable in that case...
614fd8d to
ed82f17
Compare
|
took @sipa suggestions |
|
I think this actually breaks in pruned mode, since nTx gets set to 0. :/ ( Actually, I can't find where pruning resets nTx... just asserts and comments implying it must. :| ) |
|
@luke-jr Really? That would be unfortunate. I assumed that nTX == 0 was only the case if we never accepted the full block. |
|
I'm not sure on the actual behaviour right now, since I can't find where it's zeroed. It may be that the asserts are an unrelated bug (but I'd expect we'd have noticed if that were the case). |
|
Can you point to the asserts? |
|
Nevermind, looks like there's only one left in master, and it's wrapped under a |
This is hopefully not the case, because I have a merged PR with tests that pass #13451 |
|
utACK ed82f17 |
sdaftuar
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.
ACK apart from the nits I left.
I also wrote up a test that exercises the logic, if you feel like including that with this patch: sdaftuar@e6db405
|
|
||
| const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash()); | ||
| if (!pindex || !chainActive.Contains(pindex)) { | ||
| if (!pindex || !chainActive.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.
pindex->nTx == 0 implies !chainActive.Contains(pindex), so I think we can eliminate that condition. You can't be in chainactive if you never received the transactions for a block. Alternatively, we could add a comment for future readers that explains that this is redundant.
| for (const uint256& hash : vMatch) | ||
| res.push_back(hash.GetHex()); | ||
| // Check if proof is valid, only add results if so | ||
| if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) { |
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.
nit: I think if the proof lies about the number of transactions, we should throw an error, rather than just return an empty list, but I don't feel strongly about the API if you like it this way.
| "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n" | ||
| "\nResult:\n" | ||
| "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n" | ||
| "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n" |
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 leave the language here unchanged? If we can't validate the proof because the number of transactions differs from what we stored in our blockindex, then the proof is invalid!
|
cherry-picked @sdaftuar test, thanks! |
Note to reviewers: 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. |
|
utACK d280617 |
…proof structure d280617 [qa] Add a test for merkle proof malleation (Suhas Daftuar) ed82f17 have verifytxoutproof check the number of txns in proof structure (Gregory Sanders) Pull request description: Recent publication of a weakness in Bitcoin's merkle tree construction demonstrates many SPV applications vulnerable to an expensive to pull off yet still plausible attack: https://bitslog.wordpress.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/ This change would at least allow `verifytxoutproof` to properly validate that the proof matches a known block, with known number of transactions any time after the full block is processed. This should neuter the attack entirely. The negative is that a header-only processed block/future syncing mode would cause this to fail until the node has imported the data required. related: #13451 `importprunedfunds` needs this check as well. Can expand it to cover this if people like the idea. Tree-SHA512: 0682ec2b622a38b29f3f635323e0a8b6fc071e8a6fd134c954579926ee7b516e642966bafa667016744ce49c16e19b24dbc8801f982a36ad0a6a4aff6d93f82b
Github-Pull: bitcoin#13452 Rebased-From: ed82f17
Github-Pull: bitcoin#13452 Rebased-From: d280617
|
Should be backported in #13644. |
Github-Pull: bitcoin#13452 Rebased-From: ed82f17
Github-Pull: bitcoin#13452 Rebased-From: d280617
Github-Pull: bitcoin#13452 Rebased-From: ed82f17
…xns in proof structure d280617 [qa] Add a test for merkle proof malleation (Suhas Daftuar) ed82f17 have verifytxoutproof check the number of txns in proof structure (Gregory Sanders) Pull request description: Recent publication of a weakness in Bitcoin's merkle tree construction demonstrates many SPV applications vulnerable to an expensive to pull off yet still plausible attack: https://bitslog.wordpress.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/ This change would at least allow `verifytxoutproof` to properly validate that the proof matches a known block, with known number of transactions any time after the full block is processed. This should neuter the attack entirely. The negative is that a header-only processed block/future syncing mode would cause this to fail until the node has imported the data required. related: bitcoin#13451 `importprunedfunds` needs this check as well. Can expand it to cover this if people like the idea. Tree-SHA512: 0682ec2b622a38b29f3f635323e0a8b6fc071e8a6fd134c954579926ee7b516e642966bafa667016744ce49c16e19b24dbc8801f982a36ad0a6a4aff6d93f82b
…xns in proof structure d280617 [qa] Add a test for merkle proof malleation (Suhas Daftuar) ed82f17 have verifytxoutproof check the number of txns in proof structure (Gregory Sanders) Pull request description: Recent publication of a weakness in Bitcoin's merkle tree construction demonstrates many SPV applications vulnerable to an expensive to pull off yet still plausible attack: https://bitslog.wordpress.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/ This change would at least allow `verifytxoutproof` to properly validate that the proof matches a known block, with known number of transactions any time after the full block is processed. This should neuter the attack entirely. The negative is that a header-only processed block/future syncing mode would cause this to fail until the node has imported the data required. related: bitcoin#13451 `importprunedfunds` needs this check as well. Can expand it to cover this if people like the idea. Tree-SHA512: 0682ec2b622a38b29f3f635323e0a8b6fc071e8a6fd134c954579926ee7b516e642966bafa667016744ce49c16e19b24dbc8801f982a36ad0a6a4aff6d93f82b
Recent publication of a weakness in Bitcoin's merkle tree construction demonstrates many SPV applications vulnerable to an expensive to pull off yet still plausible attack: https://bitslog.wordpress.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/
This change would at least allow
verifytxoutproofto properly validate that the proof matches a known block, with known number of transactions any time after the full block is processed. This should neuter the attack entirely.The negative is that a header-only processed block/future syncing mode would cause this to fail until the node has imported the data required.
related: #13451
importprunedfundsneeds this check as well. Can expand it to cover this if people like the idea.