1
0
mirror of https://github.com/bitcoin/bips.git synced 2026-04-20 16:28:39 +00:00

BIP-375: add input eligibility validation

Verify segwit version >1 not used if silent payment outputs present (bip352)
Verify SIGHASH_ALL requirement
This commit is contained in:
macgyver13
2026-02-23 10:17:56 -05:00
parent 6a91f88030
commit ab30224051

View File

@@ -6,17 +6,20 @@ Provides independent checks for PSBT structure, ECDH share coverage,
input eligibility, and output script correctness. input eligibility, and output script correctness.
""" """
import struct
from typing import Tuple from typing import Tuple
from deps.bitcoin_test.psbt import ( from deps.bitcoin_test.psbt import (
PSBT, PSBT,
PSBT_GLOBAL_TX_MODIFIABLE, PSBT_GLOBAL_TX_MODIFIABLE,
PSBT_IN_SIGHASH_TYPE,
PSBT_IN_WITNESS_UTXO,
PSBT_OUT_SCRIPT, PSBT_OUT_SCRIPT,
) )
from deps.dleq import dleq_verify_proof from deps.dleq import dleq_verify_proof
from secp256k1lab.secp256k1 import GE from secp256k1lab.secp256k1 import GE
from .inputs import is_input_eligible, pubkey_from_eligible_input from .inputs import is_input_eligible, parse_witness_utxo, pubkey_from_eligible_input
from .psbt_bip375 import ( from .psbt_bip375 import (
PSBT_GLOBAL_SP_ECDH_SHARE, PSBT_GLOBAL_SP_ECDH_SHARE,
PSBT_GLOBAL_SP_DLEQ, PSBT_GLOBAL_SP_DLEQ,
@@ -247,7 +250,38 @@ def validate_dleq_proof(
def validate_input_eligibility(psbt: PSBT) -> Tuple[bool, str]: def validate_input_eligibility(psbt: PSBT) -> Tuple[bool, str]:
return False, "Input eligibility check not implemented yet" """
Validate input eligibility constraints for silent payments
Checks:
- No segwit v>1 inputs when SP outputs present
- SIGHASH_ALL required when SP outputs present
"""
# Check if SP outputs exist
has_sp_outputs = any(PSBT_OUT_SP_V0_INFO in om for om in psbt.o)
if not has_sp_outputs:
return True, None
# Check segwit version restrictions
for i, input_map in enumerate(psbt.i):
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+)
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
for i, input_map in enumerate(psbt.i):
if PSBT_IN_SIGHASH_TYPE in input_map:
sighash = input_map[PSBT_IN_SIGHASH_TYPE]
if len(sighash) >= 4:
sighash_type = struct.unpack("<I", sighash[:4])[0]
if sighash_type != 1: # SIGHASH_ALL
return (
False,
f"Input {i} uses non-SIGHASH_ALL ({sighash_type}) with silent payments",
)
return True, None
def validate_output_scripts(psbt: PSBT) -> Tuple[bool, str]: def validate_output_scripts(psbt: PSBT) -> Tuple[bool, str]: