@@ -296,9 +296,24 @@ impl Consensus {
296296 return Err ( tx_err ! ( txid, NullPrevOut ) ) ?;
297297 }
298298
299- // Check script sizes (current tx scriptsig and TODO witness if present)
299+ // Witness size is intentionally not checked here — witness-specific
300+ // limits are enforced during script execution, not in context-free checks.
301+ // This matches Bitcoin Core's CheckTransaction() which explicitly skips
302+ // witness in context-free checks because witness data has not been
303+ // checked for malleability at this point.
304+ // See: https://github.com/bitcoin/bitcoin/blob/master/src/consensus/tx_check.cpp
300305 Self :: validate_script_size ( & input. script_sig , txid) ?;
301- // TODO check also witness script size
306+ }
307+
308+ // Check for duplicate inputs (CVE-2018-17144).
309+ // UpdateCoins does not detect duplicates — a duplicate prevout causes either
310+ // a crash or an inflation bug depending on the coins database implementation.
311+ // Bitcoin Core catches this explicitly in CheckTransaction() for the same reason.
312+ let mut seen = HashSet :: new ( ) ;
313+ for input in & transaction. input {
314+ if !seen. insert ( & input. previous_output ) {
315+ return Err ( tx_err ! ( txid, DuplicateInput ) ) ?;
316+ }
302317 }
303318
304319 let out_value = transaction
@@ -983,6 +998,24 @@ mod tests {
983998 }
984999 }
9851000
1001+ #[ test]
1002+ fn test_duplicate_inputs_rejected ( ) {
1003+ let outpoint = dummy_outpoint ( ) ;
1004+
1005+ // Same prevout used in both inputs
1006+ let tx = build_tx (
1007+ vec ! [ txin!( outpoint) , txin!( outpoint) ] ,
1008+ vec ! [ txout!( 0 , ScriptBuf :: new( ) ) ] ,
1009+ ) ;
1010+
1011+ match Consensus :: check_transaction_context_free ( & tx) {
1012+ Err ( BlockchainError :: TransactionError ( tx_err) ) => {
1013+ assert_eq ! ( tx_err. error, BlockValidationErrors :: DuplicateInput ) ;
1014+ }
1015+ other => panic ! ( "Expected DuplicateInput, got: {other:?}" ) ,
1016+ }
1017+ }
1018+
9861019 #[ test]
9871020 fn test_input_value_above_max_money ( ) {
9881021 let outpoint = dummy_outpoint ( ) ;
0 commit comments