def create_segwit_fund_and_spend_tx(spend, case0=False): if not case0: # Spending from a P2SH-P2WPKH coin, # txhash:a45698363249312f8d3d93676aa714be59b0bd758e62fa054fb1ea6218480691 redeem_script0 = bytearray.fromhex( '0014fcf9969ce1c98a135ed293719721fb69f0b686cb') # Spending from a P2SH-P2WSH coin, # txhash:6b536caf727ccd02c395a1d00b752098ec96e8ec46c96bee8582be6b5060fa2f redeem_script1 = bytearray.fromhex( '0020fc8b08ed636cb23afcb425ff260b3abd03380a2333b54cfa5d51ac52d803baf4' ) else: redeem_script0 = bytearray.fromhex('51020000') redeem_script1 = bytearray.fromhex('53020080') redeem_scripts = [redeem_script0, redeem_script1] # Fund transaction to segwit addresses txfund = CTransaction() txfund.vin = [CTxIn(COutPoint(spend.tx.sha256, spend.n))] amount = (50 * COIN - 1000) // len(redeem_scripts) for redeem_script in redeem_scripts: txfund.vout.append( CTxOut( amount, CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL]))) txfund.rehash() # Segwit spending transaction # We'll test if a node that checks for standardness accepts this # txn. It should fail exclusively because of the restriction in # the scriptSig (non clean stack..), so all other characteristcs # must pass standardness checks. For this reason, we create # standard P2SH outputs. txspend = CTransaction() for i in range(len(redeem_scripts)): txspend.vin.append( CTxIn(COutPoint(txfund.sha256, i), CScript([redeem_scripts[i]]))) txspend.vout = [ CTxOut( 50 * COIN - 2000, CScript( [OP_HASH160, hash160(CScript([OP_TRUE])), OP_EQUAL])) ] txspend.rehash() return txfund, txspend
def create_fund_and_spend_tx(dummy=OP_0, sigtype='ecdsa'): spendfrom = spendable_outputs.pop() script = CScript([OP_1, public_key, OP_1, OP_CHECKMULTISIG]) value = spendfrom.vout[0].nValue # Fund transaction txfund = create_transaction(spendfrom, 0, b'', value, script) txfund.rehash() fundings.append(txfund) # Spend transaction txspend = CTransaction() txspend.vout.append(CTxOut(value - 1000, CScript([OP_TRUE]))) txspend.vin.append(CTxIn(COutPoint(txfund.sha256, 0), b'')) # Sign the transaction sighashtype = SIGHASH_ALL | SIGHASH_FORKID hashbyte = bytes([sighashtype & 0xff]) sighash = SignatureHashForkId(script, txspend, 0, sighashtype, value) if sigtype == 'schnorr': txsig = schnorr.sign(privkeybytes, sighash) + hashbyte elif sigtype == 'ecdsa': txsig = private_key.sign(sighash) + hashbyte txspend.vin[0].scriptSig = CScript([dummy, txsig]) txspend.rehash() return txspend
def test_invalid_args(self, electrum_client): from test_framework.connectrum.exc import ElectrumErrorResponse error_code = "-32602" hash_param_methods = ("blockchain.scripthash.get_balance", "blockchain.scripthash.get_history", "blockchain.scripthash.listunspent") for method in hash_param_methods: assert_raises(ElectrumErrorResponse, electrum_client.call, method, "invalidhash") try: electrum_client.call(method, "invalidhash") except Exception as e: print("ERROR:" + str(e)) assert error_code in str(e) # invalid tx try: tx = CTransaction() tx.calc_sha256() tx.vin = [CTxIn(COutPoint(0xbeef, 1))] electrum_client.call("blockchain.transaction.broadcast", ToHex(tx)) except Exception as e: print("ERROR: " + str(e)) assert error_code in str(e)
def create_fund_and_spend_tx(): spendfrom = spendable_outputs.pop() script = CScript([OP_ADD]) value = spendfrom.vout[0].nValue # Fund transaction txfund = create_transaction(spendfrom, 0, b'', value, script) pad_tx(txfund) txfund.rehash() fundings.append(txfund) # Spend transaction txspend = CTransaction() txspend.vout.append(CTxOut(value - 1000, CScript([OP_TRUE]))) txspend.vin.append(CTxIn(COutPoint(txfund.sha256, 0), b'')) # Sign the transaction txspend.vin[0].scriptSig = CScript( b'\x01\x01\x51') # PUSH1(0x01) OP_1 pad_tx(txspend) txspend.rehash() return txspend
def minefunding2(n): """ Mine a block with a bunch of outputs that are very dense sigchecks when spent (2 sigchecks each); return the inputs that can be used to spend. """ cds_scriptpubkey = CScript([ cds_message, cds_pubkey, OP_3DUP, OP_CHECKDATASIGVERIFY, OP_CHECKDATASIGVERIFY ]) # The scriptsig is carefully padded to have size 26, which is the # shortest allowed for 2 sigchecks for mempool admission. # The resulting inputs have size 67 bytes, 33.5 bytes/sigcheck. cds_scriptsig = CScript([b'x' * 16, cds_signature]) assert_equal(len(cds_scriptsig), 26) logging.debug( "Gen {} with locking script {} unlocking script {} .".format( n, cds_scriptpubkey.hex(), cds_scriptsig.hex())) tx = self.spendable_outputs.popleft() usable_inputs = [] txes = [] for i in range(n): tx = create_transaction(tx, cds_scriptpubkey, bytes([OP_TRUE]) if i == 0 else b"") txes.append(tx) usable_inputs.append( CTxIn(COutPoint(tx.sha256, 1), cds_scriptsig)) newtip = self.build_block(tip, txes) self.pynode.send_blocks_and_test([newtip], node, timeout=10) return usable_inputs, newtip
def make_spend(sigcheckcount): # Add a funding tx to fundings, and return a tx spending that using # scriptsig. logging.debug("Gen tx with {} sigchecks.".format(sigcheckcount)) def get_script_with_sigcheck(count): return CScript([cds_message, cds_pubkey] + (count - 1) * [OP_3DUP, OP_CHECKDATASIGVERIFY] + [OP_CHECKDATASIG]) # get funds locked with OP_1 sourcetx = self.spendable_outputs.popleft() # make funding that forwards to scriptpubkey last_sigcheck_count = ((sigcheckcount - 1) % 30) + 1 fundtx = create_transaction( sourcetx, get_script_with_sigcheck(last_sigcheck_count)) fill_sigcheck_script = get_script_with_sigcheck(30) remaining_sigcheck = sigcheckcount while remaining_sigcheck > 30: fundtx.vout[0].nValue -= 1000 fundtx.vout.append(CTxOut(100, bytes(fill_sigcheck_script))) remaining_sigcheck -= 30 fundtx.rehash() fundings.append(fundtx) # make the spending scriptsig = CScript([cds_signature]) tx = CTransaction() tx.vin.append(CTxIn(COutPoint(fundtx.sha256, 1), scriptsig)) input_index = 2 remaining_sigcheck = sigcheckcount while remaining_sigcheck > 30: tx.vin.append( CTxIn(COutPoint(fundtx.sha256, input_index), scriptsig)) remaining_sigcheck -= 30 input_index += 1 tx.vout.append(CTxOut(0, CScript([OP_RETURN]))) pad_tx(tx) tx.rehash() return tx
def make_spend(scriptpubkey, scriptsig): # Add a funding tx to fundings, and return a tx spending that using # scriptsig. logging.debug( "Gen tx with locking script {} unlocking script {} .".format( scriptpubkey.hex(), scriptsig.hex())) # get funds locked with OP_1 sourcetx = self.spendable_outputs.popleft() # make funding that forwards to scriptpubkey fundtx = create_transaction(sourcetx, scriptpubkey) fundings.append(fundtx) # make the spending tx = CTransaction() tx.vin.append(CTxIn(COutPoint(fundtx.sha256, 1), scriptsig)) tx.vout.append(CTxOut(0, CScript([OP_RETURN]))) pad_tx(tx) tx.rehash() return tx
def create_transaction(spendfrom, custom_script, amount=None): # Fund and sign a transaction to a given output. # spendfrom should be a CTransaction with first output to OP_TRUE. # custom output will go on position 1, after position 0 which will be # OP_TRUE (so it can be reused). customout = CTxOut(0, bytes(custom_script)) # set output amount to required dust if not given customout.nValue = amount or (len(customout.serialize()) + 148) * 3 ctx = CTransaction() ctx.vin.append(CTxIn(COutPoint(spendfrom.sha256, 0), bytes([OP_TRUE]))) ctx.vout.append(CTxOut(0, bytes([OP_TRUE]))) ctx.vout.append(customout) pad_tx(ctx) fee = len(ctx.serialize()) ctx.vout[0].nValue = spendfrom.vout[0].nValue - customout.nValue - fee ctx.rehash() return ctx
def create_fund_and_spend_tx(): spend_from = spendable_outputs.pop() value = spend_from.vout[0].nValue # Reversed data data = bytes.fromhex('0123456789abcdef') rev_data = bytes(reversed(data)) # Lockscript: provide a bytestring that reverses to X script = CScript([OP_REVERSEBYTES, rev_data, OP_EQUAL]) # Fund transaction: REVERSEBYTES <reversed(x)> EQUAL tx_fund = create_tx_with_script(spend_from, 0, b'', value, script) tx_fund.rehash() # Spend transaction: <x> tx_spend = CTransaction() tx_spend.vout.append( CTxOut(value - 1000, CScript([b'x' * 100, OP_RETURN]))) tx_spend.vin.append(CTxIn(COutPoint(tx_fund.sha256, 0), b'')) tx_spend.vin[0].scriptSig = CScript([data]) tx_spend.rehash() return tx_spend, tx_fund
def run_test(self): logging.info("Initializing test directory "+self.options.tmpdir) node = self.nodes[0] self.bootstrap_p2p() tip = self.get_best_block(node) logging.info("Create some blocks with OP_1 coinbase for spending.") blocks = [] for _ in range(10): tip = self.build_block(tip) blocks.append(tip) self.p2p.send_blocks_and_test(blocks, node, success=True) spendable_outputs = [block.vtx[0] for block in blocks] logging.info("Mature the blocks and get out of IBD.") node.generate(100) tip = self.get_best_block(node) logging.info( "Set up spending transactions to test and mine the funding transactions.") # Generate a key pair privkeybytes = b"xyzxyzhh" * 4 private_key = CECKey() private_key.set_secretbytes(privkeybytes) # get uncompressed public key serialization public_key = private_key.get_pubkey() # Create funding/spending transaction pair spend_from = spendable_outputs.pop() value = spend_from.vout[0].nValue # Reversed data data = bytes.fromhex('0123456789abcdef') rev_data = bytes(reversed(data)) # Lockscript: provide a bytestring that reverses to X script = CScript([OP_REVERSEBYTES, rev_data, OP_EQUAL]) # Fund transaction: REVERSEBYTES <reversed(x)> EQUAL tx_reversebytes_fund = create_tx_with_script(spend_from, 0, b'', value, script) tx_reversebytes_fund.rehash() # Spend transaction: <x> tx_reversebytes_spend = CTransaction() tx_reversebytes_spend.vout.append(CTxOut(value - 1000, CScript([b'x' * 100, OP_RETURN]))) tx_reversebytes_spend.vin.append(CTxIn(COutPoint(tx_reversebytes_fund.sha256, 0), b'')) tx_reversebytes_spend.vin[0].scriptSig = CScript([data]) tx_reversebytes_spend.rehash() # Mine funding transaction into block. Pre-upgrade output scripts can have # OP_REVERSEBYTES and still be fully valid, but they cannot spend it. tip = self.build_block(tip, [tx_reversebytes_fund]) self.p2p.send_blocks_and_test([tip], node) logging.info( "Submitting a new OP_REVERSEBYTES tx via net, and mining it in a block") # Send OP_REVERSEBYTES tx self.p2p.send_txs_and_test([tx_reversebytes_spend], node) # Verify OP_REVERSEBYTES tx is in mempool waitFor(10, lambda: set(node.getrawmempool()) == {tx_reversebytes_spend.hash}) # Mine OP_REVERSEBYTES tx into block tip = self.build_block(tip, [tx_reversebytes_spend]) self.p2p.send_blocks_and_test([tip], node)