Duplicate input detection#979
Conversation
58f8748 to
dd1fa91
Compare
|
|
Thanks ft pointing this, i checked the exact code(please correct me if im wrong) The .remove() happens inside verify_input_script(), which is behind # [cfg(feature="bitcoinkernel")] so the protection exists only when the bitcoinkernel is enabled. THis pr detects duplicate input, so the tx is rejected unconditionaly accros all build confg, and also matching bitcoin cores's behavior for duplicate input handling. |
Hmm, now I think you are onto something! If |
Thats a valid approach, like changing get_utxo/verify_tx to use .remove would naturally catch duplicates but maybe i think the tradeoff is that the current approach will catch it earlier in check_transaction_context_free(), before touching utxo mapping (also it matches the bitcoin core design the checktransaction fn one where duplicte inputs are rejected as a strctual prop, independent of any chain state). happy to update the pr either way, pls let me know which approach is preferable. |
|
Hii @Davidson-Souza Just a gentle ping on this PR whenever you get time to discuss or review. Thanks!! |
|
I prefer the latter (not using an extra hash set). Perhaps we could have an issue to discuss this mo in-depth? PRs are usually not the place for deep discussions. |
|
need rebase |
rebased. |
| if !used_in_this_tx.insert(previous_output) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
I don’t understand the reason for this here.
There was a problem hiding this comment.
The used_in_this_tx guard is necessary since check_transaction_context_free() now rejects any transaction containing duplicate inputs.
In the original build_transactions(..., true) code, transactions with duplicate inputs were inadvertently being created because the same outpoint could be reused multiple times inside the inner loop. Once the consensus validation was added, test_gbt_with_conflict started failing with DuplicateInput before the mempool conflict logic even kicked in.
So i added guard which makes sure that each outpoint appears only once within a single transaction.
There was a problem hiding this comment.
In the mempool this does not make sense, because in the mempool there can be RBF.
There was a problem hiding this comment.
In the mempool this does not make sense, because in the mempool there can be RBF.
To clarify, used_in_this_tx is in build_transactions(), which is a test helper function that creates fake transactions. This is not related to the mempool logic at all and does not affect RBF.
RBF requires two valid transactions competing against one another in the mempool, and that behavior is untouched by this PR.
This is just a guard that stops build_transactions() from creating an invalid transaction that uses the same input twice in a transaction.
However, I can see where you're coming from and am happy to follow your recommendation on closing this and waiting until the discussion in the issue is over.
moisesPompilio
left a comment
There was a problem hiding this comment.
I think it’s better to close this PR because it is not mature enough. There is still an open issue to discuss this problem.
| if !used_in_this_tx.insert(previous_output) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
In the mempool this does not make sense, because in the mempool there can be RBF.
Description and Notes
This PR adds duplicate input detection inside
check_transaction_context_free(), closing a missing consensus-level validation gap.Floresta had no context-free check for duplicate inputs. A transaction spending the same
OutPointtwice could pass consensus checks and proceed further into verification. Mempool tests were also constructing duplicate inputs inside a single transaction, which masked the missing consensus validation.Bitcoin Core performs this check in
CheckTransaction()(see CVE-2018-17144) because missing it can cause crashes or inflation bugs depending on UTXO handling.In Floresta,
get_utxo()uses.get()on the UTXO map, so the same UTXO value could be counted twice towardin_value, creating a potential inflation vector.Changes
DuplicateInputtoBlockValidationErrorswith a correspondingDisplayimplementationHashSet-based duplicate prevout check incheck_transaction_context_free()DuplicatedInputstoConflictingTransactionDuplicateInputinfloresta-wireblock validation flowCheckTransaction()behaviorHow to verify the changes you have done?