diff --git a/bip-0352.mediawiki b/bip-0352.mediawiki index da947e56..8ac0719d 100644 --- a/bip-0352.mediawiki +++ b/bip-0352.mediawiki @@ -190,6 +190,7 @@ Future silent payments versions will use the following scheme: For silent payments v0 a transaction MUST be scanned if and only if all of the following are true: +* The transaction is consensus-valid * The transaction contains at least one BIP341 taproot output (note: spent transactions optionally can be skipped by only considering transactions with at least one unspent taproot output) * The transaction has at least one input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list * The transaction does not spend an output with SegWit version > 1'''Why skip transactions that spend SegWit version > 1?''' Skipping transactions that spend unknown output scripts allows us to have a clean upgrade path for silent payments by avoiding the need to scan the same transaction multiple times with different rule sets. If a new SegWit version is added in the future and silent payments v1 is released with support, we would want to avoid having to first scan the transaction with the silent payment v0 rules and then again with the silent payment v1 rules. Note: this restriction only applies to the inputs of a transaction. diff --git a/bip-0352/reference.py b/bip-0352/reference.py index c334d328..b38a29e5 100755 --- a/bip-0352/reference.py +++ b/bip-0352/reference.py @@ -32,6 +32,10 @@ from bitcoin_utils import ( K_max = 2323 # per-group recipient limit NUMS_H = 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 +TAPROOT_CONTROL_BASE_SIZE = 33 +TAPROOT_CONTROL_NODE_SIZE = 32 +TAPROOT_CONTROL_MAX_NODE_COUNT = 128 +TAPROOT_CONTROL_MAX_SIZE = TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT def get_pubkey_from_input(vin: VinInfo) -> GE: @@ -79,6 +83,9 @@ def get_pubkey_from_input(vin: VinInfo) -> GE: # Script-path spend control_block = witnessStack[-1] # control block is <32 byte internal key> and 0 or more <32 byte hash> + assert len(control_block) >= TAPROOT_CONTROL_BASE_SIZE + assert len(control_block) <= TAPROOT_CONTROL_MAX_SIZE + assert (len(control_block) - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE == 0 internal_key = control_block[1:33] if (internal_key == NUMS_H.to_bytes(32, 'big')): # Skip if NUMS_H