From e726d13ade44e2184635935c84a83d4082da3a63 Mon Sep 17 00:00:00 2001 From: questfever Date: Thu, 13 Aug 2026 17:29:30 +0800 Subject: [PATCH] BIP375: correctly detect SegWit v2+ witness programs --- bip-0375/bip375_test_vectors.json | 19 ++++++++++++++++++- bip-0375/validator/validate_psbt.py | 11 ++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/bip-0375/bip375_test_vectors.json b/bip-0375/bip375_test_vectors.json index 3f16f51b..38511f65 100644 --- a/bip-0375/bip375_test_vectors.json +++ b/bip-0375/bip375_test_vectors.json @@ -568,6 +568,23 @@ } ], "valid": [ + { + "description": "input eligibility: bare OP_2 script is not a segwit v2 witness program", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAQqghgEAAAAAAAFSIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "prevout_scriptpubkey": "52", + "amount": 100000, + "witness_utxo": "a0860100000000000152" + } + ] + }, + "checks": [ + "input_eligibility" + ] + }, { "description": "can finalize: one P2PKH input single-signer", "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIDnBDcvHz0XG2UNW/1DBK42GqVUM8DcXPZzr94cU5nx1AiBxlVpC7SBTJDIHI8TwFCXc6J9CX4NwKEy0J2z9tt6jrAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", @@ -1756,4 +1773,4 @@ } } ] -} \ No newline at end of file +} diff --git a/bip-0375/validator/validate_psbt.py b/bip-0375/validator/validate_psbt.py index 0ec7c848..bc5c1d44 100644 --- a/bip-0375/validator/validate_psbt.py +++ b/bip-0375/validator/validate_psbt.py @@ -250,6 +250,15 @@ def validate_dleq_proof( return True, None +def is_segwit_v2_or_later(script_pubkey: bytes) -> bool: + """Return whether script_pubkey is a SegWit v2-v16 witness program.""" + return ( + 4 <= len(script_pubkey) <= 42 + and 0x52 <= script_pubkey[0] <= 0x60 # OP_2 through OP_16 + and script_pubkey[1] == len(script_pubkey) - 2 + ) + + def validate_input_eligibility(psbt: PSBT) -> Tuple[bool, str]: """ Validate input eligibility constraints for silent payments @@ -268,7 +277,7 @@ def validate_input_eligibility(psbt: PSBT) -> Tuple[bool, str]: if PSBT_IN_WITNESS_UTXO in input_map: witness_utxo = input_map[PSBT_IN_WITNESS_UTXO] script = parse_witness_utxo(witness_utxo) - if script and 0x51 < script[0] <= 0x60: # OP_2 or higher (segwit v2+) + if is_segwit_v2_or_later(script): return False, f"Input {i} uses segwit version > 1 with silent payments" # Check SIGHASH_ALL requirement - PSBT_IN_SIGHASH_TYPE is optional, but if set it must be SIGHASH_ALL when SP outputs are present