mirror of
https://github.com/bitcoin/bips.git
synced 2026-05-04 16:41:51 +00:00
BIP-375: add output scripts validation
Add support for computing bip352 output scripts Extract ECDH shares and public key from PSBT and aggregate both if necessary Refactor validate_ecdh_coverage to use collect_input_ecdh_and_pubkey
This commit is contained in:
51
bip-0375/validator/bip352_crypto.py
Normal file
51
bip-0375/validator/bip352_crypto.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Silent payment output script derivation
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
from deps.bitcoin_test.messages import COutPoint
|
||||
from secp256k1lab.secp256k1 import G, GE, Scalar
|
||||
from secp256k1lab.ecdh import ecdh_compressed_in_raw_out
|
||||
from secp256k1lab.util import tagged_hash
|
||||
|
||||
|
||||
def compute_silent_payment_output_script(
|
||||
outpoints: List[COutPoint],
|
||||
summed_pubkey_bytes: bytes,
|
||||
ecdh_share_bytes: bytes,
|
||||
spend_pubkey_bytes: bytes,
|
||||
k: int,
|
||||
) -> bytes:
|
||||
"""Compute silent payment output script per BIP-352"""
|
||||
input_hash_bytes = get_input_hash(outpoints, GE.from_bytes(summed_pubkey_bytes))
|
||||
|
||||
# Compute shared_secret = input_hash * ecdh_share
|
||||
shared_secret_bytes = ecdh_compressed_in_raw_out(
|
||||
input_hash_bytes, ecdh_share_bytes
|
||||
).to_bytes_compressed()
|
||||
|
||||
# Compute t_k = hash_BIP0352/SharedSecret(shared_secret || k)
|
||||
t_k = Scalar.from_bytes_checked(
|
||||
tagged_hash("BIP0352/SharedSecret", shared_secret_bytes + ser_uint32(k))
|
||||
)
|
||||
|
||||
# Compute P_k = B_spend + t_k * G
|
||||
B_spend = GE.from_bytes(spend_pubkey_bytes)
|
||||
P_k = B_spend + t_k * G
|
||||
|
||||
# Return P2TR script (x-only pubkey)
|
||||
return bytes([0x51, 0x20]) + P_k.to_bytes_xonly()
|
||||
|
||||
|
||||
def get_input_hash(outpoints: List[COutPoint], sum_input_pubkeys: GE) -> bytes:
|
||||
"""Compute input hash per BIP-352"""
|
||||
lowest_outpoint = sorted(outpoints, key=lambda outpoint: outpoint.serialize())[0]
|
||||
return tagged_hash(
|
||||
"BIP0352/Inputs",
|
||||
lowest_outpoint.serialize() + sum_input_pubkeys.to_bytes_compressed(),
|
||||
)
|
||||
|
||||
|
||||
def ser_uint32(u: int) -> bytes:
|
||||
return u.to_bytes(4, "big")
|
||||
Reference in New Issue
Block a user