2021-06-25 05:53:51 +00:00
#!/usr/bin/env python3
# Copyright (c) 2014-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test for taproot sighash algorithm with pegins and issuances
2021-08-25 20:47:13 +00:00
from random import randint
2021-07-11 11:02:11 +00:00
from test_framework . util import BITCOIN_ASSET_BYTES , assert_raises_rpc_error , satoshi_round
2021-10-14 23:48:40 +00:00
from test_framework . key import ECKey , compute_xonly_pubkey , generate_privkey , sign_schnorr
from test_framework . messages import COIN , COutPoint , CTransaction , CTxIn , CTxInWitness , CTxOut , CTxOutNonce , CTxOutValue , ser_uint256 , sha256 , tx_from_hex
2021-06-25 05:53:51 +00:00
from test_framework . test_framework import BitcoinTestFramework
2021-10-14 23:48:40 +00:00
from test_framework . script import CScript , CScriptNum , CScriptOp , OP_0 , OP_1 , OP_2 , OP_ADD64 , OP_AND , OP_CHECKSIGFROMSTACK , OP_DIV64 , OP_DROP , OP_DUP , OP_ECMULSCALARVERIFY , OP_EQUAL , OP_EQUALVERIFY , OP_FALSE , OP_FROMALTSTACK , OP_GREATERTHAN64 , OP_GREATERTHANOREQUAL64 , OP_INSPECTINPUTASSET , OP_INSPECTINPUTISSUANCE , OP_INSPECTINPUTOUTPOINT , OP_INSPECTINPUTSCRIPTPUBKEY , OP_INSPECTINPUTSEQUENCE , OP_INSPECTINPUTVALUE , OP_INSPECTLOCKTIME , OP_INSPECTNUMINPUTS , OP_INSPECTNUMOUTPUTS , OP_INSPECTOUTPUTASSET , OP_INSPECTOUTPUTNONCE , OP_INSPECTOUTPUTSCRIPTPUBKEY , OP_INSPECTOUTPUTVALUE , OP_INSPECTVERSION , OP_LE32TOLE64 , OP_LE64TOSCRIPTNUM , OP_LESSTHAN64 , OP_LESSTHANOREQUAL64 , OP_MUL64 , OP_NEG64 , OP_NOT , OP_INVERT , OP_OR , OP_PUSHCURRENTINPUTINDEX , OP_SCRIPTNUMTOLE64 , OP_SHA256FINALIZE , OP_SHA256INITIALIZE , OP_SHA256UPDATE , OP_SIZE , OP_SUB64 , OP_SWAP , OP_TWEAKVERIFY , OP_TOALTSTACK , OP_TXWEIGHT , OP_VERIFY , OP_XOR , taproot_construct , SIGHASH_DEFAULT , SIGHASH_ALL , SIGHASH_NONE , SIGHASH_SINGLE , SIGHASH_ANYONECANPAY
2021-06-25 05:53:51 +00:00
import os
VALID_SIGHASHES_ECDSA = [
SIGHASH_ALL ,
SIGHASH_NONE ,
SIGHASH_SINGLE ,
SIGHASH_ANYONECANPAY + SIGHASH_ALL ,
SIGHASH_ANYONECANPAY + SIGHASH_NONE ,
SIGHASH_ANYONECANPAY + SIGHASH_SINGLE
]
VALID_SIGHASHES_TAPROOT = [ SIGHASH_DEFAULT ] + VALID_SIGHASHES_ECDSA
class TapHashPeginTest ( BitcoinTestFramework ) :
def set_test_params ( self ) :
self . setup_clean_chain = True
self . num_nodes = 1
self . extra_args = [
[ " -initialfreecoins=2100000000000000 " ,
" -anyonecanspendaremine=1 " ,
" -blindedaddresses=1 " ,
" -validatepegin=0 " ,
" -con_parent_chain_signblockscript=51 " ,
" -parentscriptprefix=75 " ,
" -parent_bech32_hrp=ert " ,
" -minrelaytxfee=0 " ,
" -maxtxfee=100.0 " ,
] ]
def skip_test_if_missing_module ( self ) :
self . skip_if_no_wallet ( )
def setup_network ( self , split = False ) :
self . setup_nodes ( )
2021-07-11 11:02:11 +00:00
def get_utxo ( self , fund_tx , idx ) :
spent = None
# Coin selection
for utxo in self . nodes [ 0 ] . listunspent ( ) :
if utxo [ " txid " ] == ser_uint256 ( fund_tx . vin [ idx ] . prevout . hash ) [ : : - 1 ] . hex ( ) and utxo [ " vout " ] == fund_tx . vin [ idx ] . prevout . n :
spent = utxo
assert ( spent is not None )
assert ( len ( fund_tx . vin ) == 2 )
return spent
def create_taproot_utxo ( self , scripts = None , blind = False ) :
2021-06-25 05:53:51 +00:00
# modify the transaction to add one output that should spend previous taproot
# Create a taproot prevout
addr = self . nodes [ 0 ] . getnewaddress ( )
sec = generate_privkey ( )
pub = compute_xonly_pubkey ( sec ) [ 0 ]
tap = taproot_construct ( pub , scripts )
spk = tap . scriptPubKey
# No need to test blinding in this unit test
unconf_addr = self . nodes [ 0 ] . getaddressinfo ( addr ) [ ' unconfidential ' ]
raw_tx = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { unconf_addr : 1.2 } ] )
# edit spk directly, no way to get new address.
# would need to implement bech32m in python
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( raw_tx )
2021-06-25 05:53:51 +00:00
tx . vout [ 0 ] . scriptPubKey = spk
tx . vout [ 0 ] . nValue = CTxOutValue ( 12 * 10 * * 7 )
raw_hex = tx . serialize ( ) . hex ( )
fund_tx = self . nodes [ 0 ] . fundrawtransaction ( raw_hex , False , ) [ " hex " ]
2021-09-05 12:35:58 +00:00
fund_tx = tx_from_hex ( fund_tx )
2021-06-25 05:53:51 +00:00
# Createrawtransaction might rearrage txouts
prev_vout = None
for i , out in enumerate ( fund_tx . vout ) :
if spk == out . scriptPubKey :
prev_vout = i
tx = self . nodes [ 0 ] . blindrawtransaction ( fund_tx . serialize ( ) . hex ( ) )
signed_raw_tx = self . nodes [ 0 ] . signrawtransactionwithwallet ( tx )
2021-10-14 23:48:40 +00:00
self . nodes [ 0 ] . sendrawtransaction ( signed_raw_tx [ ' hex ' ] )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( signed_raw_tx [ ' hex ' ] )
2021-06-25 05:53:51 +00:00
tx . rehash ( )
2023-11-13 09:06:43 +00:00
self . generate ( self . nodes [ 0 ] , 1 )
2021-06-25 05:53:51 +00:00
last_blk = self . nodes [ 0 ] . getblock ( self . nodes [ 0 ] . getbestblockhash ( ) )
assert ( tx . hash in last_blk [ ' tx ' ] )
return tx , prev_vout , spk , sec , pub , tap
2021-10-14 23:48:40 +00:00
def tapscript_satisfy_test ( self , script , inputs = None , add_issuance = False ,
add_pegin = False , fail = None , add_prevout = False , add_asset = False ,
add_value = False , add_spk = False , seq = 0 , add_out_spk = None ,
add_out_asset = None , add_out_value = None , add_out_nonce = None ,
ver = 2 , locktime = 0 , add_num_outputs = False , add_weight = False , blind = False ) :
if inputs is None :
inputs = [ ]
2021-06-25 05:53:51 +00:00
# Create a taproot utxo
scripts = [ ( " s0 " , script ) ]
prev_tx , prev_vout , spk , sec , pub , tap = self . create_taproot_utxo ( scripts )
2021-07-11 11:02:11 +00:00
if add_pegin :
fund_info = self . nodes [ 0 ] . getpeginaddress ( )
peg_id = self . nodes [ 0 ] . sendtoaddress ( fund_info [ " mainchain_address " ] , 1 )
raw_peg_tx = self . nodes [ 0 ] . gettransaction ( peg_id ) [ " hex " ]
peg_txid = self . nodes [ 0 ] . sendrawtransaction ( raw_peg_tx )
2023-11-13 09:06:43 +00:00
self . generate ( self . nodes [ 0 ] , 101 )
2021-07-11 11:02:11 +00:00
peg_prf = self . nodes [ 0 ] . gettxoutproof ( [ peg_txid ] )
claim_script = fund_info [ " claim_script " ]
raw_claim = self . nodes [ 0 ] . createrawpegin ( raw_peg_tx , peg_prf , claim_script )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( raw_claim [ ' hex ' ] )
2021-07-11 11:02:11 +00:00
else :
tx = CTransaction ( )
tx . nVersion = ver
tx . nLockTime = locktime
2021-06-25 05:53:51 +00:00
# Spend the pegin and taproot tx together
in_total = prev_tx . vout [ prev_vout ] . nValue . getAmount ( )
fees = 1000
2021-07-11 11:02:11 +00:00
tap_in_pos = 0
if blind :
# Add an unrelated output
key = ECKey ( )
key . generate ( )
tx . vout . append ( CTxOut ( nValue = CTxOutValue ( 10000 ) , scriptPubKey = spk , nNonce = CTxOutNonce ( key . get_pubkey ( ) . get_bytes ( ) ) ) )
tx_hex = self . nodes [ 0 ] . fundrawtransaction ( tx . serialize ( ) . hex ( ) )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( tx_hex [ ' hex ' ] )
2021-07-11 11:02:11 +00:00
tx . vin . append ( CTxIn ( COutPoint ( prev_tx . sha256 , prev_vout ) , nSequence = seq ) )
2021-06-25 05:53:51 +00:00
tx . vout . append ( CTxOut ( nValue = CTxOutValue ( in_total - fees ) , scriptPubKey = spk ) ) # send back to self
tx . vout . append ( CTxOut ( CTxOutValue ( fees ) ) )
2021-07-11 11:02:11 +00:00
if add_issuance :
blind_addr = self . nodes [ 0 ] . getnewaddress ( )
issue_addr = self . nodes [ 0 ] . validateaddress ( blind_addr ) [ ' unconfidential ' ]
# Issuances only require one fee output and that output must the last
# one. However the way, the current code is structured, it is not possible
# to this in a super clean without special casing.
if add_pegin :
tx . vout . pop ( )
tx . vout . pop ( )
tx . vout . insert ( 0 , CTxOut ( nValue = CTxOutValue ( in_total ) , scriptPubKey = spk ) ) # send back to self)
issued_tx = self . nodes [ 0 ] . rawissueasset ( tx . serialize ( ) . hex ( ) , [ { " asset_amount " : 2 , " asset_address " : issue_addr , " blind " : False } ] ) [ 0 ] [ " hex " ]
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( issued_tx )
2021-07-11 11:02:11 +00:00
# Sign inputs
if add_pegin :
signed = self . nodes [ 0 ] . signrawtransactionwithwallet ( tx . serialize ( ) . hex ( ) )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( signed [ ' hex ' ] )
2021-07-11 11:02:11 +00:00
tap_in_pos + = 1
else :
# Need to create empty witness when not deserializing from rpc
tx . wit . vtxinwit . append ( CTxInWitness ( ) )
if blind :
tx . vin [ 0 ] , tx . vin [ 1 ] = tx . vin [ 1 ] , tx . vin [ 0 ]
utxo = self . get_utxo ( tx , 1 )
zero_str = " 0 " * 64
blinded_raw = self . nodes [ 0 ] . rawblindrawtransaction ( tx . serialize ( ) . hex ( ) , [ zero_str , utxo [ " amountblinder " ] ] , [ 1.2 , utxo [ ' amount ' ] ] , [ utxo [ ' asset ' ] , utxo [ ' asset ' ] ] , [ zero_str , utxo [ ' assetblinder ' ] ] )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( blinded_raw )
2021-07-11 11:02:11 +00:00
signed_raw_tx = self . nodes [ 0 ] . signrawtransactionwithwallet ( tx . serialize ( ) . hex ( ) )
2021-09-05 12:35:58 +00:00
tx = tx_from_hex ( signed_raw_tx [ ' hex ' ] )
2021-07-11 11:02:11 +00:00
2021-06-25 05:53:51 +00:00
suffix_annex = [ ]
2021-09-05 12:35:58 +00:00
control_block = bytes ( [ tap . leaves [ " s0 " ] . version + tap . negflag ] ) + tap . internal_pubkey + tap . leaves [ " s0 " ] . merklebranch
2021-07-11 11:02:11 +00:00
# Add the prevout to the top of inputs. The witness script will check for equality.
if add_prevout :
inputs = [ prev_vout . to_bytes ( 4 , ' little ' ) , ser_uint256 ( prev_tx . sha256 ) ]
if add_asset :
assert blind # only used with blinding in testing
utxo = self . nodes [ 0 ] . gettxout ( ser_uint256 ( tx . vin [ 1 ] . prevout . hash ) [ : : - 1 ] . hex ( ) , tx . vin [ 1 ] . prevout . n )
if " assetcommitment " in utxo :
asset = bytes . fromhex ( utxo [ " assetcommitment " ] )
else :
asset = b " \x01 " + bytes . fromhex ( utxo [ " asset " ] ) [ : : - 1 ]
inputs = [ asset [ 0 : 1 ] , asset [ 1 : 33 ] ]
if add_value :
utxo = self . nodes [ 0 ] . gettxout ( ser_uint256 ( tx . vin [ 1 ] . prevout . hash ) [ : : - 1 ] . hex ( ) , tx . vin [ 1 ] . prevout . n )
if " valuecommitment " in utxo :
value = bytes . fromhex ( utxo [ " valuecommitment " ] )
inputs = [ value [ 0 : 1 ] , value [ 1 : 33 ] ]
else :
value = b " \x01 " + int ( satoshi_round ( utxo [ " value " ] ) * COIN ) . to_bytes ( 8 , ' little ' )
inputs = [ value [ 0 : 1 ] , value [ 1 : 9 ] ]
if add_spk :
ver = CScriptOp . decode_op_n ( int . from_bytes ( spk [ 0 : 1 ] , ' little ' ) )
inputs = [ CScriptNum . encode ( CScriptNum ( ver ) ) [ 1 : ] , spk [ 2 : len ( spk ) ] ] # always segwit
# Add witness for outputs
if add_out_asset is not None :
asset = tx . vout [ add_out_asset ] . nAsset . vchCommitment
inputs = [ asset [ 0 : 1 ] , asset [ 1 : 33 ] ]
if add_out_value is not None :
value = tx . vout [ add_out_value ] . nValue . vchCommitment
if len ( value ) == 9 :
inputs = [ value [ 0 : 1 ] , value [ 1 : 9 ] [ : : - 1 ] ]
else :
inputs = [ value [ 0 : 1 ] , value [ 1 : 33 ] ]
if add_out_nonce is not None :
nonce = tx . vout [ add_out_nonce ] . nNonce . vchCommitment
if len ( nonce ) == 1 :
inputs = [ b ' ' ]
else :
inputs = [ nonce ]
if add_out_spk is not None :
out_spk = tx . vout [ add_out_spk ] . scriptPubKey
if len ( out_spk ) == 0 :
# Python upstream encoding CScriptNum interesting behaviour where it also encodes the length
# This assumes the implicit wallet behaviour of using segwit outputs.
# This is useful while sending scripts, but not while using CScriptNums in constructing scripts
inputs = [ CScriptNum . encode ( CScriptNum ( - 1 ) ) [ 1 : ] , sha256 ( out_spk ) ]
else :
ver = CScriptOp . decode_op_n ( int . from_bytes ( out_spk [ 0 : 1 ] , ' little ' ) )
inputs = [ CScriptNum . encode ( CScriptNum ( ver ) ) [ 1 : ] , out_spk [ 2 : len ( out_spk ) ] ] # always segwit
if add_num_outputs :
num_outs = len ( tx . vout )
inputs = [ CScriptNum . encode ( CScriptNum ( num_outs ) ) [ 1 : ] ]
if add_weight :
# Add a dummy input and check the overall weight
inputs = [ int ( 5 ) . to_bytes ( 8 , ' little ' ) ]
wit = inputs + [ bytes ( tap . leaves [ " s0 " ] . script ) , control_block ] + suffix_annex
tx . wit . vtxinwit [ tap_in_pos ] . scriptWitness . stack = wit
exp_weight = self . nodes [ 0 ] . decoderawtransaction ( tx . serialize ( ) . hex ( ) ) [ " weight " ]
inputs = [ exp_weight . to_bytes ( 8 , ' little ' ) ]
2021-06-25 05:53:51 +00:00
wit = inputs + [ bytes ( tap . leaves [ " s0 " ] . script ) , control_block ] + suffix_annex
2021-07-11 11:02:11 +00:00
tx . wit . vtxinwit [ tap_in_pos ] . scriptWitness . stack = wit
if fail :
assert_raises_rpc_error ( - 26 , fail , self . nodes [ 0 ] . sendrawtransaction , tx . serialize ( ) . hex ( ) )
return
2021-06-25 05:53:51 +00:00
self . nodes [ 0 ] . sendrawtransaction ( hexstring = tx . serialize ( ) . hex ( ) )
2023-11-13 09:06:43 +00:00
self . generate ( self . nodes [ 0 ] , 1 )
2021-06-25 05:53:51 +00:00
last_blk = self . nodes [ 0 ] . getblock ( self . nodes [ 0 ] . getbestblockhash ( ) )
tx . rehash ( )
assert ( tx . hash in last_blk [ ' tx ' ] )
def run_test ( self ) :
2023-11-13 09:06:43 +00:00
self . generate ( self . nodes [ 0 ] , 101 )
2021-06-25 05:53:51 +00:00
self . wait_until ( lambda : self . nodes [ 0 ] . getblockcount ( ) == 101 , timeout = 5 )
2023-11-13 15:10:30 +00:00
# ELEMENTS: spend the initialfreecoins to node0, to fix bad-txns-inputs-missingorspent error when creating the first taproot utxo
2023-11-13 09:06:43 +00:00
self . nodes [ 0 ] . sendtoaddress ( self . nodes [ 0 ] . getnewaddress ( ) , 50 )
self . generate ( self . nodes [ 0 ] , 1 )
2021-06-25 05:53:51 +00:00
# Test whether the above test framework is working
self . log . info ( " Test simple op_1 " )
self . tapscript_satisfy_test ( CScript ( [ OP_1 ] ) )
# Test streaming sha256
2021-10-14 21:48:49 +00:00
# All preimages up to len 80 can be filled in a single standard witness element
2021-06-25 05:53:51 +00:00
# Testing only random even len for speedup
2021-07-11 11:02:11 +00:00
self . log . info ( " Testing streaming SHA256 " )
2021-06-25 05:53:51 +00:00
for k in range ( 0 , 81 , 2 ) :
preimage = os . urandom ( k )
hash = sha256 ( preimage )
self . tapscript_satisfy_test ( CScript ( [ OP_SHA256INITIALIZE , OP_SWAP , OP_SHA256FINALIZE , hash , OP_EQUAL ] ) , inputs = [ bytes ( 0 ) , preimage ] )
# All preimages greater than 80 require Cating the elements
# But this only works till 520 bytes, streaming opcodes can
# be when dealing with more than 520 bytes
# Also adds a test when the sha256 buffer is full
for pre_len in [ 64 * i for i in range ( 2 , 10 ) ] + [ 100 , 520 , 521 , 800 , 1000 , 10000 ] :
preimage = os . urandom ( pre_len )
hash = sha256 ( preimage )
# Split into chunks of 80
wit = [ preimage [ i : min ( i + 80 , len ( preimage ) ) ] for i in range ( 0 , len ( preimage ) , 80 ) ]
script = CScript ( [ OP_SHA256INITIALIZE ] + [ OP_SWAP , OP_SHA256UPDATE ] * ( len ( wit ) - 2 ) + [ OP_SWAP , OP_SHA256FINALIZE , hash , OP_EQUAL ] )
self . tapscript_satisfy_test ( script , wit [ : : - 1 ] )
2021-07-11 11:02:11 +00:00
# Test introspection opcodes
# 1a. No Pegins/issuances
self . log . info ( " Instrospection tests: outpoint flag " )
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \x00 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) )
# 1b. Add a pegin (Test pegin input must be 0x40)
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \x40 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) , add_pegin = True )
# 1c. Add pegin (The non-pegin input must be push 0x00)
self . tapscript_satisfy_test ( CScript ( [ OP_1 , OP_INSPECTINPUTOUTPOINT , b ' \x00 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) , add_pegin = True )
# 1d. Add an issuance
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \x80 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) , add_issuance = True )
# 1e. Both issuance and pegins together
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \xc0 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) , add_pegin = True , add_issuance = True )
# 1f. Failure test case
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \x00 ' , OP_EQUALVERIFY , OP_DROP , OP_DROP , OP_1 ] ) , add_pegin = True , add_issuance = True , fail = " Script failed an OP_EQUALVERIFY operation " )
# Test opcode for inspecting prev tx
self . log . info ( " Instrospection tests: inputs " )
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTOUTPOINT , b ' \x00 ' , OP_EQUALVERIFY , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , add_prevout = True )
# Test taproot asset with blinding.
self . tapscript_satisfy_test ( CScript ( [ OP_1 ] ) , blind = True )
# 2 Test asset(explicit and conf)
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTASSET , 1 , OP_EQUALVERIFY , BITCOIN_ASSET_BYTES , OP_EQUAL ] ) )
for _ in range ( 5 ) : # run multiple times for wallet to select conf utxos
self . tapscript_satisfy_test ( CScript ( [ OP_1 , OP_INSPECTINPUTASSET , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , blind = True , add_asset = True )
# 3 Test asset(explicit and conf)
amt = 12 * 10 * * 7
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTVALUE , 1 , OP_EQUALVERIFY , amt . to_bytes ( 8 , ' little ' ) , OP_EQUAL ] ) )
for _ in range ( 5 ) : # run multiple times for wallet to select conf utxos
self . tapscript_satisfy_test ( CScript ( [ OP_1 , OP_INSPECTINPUTVALUE , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , blind = True , add_value = True )
# 4 Test scriptpubkey
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTSCRIPTPUBKEY , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , add_spk = True )
# 5 Test nSequence
one , two = 1 , 2
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTSEQUENCE , one . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , seq = 1 )
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTSEQUENCE , two . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , seq = 1 , fail = " Script evaluated without error but finished with a false/empty top stack element " )
# 6 Test issuances
# No issaunce
self . tapscript_satisfy_test ( CScript ( [ OP_0 , OP_INSPECTINPUTISSUANCE , OP_FALSE , OP_EQUAL ] ) )
# Issuance with 2 units
asset_issue_amount = 2 * COIN
self . tapscript_satisfy_test ( CScript ( [
OP_0 , OP_INSPECTINPUTISSUANCE ,
# Check blinding nonce is zero
bytes ( 32 ) , OP_EQUALVERIFY ,
# Check the entropy is 32 bytes
OP_SIZE , 32 , OP_EQUALVERIFY , OP_DROP ,
# Check the explicit issue amount
1 , OP_EQUALVERIFY , asset_issue_amount . to_bytes ( 8 , ' little ' ) , OP_EQUALVERIFY ,
# Last inflation keys is null, check it as explicit `0` LE 8
1 , OP_EQUALVERIFY , int ( 0 ) . to_bytes ( 8 , ' little ' ) , OP_EQUAL
] ) , add_issuance = True )
# Input index out of bounds
self . tapscript_satisfy_test ( CScript ( [ 120 , OP_1 , OP_INSPECTINPUTASSET , OP_FALSE , OP_EQUAL ] ) , fail = " Introspection index out of bounds " )
self . tapscript_satisfy_test ( CScript ( [ - 1 , OP_1 , OP_INSPECTINPUTVALUE , OP_FALSE , OP_EQUAL ] ) , fail = " Introspection index out of bounds " )
# Test current input
self . log . info ( " Instrospection tests: current input index " )
self . tapscript_satisfy_test ( CScript ( [ OP_PUSHCURRENTINPUTINDEX , OP_0 , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ OP_PUSHCURRENTINPUTINDEX , OP_1 , OP_EQUAL ] ) , fail = " Script evaluated without error but finished with a false/empty top stack element " )
# Test Outputs
self . log . info ( " Instrospection tests: outputs " )
for blind in [ True , False ] :
for out_pos in [ 0 , 1 ] :
self . tapscript_satisfy_test ( CScript ( [ out_pos , OP_INSPECTOUTPUTASSET , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , blind = blind , add_out_asset = out_pos )
self . tapscript_satisfy_test ( CScript ( [ out_pos , OP_INSPECTOUTPUTVALUE , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUAL ] ) , blind = blind , add_out_value = out_pos )
self . tapscript_satisfy_test ( CScript ( [ out_pos , OP_INSPECTOUTPUTNONCE , OP_EQUAL ] ) , blind = blind , add_out_nonce = out_pos )
self . tapscript_satisfy_test ( CScript ( [ out_pos , OP_INSPECTOUTPUTSCRIPTPUBKEY , OP_TOALTSTACK , OP_EQUALVERIFY , OP_FROMALTSTACK , OP_EQUALVERIFY , OP_1 ] ) , blind = blind , add_out_spk = out_pos )
# Test that output index out of bounds fail
self . tapscript_satisfy_test ( CScript ( [ 120 , OP_INSPECTOUTPUTASSET , OP_FALSE , OP_EQUAL ] ) , fail = " Introspection index out of bounds " )
self . tapscript_satisfy_test ( CScript ( [ - 1 , OP_INSPECTOUTPUTVALUE , OP_FALSE , OP_EQUAL ] ) , fail = " Introspection index out of bounds " )
# Finally, check the tx instrospection
self . log . info ( " Instrospection tests: tx " )
# Test version equality
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTVERSION , int ( 2 ) . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , ver = 2 )
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTVERSION , int ( 5 ) . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , ver = 2 , fail = " Script evaluated without error but finished with a false/empty top stack element " )
# Test nlocktime
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTLOCKTIME , int ( 7 ) . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , locktime = 7 )
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTLOCKTIME , int ( 7 ) . to_bytes ( 4 , ' little ' ) , OP_EQUAL ] ) , locktime = 10 , fail = " Script evaluated without error but finished with a false/empty top stack element " )
# Test num_inputs
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTNUMINPUTS , OP_1 , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTNUMINPUTS , OP_2 , OP_EQUAL ] ) , fail = " Script evaluated without error but finished with a false/empty top stack element " )
# Test num_outputs
self . tapscript_satisfy_test ( CScript ( [ OP_INSPECTNUMOUTPUTS , OP_EQUAL ] ) , add_num_outputs = True )
2023-02-26 19:28:42 -08:00
# Test tx weight
2021-07-11 11:02:11 +00:00
self . tapscript_satisfy_test ( CScript ( [ OP_TXWEIGHT , OP_EQUAL ] ) , add_weight = True )
2021-06-25 05:53:51 +00:00
2021-08-25 20:47:13 +00:00
# short handle to convert int to 8 byte LE
def le8 ( x , signed = True ) :
return int ( x ) . to_bytes ( 8 , ' little ' , signed = signed )
def check_add ( a , b , c , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_ADD64 , OP_VERIFY , le8 ( c ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_sub ( a , b , c , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_SUB64 , OP_VERIFY , le8 ( c ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_mul ( a , b , c , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_MUL64 , OP_VERIFY , le8 ( c ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_div ( a , b , q , r , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_DIV64 , OP_VERIFY , le8 ( q ) , OP_EQUALVERIFY , le8 ( r ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_le ( a , b , res , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_LESSTHAN64 , res , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_leq ( a , b , res , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_LESSTHANOREQUAL64 , res , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_ge ( a , b , res , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_GREATERTHAN64 , res , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_geq ( a , b , res , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_GREATERTHANOREQUAL64 , res , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] , fail = fail )
2021-10-14 23:48:40 +00:00
2021-08-25 20:47:13 +00:00
def check_neg ( a , res , fail = None ) :
self . tapscript_satisfy_test ( CScript ( [ OP_NEG64 , OP_VERIFY , le8 ( res ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) ] , fail = fail )
# Arithematic opcodes
self . log . info ( " Check Arithmetic opcodes " )
check_add ( 5 , 5 , 10 )
check_add ( - 5 , - 5 , - 10 )
check_add ( - 5 , 5 , 0 )
check_add ( 14231 , - 123213 , 14231 - 123213 )
check_add ( 2 * * 63 - 1 , 5 , 4 , fail = " Script failed an OP_VERIFY operation " ) #overflow
check_add ( 5 , 2 * * 63 - 1 , 4 , fail = " Script failed an OP_VERIFY operation " ) #overflow
check_add ( - 5 , - 2 * * 63 + 1 , - 4 , fail = " Script failed an OP_VERIFY operation " ) #overflow
2021-10-14 21:48:49 +00:00
# Subtraction
2021-08-25 20:47:13 +00:00
check_sub ( 5 , 6 , - 1 )
check_sub ( - 5 , 6 , - 11 )
check_sub ( - 5 , - 5 , 0 )
check_sub ( 14231 , - 123213 , 14231 + 123213 )
check_sub ( 2 * * 63 - 1 , 4 , 2 * * 63 - 5 )
check_sub ( - 5 , 2 * * 63 - 1 , - 4 , fail = " Script failed an OP_VERIFY operation " ) #overflow
check_sub ( 2 * * 63 - 1 , - 4 , 5 , fail = " Script failed an OP_VERIFY operation " ) #overflow
# Multiplication
check_mul ( 5 , 6 , 30 )
check_mul ( - 5 , 6 , - 30 )
check_mul ( - 5 , 0 , 0 )
check_mul ( - 5 , - 6 , 30 )
check_mul ( 14231 , - 123213 , - 14231 * 123213 )
check_mul ( 2 * * 32 , 2 * * 31 - 1 , 2 * * 63 - 2 * * 32 )
check_mul ( 2 * * 32 , 2 * * 31 , 0 , fail = " Script failed an OP_VERIFY operation " ) #overflow
check_mul ( - 2 * * 32 , 2 * * 31 , - 2 * * 63 ) # no overflow
check_mul ( - 2 * * 32 , - 2 * * 32 , 0 , fail = " Script failed an OP_VERIFY operation " ) #overflow
# Division
check_div ( 5 , 6 , 0 , 5 )
check_div ( 4 , 2 , 2 , 0 )
check_div ( - 5 , 6 , - 1 , 1 ) # r must be in 0<=r<a
check_div ( 5 , - 6 , 0 , 5 ) # r must be in 0<=r<a
check_div ( - 5 , 0 , 0 , 0 , fail = " Script failed an OP_VERIFY operation " ) # only fails if b = 0
check_div ( - 2 * * 63 , - 1 , 0 , 0 , fail = " Script failed an OP_VERIFY operation " ) # failure on -2**63/-1
check_div ( 6213123213513 , 621 , 6213123213513 / / 621 , 6213123213513 % 621 )
check_div ( 2 * * 62 , 2 * * 31 , 2 * * 31 , 0 )
# Less than test
# Comparison tests
# Less than
check_le ( 5 , 6 , 1 )
check_le ( 5 , 5 , 0 )
check_le ( 6 , 5 , 0 )
# Less than equal
check_leq ( 5 , 6 , 1 )
check_leq ( 5 , 5 , 1 )
check_leq ( 6 , 5 , 0 )
# Greater than
check_ge ( 5 , 6 , 0 )
check_ge ( 5 , 5 , 0 )
check_ge ( 6 , 5 , 1 )
# Greater than equal
check_geq ( 5 , 6 , 0 )
check_geq ( 5 , 5 , 1 )
check_geq ( 6 , 5 , 1 )
# equal
check_neg ( 5 , - 5 )
check_neg ( - 5 , 5 )
check_neg ( 5 , 4 , fail = " Script evaluated without error but finished with a false/empty top stack element " )
check_neg ( - 2 * * 63 , 0 , fail = " Script failed an OP_VERIFY operation " )
check_neg ( 2 * * 63 - 1 , - 2 * * 63 + 1 )
# Test boolean operations
for _ in range ( 5 ) :
a = randint ( - 2 * * 63 , 2 * * 63 - 1 )
b = randint ( - 2 * * 63 , 2 * * 63 - 1 )
self . tapscript_satisfy_test ( CScript ( [ OP_AND , le8 ( a & b ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] )
self . tapscript_satisfy_test ( CScript ( [ OP_OR , le8 ( a | b ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] )
self . tapscript_satisfy_test ( CScript ( [ OP_INVERT , le8 ( ~ a ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) ] )
self . tapscript_satisfy_test ( CScript ( [ OP_XOR , le8 ( a ^ b ) , OP_EQUAL ] ) , inputs = [ le8 ( a ) , le8 ( b ) ] )
# Finally, test conversion opcodes
self . log . info ( " Check conversion opcodes " )
for n in [ - 2 * * 31 + 1 , - 1 , 0 , 1 , 2 * * 31 - 1 ] :
self . tapscript_satisfy_test ( CScript ( [ le8 ( n ) , OP_LE64TOSCRIPTNUM , n , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ n , OP_SCRIPTNUMTOLE64 , le8 ( n ) , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ n , OP_DUP , OP_SCRIPTNUMTOLE64 , OP_LE64TOSCRIPTNUM , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ le8 ( n ) , OP_DUP , OP_LE64TOSCRIPTNUM , OP_SCRIPTNUMTOLE64 , OP_EQUAL ] ) )
self . tapscript_satisfy_test ( CScript ( [ n . to_bytes ( 4 , ' little ' , signed = True ) , OP_LE32TOLE64 , le8 ( n ) , OP_EQUAL ] ) , fail = " Script evaluated without error but finished with a false/empty top stack element " if ( n < 0 ) else None )
# Non 8 byte inputs
self . tapscript_satisfy_test ( CScript ( [ OP_ADD64 , OP_VERIFY , le8 ( 9 ) , OP_EQUAL ] ) , inputs = [ le8 ( 0 ) , int ( 9 ) . to_bytes ( 7 , ' little ' ) ] , fail = " Arithmetic opcodes expect 8 bytes operands " )
# Overflow inputs
self . tapscript_satisfy_test ( CScript ( [ le8 ( 2 * * 31 ) , OP_LE64TOSCRIPTNUM , 2 * * 31 , OP_EQUAL ] ) , fail = " Arithmetic opcode error " )
2021-08-02 02:54:41 +00:00
self . log . info ( " Check Crypto opcodes " )
res = bytes . fromhex ( " 03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7 " )
scalar = bytes . fromhex ( " 000000000000000000000000000000000000000000000000000000000000000a " )
g = bytes . fromhex ( " 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " )
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ res , g , scalar ] )
res = bytes . fromhex ( " 032c0158d0f6df4881e99e65fbea21f27321d817f79ad39e08eaf4f16f1419bb0c " )
scalar = bytes . fromhex ( " e0f47c124f228b97bbdc0e4398aac9788869b9fbbc193d5323fdad9570609de6 " )
g = bytes . fromhex ( " 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " )
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ res , g , scalar ] )
# test that other random values fail correctly
res = bytes . fromhex ( " 032c0158d0f6df4881e99e65fbea21f27321d817f79ad39e08eaf4f16f1419bb0c " )
scalar = bytes . fromhex ( " e0f47c124f228b97bbdc0e4398aac9788869b9fbbc193d5323fdad9570609de6 " )
2021-10-14 21:48:49 +00:00
g = bytes . fromhex ( " 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " ) # y coordinate mutated
2021-08-02 02:54:41 +00:00
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ res , g , scalar ] , fail = " Public key is neither compressed or uncompressed " )
invalid_full_pks_33 = [
" 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81700 " # invalid point on curve
]
invalid_full_pks_non33 = [
" 0979be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " , # 33 byte without 0x02,0x03
" 0462b31419b87d5e095e9d7532f92aea39c39735253a48fbdaff48441d5cf706f9a7a946ce481411e4034143e0acad4e79aecb2a8212ee5cca26a7cc5fe5b45881 " , # compressed
" 62b31419b87d5e095e9d7532f92aea39c39735253a48fbdaff48441d5cf706f9 " , # x-only key
" 0262b31419b87d5e095e9d7532f92aea39c39735253a48fbdaff48441d5cf706f9f9f9 " # 34 byte key
]
invalid_tweaks = [
" e07c124f228b97bbdc0e4398aac9788869b9fbbc193d5323fdad9570609de6 " , # non 32 byte hash
" fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143 " # order + 2
]
invalid_xonly_keys = [
" 0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " , # 33 byte valid key
" 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81700 " , # invalid point on curve
" 0462b31419b87d5e095e9d7532f92aea39c39735253a48fbdaff48441d5cf706f9a7a946ce481411e4034143e0acad4e79aecb2a8212ee5cca26a7cc5fe5b45881 " , # compressed
" 62b31419b87d5e095e9d7532f92aea39c39735253a48fbdaff48441d5cf706 " # 31 byte x-only key
]
valid_res = bytes . fromhex ( " 032c0158d0f6df4881e99e65fbea21f27321d817f79ad39e08eaf4f16f1419bb0c " )
valid_scalar = bytes . fromhex ( " e0f47c124f228b97bbdc0e4398aac9788869b9fbbc193d5323fdad9570609de6 " )
valid_g = bytes . fromhex ( " 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " )
valid_xonly_key = bytes . fromhex ( " 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 " )
for invalid_tweak in invalid_tweaks :
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ valid_res , valid_g , bytes . fromhex ( invalid_tweak ) ] , fail = " EC scalar mult verify fail " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , bytes . fromhex ( invalid_tweaks [ 1 ] ) , valid_xonly_key ] , fail = " EC scalar mult verify fail " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , bytes . fromhex ( invalid_tweaks [ 0 ] ) , valid_xonly_key ] , fail = " Public key is neither compressed or uncompressed " )
for invalid_full_pk in invalid_full_pks_33 :
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ bytes . fromhex ( invalid_full_pk ) , valid_g , valid_scalar ] , fail = " EC scalar mult verify fail " )
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ valid_res , bytes . fromhex ( invalid_full_pk ) , valid_scalar ] , fail = " EC scalar mult verify fail " )
for invalid_full_pk in invalid_full_pks_non33 :
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ bytes . fromhex ( invalid_full_pk ) , valid_g , valid_scalar ] , fail = " Public key is neither compressed or uncompressed " )
self . tapscript_satisfy_test ( CScript ( [ OP_ECMULSCALARVERIFY , OP_1 ] ) , inputs = [ valid_res , bytes . fromhex ( invalid_full_pk ) , valid_scalar ] , fail = " Public key is neither compressed or uncompressed " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , valid_scalar , bytes . fromhex ( invalid_xonly_keys [ 0 ] ) ] , fail = " Public key is neither compressed or uncompressed " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , valid_scalar , bytes . fromhex ( invalid_xonly_keys [ 1 ] ) ] , fail = " EC scalar mult verify fail " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , valid_scalar , bytes . fromhex ( invalid_xonly_keys [ 2 ] ) ] , fail = " Public key is neither compressed or uncompressed " )
self . tapscript_satisfy_test ( CScript ( [ OP_TWEAKVERIFY , OP_1 ] ) , inputs = [ valid_res , valid_scalar , bytes . fromhex ( invalid_xonly_keys [ 3 ] ) ] , fail = " Public key is neither compressed or uncompressed " )
# Checksigfromstack tests
# 32 byte msg
def csfs_test ( msg , mutute_sig = False , fail = None ) :
sec = generate_privkey ( )
msg = bytes . fromhex ( msg )
pub = compute_xonly_pubkey ( sec ) [ 0 ]
sig = sign_schnorr ( sec , msg )
if mutute_sig :
new_sig = sig [ : 63 ]
new_sig + = ( sig [ 63 ] ^ 0xff ) . to_bytes ( 1 , ' little ' ) # flip the last bit
sig = new_sig
self . tapscript_satisfy_test ( CScript ( [ msg , pub , OP_CHECKSIGFROMSTACK ] ) , inputs = [ sig ] , fail = fail )
csfs_test ( " e168c349d0d2499caf3a6d71734c743d517f94f8571fa52c04285b68deec1936 " )
csfs_test ( " Hello World! " . encode ( ' utf-8 ' ) . hex ( ) , fail = " Invalid Schnorr signature " , mutute_sig = True )
msg = bytes . fromhex ( " e168c349d0d2499caf3a6d71734c743d517f94f8571fa52c04285b68deec1936 " )
pub = bytes . fromhex ( " 3f67e97da0df6931189cfb0072447da22707897bd5de04936a277ed7e00b35b3 " )
self . tapscript_satisfy_test ( CScript ( [ OP_0 , msg , pub , OP_CHECKSIGFROMSTACK , OP_NOT ] ) , inputs = [ ] )
short_sig = bytes . fromhex ( " 0102 " )
self . tapscript_satisfy_test ( CScript ( [ short_sig , msg , pub , OP_CHECKSIGFROMSTACK , OP_NOT ] ) , inputs = [ ] , fail = " Invalid Schnorr signature size " )
short_pub = bytes . fromhex ( " 67e97da0df6931189cfb0072447da22707897bd5de04936a277ed7e00b35b3 " )
long_pub = bytes . fromhex ( " 67e97da0df6931189cfb0072447da22707897bd5de04936a277ed7e00b35b30908 " )
sig = bytes . fromhex ( " 3f67e97da0df6931189cfb0072447da22707897bd5de04936a277ed7e00b35b33f67e97da0df6931189cfb0072447da22707897bd5de04936a277ed7e00b35b3 " )
self . tapscript_satisfy_test ( CScript ( [ msg , short_pub , OP_CHECKSIGFROMSTACK ] ) , inputs = [ sig ] , fail = " Public key version reserved for soft-fork upgrades " )
self . tapscript_satisfy_test ( CScript ( [ msg , long_pub , OP_CHECKSIGFROMSTACK ] ) , inputs = [ sig ] , fail = " Public key version reserved for soft-fork upgrades " )
2021-06-25 05:53:51 +00:00
if __name__ == ' __main__ ' :
2021-09-05 12:35:58 +00:00
TapHashPeginTest ( ) . main ( )