def create_and_mine_tx_from_txids(self, txids, success=True): tx = CTransaction() for i in txids: txtmp = CTransaction() txraw = self.nodes[0].getrawtransaction(i) f = BytesIO(hex_str_to_bytes(txraw)) txtmp.deserialize(f) for j in range(len(txtmp.vout)): tx.vin.append(CTxIn(COutPoint(int('0x' + i, 0), j))) tx.vout.append(CTxOut(0, CScript())) tx.rehash() signresults = self.nodes[0].signrawtransaction( bytes_to_hex_str(tx.serialize_without_witness()))['hex'] self.nodes[0].sendrawtransaction(signresults, True) self.nodes[0].generate(1) sync_blocks(self.nodes)
def test_basics(self, xt_node, test_node): self.log.info("bip64: basic checks") txid = xt_node.sendtoaddress(xt_node.getnewaddress(), 0.1) tx = FromHex(CTransaction(), xt_node.getrawtransaction(txid)) tx.rehash() new_outpoint = COutPoint(tx.sha256, 0) prev_outpoint = tx.vin[0].prevout # Test that the utxo doesn't exist in the chain. self.get_utxos([new_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('0', 2)) assert_equal(len(test_node.utxos.result), 0) # It does exist in the mempool. self.get_utxos([new_outpoint], checkmempool=True) assert_equal(test_node.utxos.bitmap[0], int('1', 2)) assert_equal(len(test_node.utxos.result), 1) magic_inmempool_height = 2147483647 assert_equal(test_node.utxos.result[0].height, magic_inmempool_height) # The prevout exists in the chain self.get_utxos([prev_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('1', 2)) # The prevout is spent in the mempool. self.get_utxos([prev_outpoint], checkmempool=True) assert_equal(test_node.utxos.bitmap[0], int('0', 2)) # Mine tx creating new_outpoint, now it should exist in the chain. xt_node.generate(1) self.get_utxos([new_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('1', 2)) assert_equal(test_node.utxos.result[0].height, xt_node.getblockcount()) # .. same result when including mempool self.get_utxos([new_outpoint], checkmempool=True) assert_equal(test_node.utxos.bitmap[0], int('1', 2)) # Check that we can fetch multiple outpoints self.get_utxos([new_outpoint, prev_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('01', 2)) self.get_utxos([prev_outpoint, new_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('10', 2)) self.get_utxos([new_outpoint, prev_outpoint, new_outpoint], checkmempool=False) assert_equal(test_node.utxos.bitmap[0], int('101', 2))
def send_funds_to_attacker(self, node, attacker, coinbase_tx): funding_amount = int(coinbase_tx.vout[0].nValue / self.nbDoubleSpends) funding_tx = CTransaction() funding_tx.vin.append( CTxIn(COutPoint(coinbase_tx.sha256, 0), b"", 0xffffffff)) scriptPubKey = CScript([ OP_DUP, OP_HASH160, hash160(attacker.pubkey), OP_EQUALVERIFY, OP_CHECKSIG ]) for i in range(self.nbDoubleSpends): funding_tx.vout.append(CTxOut(funding_amount, scriptPubKey)) funding_tx.rehash() funding_txid = node.sendrawtransaction(ToHex(funding_tx), False, True) assert_equal(node.getrawmempool(), [funding_txid]) return funding_tx
def new_transaction(utxokey, utxo, target_tx_size): ndx, tx_to_spend = utxo padding_size = target_tx_size while True: tx = CTransaction() tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, ndx), b'')) tx.vin[0].scriptSig = b'' tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2 * target_tx_size, SIMPLE_OUTPUT_SCRIPT)) tx.vout.append(CTxOut(1, CScript([OP_FALSE,OP_RETURN] + [bytes(1) * padding_size]))) sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, tx_to_spend.vout[0].nValue) sig = utxokey.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID])) tx.vin[0].scriptSig = CScript([sig]) tx.rehash() diff = target_tx_size - len(tx.serialize()) if diff == 0: return tx padding_size += diff
def create_and_mine_tx_from_txids(self, txids, success=True): tx = CTransaction() for txid in txids: txtmp = CTransaction() txraw = self.nodes[0].getrawtransaction(txid) f = BytesIO(hex_str_to_bytes(txraw)) txtmp.deserialize(f) for j in range(len(txtmp.vout)): tx.vin.append(CTxIn(COutPoint(int('0x' + txid, 0), j))) tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) tx.rehash() signresultfull = self.nodes[0].signrawtransaction( bytes_to_hex_str(tx.serialize_without_witness())) signresult = signresultfull['hex'] assert_equal(signresultfull['complete'], True) self.nodes[0].sendrawtransaction(signresult, True) self.nodes[0].generate(1) sync_blocks(self.nodes)
def spend_tx_to_data(tx_to_spend, key_for_tx_to_spend): "Create and send block with coinbase, returns conbase (tx, key) tuple" tx = CTransaction() tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, 0), b"", 0xffffffff)) amount = tx_to_spend.vout[0].nValue - 2000 tx.vout.append(CTxOut(amount, OP_TRUE_OP_RETURN_SCRIPT)) sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, tx_to_spend.vout[0].nValue) tx.vin[0].scriptSig = CScript([ key_for_tx_to_spend.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID])) ]) tx.rehash() return tx
def generate_transactons(self, prev_txs, unlocking_script, locking_script, fee=2000000, factor=10): generated_txs = [] for prev_tx in prev_txs: for n, vout in enumerate(prev_tx.vout): tx = CTransaction() out_val = vout.nValue - fee tx.vout.extend((CTxOut(out_val, locking_script), ) * factor) tx.vin.append( CTxIn(COutPoint(prev_tx.sha256, n), unlocking_script, 0xffffffff)) tx.calc_sha256() generated_txs.append(tx) return generated_txs
def create_tx(self, outpoints, noutput, feerate, make_long_eval_script=False): """creates p2pk transaction always using the same key (created in constructor), if make_long_eval_script is set we are prepending long evaluating script to the locking script """ pre_script = MemepoolAcceptingTransactionsDuringReorg.long_eval_script if make_long_eval_script else [] tx = CTransaction() total_input = 0 for parent_tx, n in outpoints: tx.vin.append( CTxIn(COutPoint(parent_tx.sha256, n), CScript([b"0" * 72]), 0xffffffff)) total_input += parent_tx.vout[n].nValue for _ in range(noutput): tx.vout.append( CTxOut(total_input // noutput, CScript(pre_script + [self.public_key, OP_CHECKSIG]))) tx.rehash() tx_size = len(tx.serialize()) fee_per_output = int(tx_size * feerate // noutput) for output in tx.vout: output.nValue -= fee_per_output for input, (parent_tx, n) in zip(tx.vin, outpoints): sighash = SignatureHashForkId(parent_tx.vout[n].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, parent_tx.vout[n].nValue) input.scriptSig = CScript([ self.private_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID])) ]) tx.rehash() return tx
def create_tx(self, outpoints, noutput, feerate): tx = CTransaction() total_input = 0 for parent_tx, n in outpoints: tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, n), b"", 0xffffffff)) total_input += parent_tx.vout[n].nValue for _ in range(noutput): tx.vout.append(CTxOut(total_input//noutput, CScript([b"X"*200, OP_DROP, OP_TRUE]))) tx.rehash() tx_size = len(tx.serialize()) fee_per_output = int(tx_size * feerate // noutput) for output in tx.vout: output.nValue -= fee_per_output tx.rehash() return tx
def test_doublespend_chain(self): """Doublespend of a long chain""" initial_n_value = 5000 * COIN tx0_outpoint = make_utxo(self.nodes[0], initial_n_value) prevout = tx0_outpoint remaining_value = initial_n_value chain_txids = [] while remaining_value > 1000 * COIN: remaining_value -= 100 * COIN tx = CTransaction() tx.vin = [CTxIn(prevout, n_sequence=0)] tx.vout = [CTxOut(remaining_value, CScript([1]))] tx_hex = tx_to_hex(tx) txid = self.nodes[0].sendrawtransaction(tx_hex, True) chain_txids.append(txid) prevout = COutPoint(int(txid, 16), 0) # Whether the double-spend is allowed is evaluated by including all # child fees - 40 ESS - so this attempt is rejected. dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, n_sequence=0)] dbl_tx.vout = [CTxOut(initial_n_value - 30 * COIN, CScript([1]))] dbl_tx_hex = tx_to_hex(dbl_tx) # This will raise an exception due to insufficient fee assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True) # Accepted with sufficient fee dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, n_sequence=0)] dbl_tx.vout = [CTxOut(1 * COIN, CScript([1]))] dbl_tx_hex = tx_to_hex(dbl_tx) self.nodes[0].sendrawtransaction(dbl_tx_hex, True) mempool = self.nodes[0].getrawmempool() for doublespent_txid in chain_txids: assert (doublespent_txid not in mempool)
def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(105) self.sync_all() chain_height = self.nodes[1].getblockcount() assert_equal(chain_height, 105) self.log.info("Testing transaction index...") #privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" #address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" address_hash = bytes([ 11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190, 49, 25, 70, 218, 220 ]) script_pub_key = CScript( [OP_DUP, OP_HASH160, address_hash, OP_EQUALVERIFY, OP_CHECKSIG]) unspent = self.nodes[0].listunspent() tx = CTransaction() amount = int(unspent[0]["amount"] * 10000000) tx.vin = [ CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"])) ] tx.vout = [CTxOut(amount, script_pub_key)] tx.rehash() signed_tx = self.nodes[0].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) self.nodes[0].sendrawtransaction(signed_tx["hex"], True) self.nodes[0].generate(1) self.sync_all() # Check verbose raw transaction results verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1) assert_equal(verbose["vout"][0]["valueSat"], 500000000000) assert_equal(verbose["vout"][0]["value"], 5000) self.log.info("All Tests Passed")
def branch(prevout, initial_value, max_txs, tree_width=5, fee_val=0.0001 * COIN, _total_txs=None): if _total_txs is None: _total_txs = [0] if _total_txs[0] >= max_txs: return txout_value = (initial_value - fee_val) // tree_width if txout_value < fee_val: return vout = [ CTxOut(txout_value, CScript([i + 1])) for i in range(tree_width) ] tx_data = CTransaction() tx_data.vin = [CTxIn(prevout, n_sequence=0)] tx_data.vout = vout tx_hex = tx_to_hex(tx_data) assert (len(tx_data.serialize()) < 100000) txid = self.nodes[0].sendrawtransaction(tx_hex, True) yield tx_data _total_txs[0] += 1 txid = int(txid, 16) for i, _ in enumerate(tx_data.vout): for x in branch(COutPoint(txid, i), txout_value, max_txs, tree_width=tree_width, fee_val=fee_val, _total_txs=_total_txs): yield x
def make_utxos(self): # Doesn't matter which node we use, just use node0. block = self.build_block_on_tip(self.nodes[0]) self.test_node.send_and_ping(MsgBlock(block)) assert (int(self.nodes[0].getbestblockhash(), 16) == block.sha256) self.nodes[0].generate(100) total_value = block.vtx[0].vout[0].nValue out_value = total_value // 10 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b'')) for _ in range(10): tx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) tx.rehash() block2 = self.build_block_on_tip(self.nodes[0]) block2.vtx.append(tx) block2.hashMerkleRoot = block2.calc_merkle_root() block2.solve() self.test_node.send_and_ping(MsgBlock(block2)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), block2.sha256) self.utxos.extend([[tx.x16r, i, out_value] for i in range(10)]) return
def prepare_for_test(self, height, label, coinbases, connections): transactions = [] n_generated_utxos = 0 while n_generated_utxos < self._NUMBER_OF_UTXOS_PER_HEIGHT: tx_to_spend = coinbases() tx = CTransaction() transactions.append(tx) tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, 0), b'')) locking_key = self._UTXO_KEY cscript = CScript([locking_key.get_pubkey(), OP_CHECKSIG ]) if locking_key else CScript([OP_TRUE]) for x in range(24): coinbaseoutput = CTxOut(2 * COIN, cscript) tx.vout.append(coinbaseoutput) n_generated_utxos += 1 if self.COINBASE_KEY: tx.rehash() sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, tx_to_spend.vout[0].nValue) sig = self._coinbase_key.sign(sighash) + bytes( bytearray([SIGHASH_ALL | SIGHASH_FORKID])) tx.vin[0].scriptSig = CScript([sig]) else: tx.vin[0].scriptSig = CScript([OP_TRUE]) tx.rehash() self.log.info( f"Created UTXO Tx {loghash(tx.hash)} with {n_generated_utxos} outputs" ) return transactions, None
def split_inputs(from_node, txins, txouts, initial_split=False): # ZEN_MOD_START """ We need to generate a lot of inputs so we can generate a ton of transactions. This function takes an input from txins, and creates and sends a transaction which splits the value into 2 outputs which are appended to txouts. Previously this was designed to be small inputs so they wouldn't have a high coin age when the notion of priority still existed. """ # ZEN_MOD_END prevtxout = txins.pop() # ZEN_MOD_START tx = CTransaction() tx.vin.append( CTxIn(COutPoint(int(prevtxout["txid"], 16), prevtxout["vout"]), b"")) # ZEN_MOD_END half_change = satoshi_round(prevtxout["amount"] / 2) rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000") # ZEN_MOD_START tx.vout.append(CTxOut(int(half_change * COIN), P2SH_1)) tx.vout.append(CTxOut(int(rem_change * COIN), P2SH_2)) # If this is the initial split we actually need to sign the transaction # Otherwise we just need to insert the proper ScriptSig if (initial_split): completetx = from_node.signrawtransaction(ToHex(tx))["hex"] else: tx.vin[0].scriptSig = SCRIPT_SIG[prevtxout["vout"]] completetx = ToHex(tx) # ZEN_MOD_END txid = from_node.sendrawtransaction(completetx, True) txouts.append({"txid": txid, "vout": 0, "amount": half_change}) txouts.append({"txid": txid, "vout": 1, "amount": rem_change})
def spend_separator_tx(tx_sep_tx, keys_for_sep_tx): """spends Transaction with scriptPubKey in form of: <pk1> OP_CHECKSIGVERIFY OP_CODESEPARATOR <pk2> OP_CHECKSIGVERIFY OP_CODESEPARATOR ... <pk N_signings> OP_CHECKSIG """ tx = CTransaction() tx.vin.append(CTxIn(COutPoint(tx_sep_tx.sha256, 0), b"", 0xffffffff)) k = CECKey() k.set_secretbytes(b"horsebattery") amount = tx_sep_tx.vout[0].nValue - 2000 script_lists = [[]] for item in list(tx_sep_tx.vout[0].scriptPubKey): for l in script_lists: l.append(item) if item == OP_CODESEPARATOR: script_lists.append([]) tx.vout.append(CTxOut(amount, CScript([k.get_pubkey(), OP_CHECKSIG]))) flags = bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID])) sign_list = [] for sc, key in zip(script_lists, keys_for_sep_tx): sighash = SignatureHashForkId(CScript(sc), tx, 0, SIGHASH_ALL | SIGHASH_FORKID, tx_sep_tx.vout[0].nValue) sign_list.append(key.sign(sighash) + flags) tx.vin[0].scriptSig = CScript(reversed(sign_list)) tx.rehash() return tx, k
def next_block(self, number, spend=None, additional_coinbase_value=0, script=None): if self.tip == None: base_block_hash = self.genesis_hash else: base_block_hash = self.tip.sha256 # First create the coinbase height = self.block_heights[base_block_hash] + 1 coinbase = create_coinbase(height, self.coinbase_pubkey) coinbase.vout[0].nValue += additional_coinbase_value if (spend != None): coinbase.vout[0].nValue += spend.tx.vout[ spend.n].nValue - 1 # all but one satoshi to fees coinbase.rehash() block = create_block(base_block_hash, coinbase, self.block_time) if (spend != None): tx = CTransaction() tx.vin.append( CTxIn(COutPoint(spend.tx.sha256, spend.n), "", 0xffffffff)) # no signature yet # This copies the java comparison tool testing behavior: the first # txout has a garbage scriptPubKey, "to make sure we're not # pre-verifying too much" (?) tx.vout.append( CTxOut(0, CScript([random.randint(0, 255), height & 255]))) if script == None: tx.vout.append(CTxOut(1, CScript([OP_TRUE]))) else: tx.vout.append(CTxOut(1, script)) # Now sign it if necessary scriptSig = "" scriptPubKey = bytearray(spend.tx.vout[spend.n].scriptPubKey) if (scriptPubKey[0] == OP_TRUE): # looks like an anyone-can-spend scriptSig = CScript([OP_TRUE]) else: # We have to actually sign it (sighash, err) = SignatureHash( spend.tx.vout[spend.n].scriptPubKey, tx, 0, SIGHASH_ALL, spend.tx.vout[spend.n].nValue, SAPLING_BRANCH_ID, ) scriptSig = CScript([ self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL])) ]) tx.vin[0].scriptSig = scriptSig # Now add the transaction to the block block = self.add_transactions_to_block(block, [tx]) block.solve() self.tip = block self.block_heights[block.sha256] = height self.block_time += 1 assert number not in self.blocks self.blocks[number] = block return block
def run_test(self): # helper functions def getaddresstxids(node_index, addresses, start, end): return self.nodes[node_index].getaddresstxids({ 'addresses': addresses, 'start': start, 'end': end }) def getaddressdeltas(node_index, addresses, start, end, chainInfo=None): params = { 'addresses': addresses, 'start': start, 'end': end, } if chainInfo is not None: params.update({'chainInfo': chainInfo}) return self.nodes[node_index].getaddressdeltas(params) # default received value is the balance value def check_balance(node_index, address, expected_balance, expected_received=None): if isinstance(address, list): bal = self.nodes[node_index].getaddressbalance( {'addresses': address}) else: bal = self.nodes[node_index].getaddressbalance(address) assert_equal(bal['balance'], expected_balance) if expected_received is None: expected_received = expected_balance assert_equal(bal['received'], expected_received) # begin test self.nodes[0].generate(105) self.sync_all() assert_equal(self.nodes[0].getbalance(), 5 * 10) assert_equal(self.nodes[1].getblockcount(), 105) assert_equal(self.nodes[1].getbalance(), 0) # only the oldest 5; subsequent are not yet mature unspent_txids = [u['txid'] for u in self.nodes[0].listunspent()] # Currently our only unspents are coinbase transactions, choose any one tx = self.nodes[0].getrawtransaction(unspent_txids[0], 1) # It just so happens that the first output is the mining reward, # which has type pay-to-public-key-hash, and the second output # is the founders' reward, which has type pay-to-script-hash. addr_p2pkh = tx['vout'][0]['scriptPubKey']['addresses'][0] addr_p2sh = tx['vout'][1]['scriptPubKey']['addresses'][0] # Check that balances from mining are correct (105 blocks mined); in # regtest, all mining rewards from a single call to generate() are sent # to the same pair of addresses. check_balance(1, addr_p2pkh, 105 * 10 * COIN) check_balance(1, addr_p2sh, 105 * 2.5 * COIN) # Multiple address arguments, results are the sum check_balance(1, [addr_p2sh, addr_p2pkh], 105 * 12.5 * COIN) assert_equal(len(self.nodes[1].getaddresstxids(addr_p2pkh)), 105) assert_equal(len(self.nodes[1].getaddresstxids(addr_p2sh)), 105) # test getaddresstxids for lightwalletd assert_equal(len(self.nodes[3].getaddresstxids(addr_p2pkh)), 105) assert_equal(len(self.nodes[3].getaddresstxids(addr_p2sh)), 105) # only the oldest 5 transactions are in the unspent list, # dup addresses are ignored height_txids = getaddresstxids(1, [addr_p2pkh, addr_p2pkh], 1, 5) assert_equal(sorted(height_txids), sorted(unspent_txids)) height_txids = getaddresstxids(1, [addr_p2sh], 1, 5) assert_equal(sorted(height_txids), sorted(unspent_txids)) # each txid should appear only once height_txids = getaddresstxids(1, [addr_p2pkh, addr_p2sh], 1, 5) assert_equal(sorted(height_txids), sorted(unspent_txids)) # do some transfers, make sure balances are good txids_a1 = [] addr1 = self.nodes[1].getnewaddress() expected = 0 expected_deltas = [] # for checking getaddressdeltas (below) for i in range(5): # first transaction happens at height 105, mined in block 106 txid = self.nodes[0].sendtoaddress(addr1, i + 1) txids_a1.append(txid) self.nodes[0].generate(1) self.sync_all() expected += i + 1 expected_deltas.append({ 'height': 106 + i, 'satoshis': (i + 1) * COIN, 'txid': txid, }) check_balance(1, addr1, expected * COIN) assert_equal(sorted(self.nodes[0].getaddresstxids(addr1)), sorted(txids_a1)) assert_equal(sorted(self.nodes[1].getaddresstxids(addr1)), sorted(txids_a1)) # Restart all nodes to ensure indices are saved to disk and recovered stop_nodes(self.nodes) wait_bitcoinds() self.setup_network() bal = self.nodes[1].getaddressbalance(addr1) assert_equal(bal['balance'], expected * COIN) assert_equal(bal['received'], expected * COIN) assert_equal(sorted(self.nodes[0].getaddresstxids(addr1)), sorted(txids_a1)) assert_equal(sorted(self.nodes[1].getaddresstxids(addr1)), sorted(txids_a1)) # Send 3 from addr1, but -- subtlety alert! -- addr1 at this # time has 4 UTXOs, with values 1, 2, 3, 4. Sending value 3 requires # using up the value 4 UTXO, because of the tx fee # (the 3 UTXO isn't quite large enough). # # The txid from sending *from* addr1 is also added to the list of # txids associated with that address (test will verify below). addr2 = self.nodes[2].getnewaddress() txid = self.nodes[1].sendtoaddress(addr2, 3) self.sync_all() # the one tx in the mempool refers to addresses addr1 and addr2, # check that duplicate addresses are processed correctly mempool = self.nodes[0].getaddressmempool( {'addresses': [addr2, addr1, addr2]}) assert_equal(len(mempool), 3) # test getaddressmempool for lightwalletd node mempool = self.nodes[3].getaddressmempool( {'addresses': [addr2, addr1, addr2]}) assert_equal(len(mempool), 3) # addr2 (first arg) assert_equal(mempool[0]['address'], addr2) assert_equal(mempool[0]['satoshis'], 3 * COIN) assert_equal(mempool[0]['txid'], txid) # addr1 (second arg) assert_equal(mempool[1]['address'], addr1) assert_equal(mempool[1]['satoshis'], (-4) * COIN) assert_equal(mempool[1]['txid'], txid) # addr2 (third arg) assert_equal(mempool[2]['address'], addr2) assert_equal(mempool[2]['satoshis'], 3 * COIN) assert_equal(mempool[2]['txid'], txid) # a single address can be specified as a string (not json object) addr1_mempool = self.nodes[0].getaddressmempool(addr1) assert_equal(len(addr1_mempool), 1) # Don't check the timestamp; it's local to the node, and can mismatch # due to propagation delay. del addr1_mempool[0]['timestamp'] for key in addr1_mempool[0].keys(): assert_equal(mempool[1][key], addr1_mempool[0][key]) tx = self.nodes[0].getrawtransaction(txid, 1) assert_equal(tx['vin'][0]['address'], addr1) assert_equal(tx['vin'][0]['value'], 4) assert_equal(tx['vin'][0]['valueSat'], 4 * COIN) txids_a1.append(txid) expected_deltas.append({ 'height': 111, 'satoshis': (-4) * COIN, 'txid': txid, }) self.sync_all() # ensure transaction is included in the next block self.nodes[0].generate(1) self.sync_all() # the send to addr2 tx is now in a mined block, no longer in the mempool mempool = self.nodes[0].getaddressmempool( {'addresses': [addr2, addr1]}) assert_equal(len(mempool), 0) # Test DisconnectBlock() by invalidating the most recent mined block tip = self.nodes[1].getchaintips()[0] for i in range(self.num_nodes): node = self.nodes[i] # the value 4 UTXO is no longer in our balance check_balance(i, addr1, (expected - 4) * COIN, expected * COIN) check_balance(i, addr2, 3 * COIN) assert_equal(node.getblockcount(), 111) node.invalidateblock(tip['hash']) assert_equal(node.getblockcount(), 110) mempool = node.getaddressmempool({'addresses': [addr2, addr1]}) assert_equal(len(mempool), 2) check_balance(i, addr1, expected * COIN) check_balance(i, addr2, 0) # now re-mine the addr1 to addr2 send self.nodes[0].generate(1) self.sync_all() for node in self.nodes: assert_equal(node.getblockcount(), 111) mempool = self.nodes[0].getaddressmempool( {'addresses': [addr2, addr1]}) assert_equal(len(mempool), 0) # the value 4 UTXO is no longer in our balance check_balance(2, addr1, (expected - 4) * COIN, expected * COIN) # Ensure the change from that transaction appears tx = self.nodes[0].getrawtransaction(txid, 1) change_vout = list( filter(lambda v: v['valueZat'] != 3 * COIN, tx['vout'])) change = change_vout[0]['scriptPubKey']['addresses'][0] # test getaddressbalance for node in (2, 3): bal = self.nodes[node].getaddressbalance(change) assert (bal['received'] > 0) # the inequality is due to randomness in the tx fee assert (bal['received'] < (4 - 3) * COIN) assert_equal(bal['received'], bal['balance']) assert_equal(self.nodes[2].getaddresstxids(change), [txid]) # Further checks that limiting by height works # various ranges for i in range(5): height_txids = getaddresstxids(1, [addr1], 106, 106 + i) assert_equal(height_txids, txids_a1[0:i + 1]) height_txids = getaddresstxids(1, [addr1], 1, 108) assert_equal(height_txids, txids_a1[0:3]) # Further check specifying multiple addresses txids_all = list(txids_a1) txids_all += self.nodes[1].getaddresstxids(addr_p2pkh) txids_all += self.nodes[1].getaddresstxids(addr_p2sh) multitxids = self.nodes[1].getaddresstxids( {'addresses': [addr1, addr_p2sh, addr_p2pkh]}) # No dups in return list from getaddresstxids assert_equal(len(multitxids), len(set(multitxids))) # set(txids_all) removes its (expected) duplicates assert_equal(set(multitxids), set(txids_all)) # test getaddressdeltas for node in (1, 3): deltas = self.nodes[node].getaddressdeltas({'addresses': [addr1]}) assert_equal(len(deltas), len(expected_deltas)) for i in range(len(deltas)): assert_equal(deltas[i]['address'], addr1) assert_equal(deltas[i]['height'], expected_deltas[i]['height']) assert_equal(deltas[i]['satoshis'], expected_deltas[i]['satoshis']) assert_equal(deltas[i]['txid'], expected_deltas[i]['txid']) # 106-111 is the full range (also the default) deltas_limited = getaddressdeltas(1, [addr1], 106, 111) assert_equal(deltas_limited, deltas) # only the first element missing deltas_limited = getaddressdeltas(1, [addr1], 107, 111) assert_equal(deltas_limited, deltas[1:]) deltas_limited = getaddressdeltas(1, [addr1], 109, 109) assert_equal(deltas_limited, deltas[3:4]) # the full range (also the default) deltas_info = getaddressdeltas(1, [addr1], 106, 111, chainInfo=True) assert_equal(deltas_info['deltas'], deltas) # check the additional items returned by chainInfo assert_equal(deltas_info['start']['height'], 106) block_hash = self.nodes[1].getblockhash(106) assert_equal(deltas_info['start']['hash'], block_hash) assert_equal(deltas_info['end']['height'], 111) block_hash = self.nodes[1].getblockhash(111) assert_equal(deltas_info['end']['hash'], block_hash) # Test getaddressutxos by comparing results with deltas utxos = self.nodes[3].getaddressutxos(addr1) # The value 4 note was spent, so won't show up in the utxo list, # so for comparison, remove the 4 (and -4 for output) from the # deltas list deltas = self.nodes[1].getaddressdeltas({'addresses': [addr1]}) deltas = list(filter(lambda d: abs(d['satoshis']) != 4 * COIN, deltas)) assert_equal(len(utxos), len(deltas)) for i in range(len(utxos)): assert_equal(utxos[i]['address'], addr1) assert_equal(utxos[i]['height'], deltas[i]['height']) assert_equal(utxos[i]['satoshis'], deltas[i]['satoshis']) assert_equal(utxos[i]['txid'], deltas[i]['txid']) # Check that outputs with the same address in the same tx return one txid # (can't use createrawtransaction() as it combines duplicate addresses) addr = "t2LMJ6Arw9UWBMWvfUr2QLHM4Xd9w53FftS" addressHash = unhexlify("97643ce74b188f4fb6bbbb285e067a969041caf2") scriptPubKey = CScript([OP_HASH160, addressHash, OP_EQUAL]) # Add an unrecognized script type to vout[], a legal script that pays, # but won't modify the addressindex (since the address can't be extracted). # (This extra output has no effect on the rest of the test.) scriptUnknown = CScript( [OP_HASH160, OP_DUP, OP_DROP, addressHash, OP_EQUAL]) unspent = list( filter(lambda u: u['amount'] >= 4, self.nodes[0].listunspent())) tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(unspent[0]['txid'], 16), unspent[0]['vout'])) ] tx.vout = [ CTxOut(1 * COIN, scriptPubKey), CTxOut(2 * COIN, scriptPubKey), CTxOut(7 * COIN, scriptUnknown), ] tx = self.nodes[0].signrawtransaction( hexlify(tx.serialize()).decode('utf-8')) txid = self.nodes[0].sendrawtransaction(tx['hex'], True) self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[1].getaddresstxids(addr), [txid]) check_balance(2, addr, 3 * COIN)
def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(105) self.sync_all() chain_height = self.nodes[1].getblockcount() assert_equal(chain_height, 105) assert_equal(self.nodes[1].getbalance(), 0) assert_equal(self.nodes[2].getbalance(), 0) # Check that balances are correct balance0 = self.nodes[1].getaddressbalance( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") assert_equal(balance0["balance"], 0) # Check p2pkh and p2sh address indexes self.log.info("Testing p2pkh and p2sh address index...") tx_id0 = self.nodes[0].sendtoaddress( "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 10) self.nodes[0].generate(1) tx_idb0 = self.nodes[0].sendtoaddress( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 10) self.nodes[0].generate(1) tx_id1 = self.nodes[0].sendtoaddress( "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 15) self.nodes[0].generate(1) tx_idb1 = self.nodes[0].sendtoaddress( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 15) self.nodes[0].generate(1) tx_id2 = self.nodes[0].sendtoaddress( "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 20) self.nodes[0].generate(1) tx_idb2 = self.nodes[0].sendtoaddress( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 20) self.nodes[0].generate(1) self.sync_all() txids = self.nodes[1].getaddresstxids( "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs") assert_equal(len(txids), 3) assert_equal(txids[0], tx_id0) assert_equal(txids[1], tx_id1) assert_equal(txids[2], tx_id2) tx_idsb = self.nodes[1].getaddresstxids( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") assert_equal(len(tx_idsb), 3) assert_equal(tx_idsb[0], tx_idb0) assert_equal(tx_idsb[1], tx_idb1) assert_equal(tx_idsb[2], tx_idb2) # Check that limiting by height works self.log.info("Testing querying txids by range of block heights..") height_txids = self.nodes[1].getaddresstxids({ "addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br"], "start": 105, "end": 110 }) assert_equal(len(height_txids), 2) assert_equal(height_txids[0], tx_idb0) assert_equal(height_txids[1], tx_idb1) # Check that multiple addresses works multi_tx_ids = self.nodes[1].getaddresstxids({ "addresses": [ "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs" ] }) assert_equal(len(multi_tx_ids), 6) assert_equal(multi_tx_ids[0], tx_id0) assert_equal(multi_tx_ids[1], tx_idb0) assert_equal(multi_tx_ids[2], tx_id1) assert_equal(multi_tx_ids[3], tx_idb1) assert_equal(multi_tx_ids[4], tx_id2) assert_equal(multi_tx_ids[5], tx_idb2) # Check that balances are correct balance0 = self.nodes[1].getaddressbalance( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") assert_equal(balance0["balance"], 45 * 100000000) # Check that outputs with the same address will only return one txid self.log.info("Testing for txid uniqueness...") address_hash = bytes([ 99, 73, 164, 24, 252, 69, 120, 209, 10, 55, 43, 84, 180, 92, 40, 12, 200, 196, 56, 47 ]) script_pub_key = CScript([OP_HASH160, address_hash, OP_EQUAL]) unspent = self.nodes[0].listunspent() tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"])) ] tx.vout = [CTxOut(10, script_pub_key), CTxOut(11, script_pub_key)] tx.rehash() signed_tx = self.nodes[0].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) self.nodes[0].generate(1) self.sync_all() tx_ids_many = self.nodes[1].getaddresstxids( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") assert_equal(len(tx_ids_many), 4) assert_equal(tx_ids_many[3], sent_txid) # Check that balances are correct self.log.info("Testing balances...") balance0 = self.nodes[1].getaddressbalance( "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") assert_equal(balance0["balance"], 45 * 100000000 + 21) # Check that balances are correct after spending self.log.info("Testing balances after spending...") privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" address_hash2 = bytes([ 11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190, 49, 25, 70, 218, 220 ]) script_pub_key2 = CScript( [OP_DUP, OP_HASH160, address_hash2, OP_EQUALVERIFY, OP_CHECKSIG]) self.nodes[0].importprivkey(privkey2) unspent = self.nodes[0].listunspent() tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"])) ] amount = int(unspent[0]["amount"] * 100000000 - 230000) tx.vout = [CTxOut(amount, script_pub_key2)] signed_tx = self.nodes[0].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) spending_txid = self.nodes[0].sendrawtransaction( signed_tx["hex"], True) self.nodes[0].generate(1) self.sync_all() balance1 = self.nodes[1].getaddressbalance(address2) assert_equal(balance1["balance"], amount) tx = CTransaction() tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))] send_amount = 1 * 100000000 + 12840 change_amount = amount - send_amount - 230000 tx.vout = [ CTxOut(change_amount, script_pub_key2), CTxOut(send_amount, script_pub_key) ] tx.rehash() signed_tx = self.nodes[0].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) self.nodes[0].sendrawtransaction(signed_tx["hex"], True) self.nodes[0].generate(1) self.sync_all() balance2 = self.nodes[1].getaddressbalance(address2) assert_equal(balance2["balance"], change_amount) # Check that deltas are returned correctly deltas = self.nodes[1].getaddressdeltas({ "addresses": [address2], "start": 1, "end": 200 }) balance3 = 0 for delta in deltas: balance3 += delta["satoshis"] assert_equal(balance3, change_amount) assert_equal(deltas[0]["address"], address2) assert_equal(deltas[0]["blockindex"], 1) # Check that entire range will be queried deltas_all = self.nodes[1].getaddressdeltas({"addresses": [address2]}) assert_equal(len(deltas_all), len(deltas)) # Check that deltas can be returned from range of block heights deltas = self.nodes[1].getaddressdeltas({ "addresses": [address2], "start": 113, "end": 113 }) assert_equal(len(deltas), 1) # Check that unspent outputs can be queried self.log.info("Testing utxos...") utxos = self.nodes[1].getaddressutxos({"addresses": [address2]}) assert_equal(len(utxos), 1) assert_equal(utxos[0]["satoshis"], change_amount) # Check that indexes will be updated with a reorg self.log.info("Testing reorg...") best_hash = self.nodes[0].getbestblockhash() self.nodes[0].invalidateblock(best_hash) self.nodes[1].invalidateblock(best_hash) self.nodes[2].invalidateblock(best_hash) self.nodes[3].invalidateblock(best_hash) self.sync_all() balance4 = self.nodes[1].getaddressbalance(address2) assert_equal(balance4, balance1) utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]}) assert_equal(len(utxos2), 1) assert_equal(utxos2[0]["satoshis"], amount) # Check sorting of utxos self.nodes[2].generate(150) self.nodes[2].sendtoaddress(address2, 50) self.nodes[2].generate(1) self.nodes[2].sendtoaddress(address2, 50) self.nodes[2].generate(1) self.sync_all() utxos3 = self.nodes[1].getaddressutxos({"addresses": [address2]}) assert_equal(len(utxos3), 3) assert_equal(utxos3[0]["height"], 114) assert_equal(utxos3[1]["height"], 264) assert_equal(utxos3[2]["height"], 265) # Check mempool indexing self.log.info("Testing mempool indexing...") priv_key3 = "cVfUn53hAbRrDEuMexyfgDpZPhF7KqXpS8UZevsyTDaugB7HZ3CD" address3 = "mw4ynwhS7MmrQ27hr82kgqu7zryNDK26JB" address_hash3 = bytes([ 170, 152, 114, 181, 187, 205, 181, 17, 216, 158, 14, 17, 170, 39, 218, 115, 253, 44, 63, 80 ]) script_pub_key3 = CScript( [OP_DUP, OP_HASH160, address_hash3, OP_EQUALVERIFY, OP_CHECKSIG]) #address4 = "2N8oFVB2vThAKury4vnLquW2zVjsYjjAkYQ" script_pub_key4 = CScript([OP_HASH160, address_hash3, OP_EQUAL]) unspent = self.nodes[2].listunspent() tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"])) ] amount = int(unspent[0]["amount"] * 100000000 - 230000) tx.vout = [CTxOut(amount, script_pub_key3)] tx.rehash() signed_tx = self.nodes[2].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) mem_txid1 = self.nodes[2].sendrawtransaction(signed_tx["hex"], True) time.sleep(2) tx2 = CTransaction() tx2.vin = [ CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"])) ] amount = int(unspent[1]["amount"] * 100000000 - 300000) tx2.vout = [ CTxOut(int(amount / 4), script_pub_key3), CTxOut(int(amount / 4), script_pub_key3), CTxOut(int(amount / 4), script_pub_key4), CTxOut(int(amount / 4), script_pub_key4) ] tx2.rehash() signed_tx2 = self.nodes[2].signrawtransaction( binascii.hexlify(tx2.serialize()).decode("utf-8")) mem_txid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True) time.sleep(2) mempool = self.nodes[2].getaddressmempool({"addresses": [address3]}) assert_equal(len(mempool), 3) assert_equal(mempool[0]["txid"], mem_txid1) assert_equal(mempool[0]["address"], address3) assert_equal(mempool[0]["index"], 0) assert_equal(mempool[1]["txid"], mem_txid2) assert_equal(mempool[1]["index"], 0) assert_equal(mempool[2]["txid"], mem_txid2) assert_equal(mempool[2]["index"], 1) self.nodes[2].generate(1) self.sync_all() mempool2 = self.nodes[2].getaddressmempool({"addresses": [address3]}) assert_equal(len(mempool2), 0) tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(mem_txid2, 16), 0)), CTxIn(COutPoint(int(mem_txid2, 16), 1)) ] tx.vout = [CTxOut(int(amount / 2 - 340000), script_pub_key2)] tx.rehash() self.nodes[2].importprivkey(priv_key3) signed_tx3 = self.nodes[2].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) self.nodes[2].sendrawtransaction(signed_tx3["hex"], True) time.sleep(2) mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]}) assert_equal(len(mempool3), 2) assert_equal(mempool3[0]["prevtxid"], mem_txid2) assert_equal(mempool3[0]["prevout"], 0) assert_equal(mempool3[1]["prevtxid"], mem_txid2) assert_equal(mempool3[1]["prevout"], 1) # sending and receiving to the same address privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8" address1 = "myAUWSHnwsQrhuMWv4Br6QsCnpB41vFwHn" address1hash = bytes([ 193, 146, 191, 247, 81, 175, 142, 254, 193, 81, 53, 212, 43, 254, 237, 249, 26, 111, 62, 52 ]) address1script = CScript( [OP_DUP, OP_HASH160, address1hash, OP_EQUALVERIFY, OP_CHECKSIG]) self.nodes[0].sendtoaddress(address1, 10) self.nodes[0].generate(1) self.sync_all() utxos = self.nodes[1].getaddressutxos({"addresses": [address1]}) assert_equal(len(utxos), 1) tx = CTransaction() tx.vin = [ CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["outputIndex"])) ] amount = int(utxos[0]["satoshis"] - 200000) tx.vout = [CTxOut(amount, address1script)] tx.rehash() self.nodes[0].importprivkey(privkey1) signed_tx = self.nodes[0].signrawtransaction( binascii.hexlify(tx.serialize()).decode("utf-8")) self.nodes[0].sendrawtransaction(signed_tx["hex"], True) self.sync_all() mempool_deltas = self.nodes[2].getaddressmempool( {"addresses": [address1]}) assert_equal(len(mempool_deltas), 2) # Include chaininfo in results self.log.info("Testing results with chain info...") deltas_with_info = self.nodes[1].getaddressdeltas({ "addresses": [address2], "start": 1, "end": 200, "chainInfo": True }) start_block_hash = self.nodes[1].getblockhash(1) end_block_hash = self.nodes[1].getblockhash(200) assert_equal(deltas_with_info["start"]["height"], 1) assert_equal(deltas_with_info["start"]["hash"], start_block_hash) assert_equal(deltas_with_info["end"]["height"], 200) assert_equal(deltas_with_info["end"]["hash"], end_block_hash) utxos_with_info = self.nodes[1].getaddressutxos({ "addresses": [address2], "chainInfo": True }) expected_tip_block_hash = self.nodes[1].getblockhash(267) assert_equal(utxos_with_info["height"], 267) assert_equal(utxos_with_info["hash"], expected_tip_block_hash) self.log.info("All Tests Passed")
def run_test(self): # Connect to node0 p2p0 = self.nodes[0].add_p2p_connection(BaseNode()) network_thread_start() self.nodes[0].p2p.wait_for_verack() # Build the blockchain self.tip = int(self.nodes[0].getbestblockhash(), 16) self.block_time = self.nodes[0].getblock( self.nodes[0].getbestblockhash())['time'] + 1 self.blocks = [] # Get a pubkey for the coinbase TXO coinbase_key = CECKey() coinbase_key.set_secretbytes(b"horsebattery") coinbase_pubkey = coinbase_key.get_pubkey() # Create the first block with a coinbase output to our key height = 1 block = create_block(self.tip, create_coinbase(height, coinbase_pubkey), self.block_time) self.blocks.append(block) self.block_time += 1 block.solve() # Save the coinbase for later self.block1 = block self.tip = block.sha256 height += 1 # Bury the block 100 deep so the coinbase output is spendable for i in range(100): block = create_block(self.tip, create_coinbase(height), self.block_time) block.solve() self.blocks.append(block) self.tip = block.sha256 self.block_time += 1 height += 1 # Create a transaction spending the coinbase output with an invalid (null) signature tx = CTransaction() tx.vin.append( CTxIn(COutPoint(self.block1.vtx[0].sha256, 0), scriptSig=b"")) tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE]))) tx.calc_sha256() block102 = create_block(self.tip, create_coinbase(height), self.block_time) self.block_time += 1 block102.vtx.extend([tx]) block102.hashMerkleRoot = block102.calc_merkle_root() block102.rehash() block102.solve() self.blocks.append(block102) self.tip = block102.sha256 self.block_time += 1 height += 1 # Bury the assumed valid block 8400 deep (DFTz needs 4x as much blocks to allow -assumevalid to work) for i in range(8400): block = create_block(self.tip, create_coinbase(height), self.block_time) block.nVersion = 4 block.solve() self.blocks.append(block) self.tip = block.sha256 self.block_time += 1 height += 1 # We're adding new connections so terminate the network thread self.nodes[0].disconnect_p2ps() network_thread_join() # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.start_node(1, extra_args=self.extra_args + ["-assumevalid=" + hex(block102.sha256)]) self.start_node(2, extra_args=self.extra_args + ["-assumevalid=" + hex(block102.sha256)]) p2p0 = self.nodes[0].add_p2p_connection(BaseNode()) p2p1 = self.nodes[1].add_p2p_connection(BaseNode()) p2p2 = self.nodes[2].add_p2p_connection(BaseNode()) network_thread_start() p2p0.wait_for_verack() p2p1.wait_for_verack() p2p2.wait_for_verack() # Make sure nodes actually accept the many headers self.mocktime = self.block_time set_node_times(self.nodes, self.mocktime) # send header lists to all three nodes. # node0 does not need to receive all headers # node1 must receive all headers as otherwise assumevalid is ignored in ConnectBlock # node2 should NOT receive all headers to force skipping of the assumevalid check in ConnectBlock p2p0.send_header_for_blocks(self.blocks[0:2000]) p2p1.send_header_for_blocks(self.blocks[0:2000]) p2p1.send_header_for_blocks(self.blocks[2000:4000]) p2p1.send_header_for_blocks(self.blocks[4000:6000]) p2p1.send_header_for_blocks(self.blocks[6000:8000]) p2p1.send_header_for_blocks(self.blocks[8000:]) p2p2.send_header_for_blocks(self.blocks[0:200]) # Send blocks to node0. Block 102 will be rejected. self.send_blocks_until_disconnected(p2p0) self.assert_blockchain_height(self.nodes[0], 101) # Send 200 blocks to node1. All blocks, including block 102, will be accepted. for i in range(200): p2p1.send_message(msg_block(self.blocks[i])) # Syncing so many blocks can take a while on slow systems. Give it plenty of time to sync. p2p1.sync_with_ping(300) assert_equal( self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 200) # Send blocks to node2. Block 102 will be rejected. self.send_blocks_until_disconnected(p2p2) self.assert_blockchain_height(self.nodes[2], 101)
def run_test(self): # Create a P2P connection to the first node node0 = NodeConnCB() connections = [] connections.append( NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) node0.add_connection(connections[0]) # Start up network handling in another thread. This needs to be called # after the P2P connections have been created. NetworkThread().start() # wait_for_verack ensures that the P2P connection is fully up. node0.wait_for_verack() # Out of IBD self.nodes[0].generate(1) # First create funding transaction that pays to output that does not require signatures. out_value = 10000 ftx = CTransaction() ftx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) ftxHex = self.nodes[0].fundrawtransaction( ToHex(ftx), {'changePosition': len(ftx.vout)})['hex'] ftxHex = self.nodes[0].signrawtransaction(ftxHex)['hex'] ftx = FromHex(CTransaction(), ftxHex) ftx.rehash() # Allow coinbase to mature self.nodes[0].generate(101) # Feed in funding txn and wait for both nodes to see it connections[0].send_message(msg_tx(ftx)) wait_until(lambda: ftx.hash in self.nodes[0].getrawmempool(), timeout=5) wait_until(lambda: ftx.hash in self.nodes[1].getrawmempool(), timeout=5) # Create non-final txn. parent_txid = ftx.sha256 send_value = out_value - 500 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(parent_txid, 0), b'', 0x01)) tx.vout.append(CTxOut(int(send_value), CScript([OP_TRUE]))) tx.nLockTime = int(time.time()) + 300 tx.rehash() # Send non-final txn to node0. It should be forwarded over P2P to node1. connections[0].send_message(msg_tx(tx)) wait_until(lambda: tx.hash in self.nodes[0].getrawnonfinalmempool(), timeout=5) wait_until(lambda: tx.hash in self.nodes[1].getrawnonfinalmempool(), timeout=5) assert (tx.hash not in self.nodes[0].getrawmempool()) assert (tx.hash not in self.nodes[1].getrawmempool()) # Create finalising txn. finaltx = copy.deepcopy(tx) finaltx.vin[0].nSequence = 0xFFFFFFFF finaltx.rehash() # Send finalising txn to node0. It should be forwarded over P2P to node1. connections[0].send_message(msg_tx(finaltx)) wait_until(lambda: finaltx.hash in self.nodes[0].getrawmempool(), timeout=5) wait_until(lambda: finaltx.hash in self.nodes[1].getrawmempool(), timeout=5) assert (tx.hash not in self.nodes[0].getrawnonfinalmempool()) assert (tx.hash not in self.nodes[1].getrawnonfinalmempool())
def run_test(self): self.nodes[0].generate(161) #block 161 self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({}) assert(tmpl['sizelimit'] == 1000000) assert('weightlimit' not in tmpl) assert(tmpl['sigoplimit'] == 20000) assert(tmpl['transactions'][0]['hash'] == txid) assert(tmpl['transactions'][0]['sigops'] == 2) tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']}) assert(tmpl['sizelimit'] == 1000000) assert('weightlimit' not in tmpl) assert(tmpl['sigoplimit'] == 20000) assert(tmpl['transactions'][0]['hash'] == txid) assert(tmpl['transactions'][0]['sigops'] == 2) self.nodes[0].generate(1) #block 162 balance_presetup = self.nodes[0].getbalance() self.pubkey = [] p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness for i in range(3): newaddress = self.nodes[i].getnewaddress() self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"]) multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]]) self.nodes[i].addwitnessaddress(newaddress) self.nodes[i].addwitnessaddress(multiaddress) p2sh_ids.append([]) wit_ids.append([]) for v in range(2): p2sh_ids[i].append([]) wit_ids[i].append([]) for i in range(5): for n in range(3): for v in range(2): wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 1500), self.pubkey[n], False, Decimal("1499.999"))) p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 1500), self.pubkey[n], True, Decimal("1499.999"))) self.nodes[0].generate(1) #block 163 sync_blocks(self.nodes) # Make sure all nodes recognize the transactions as theirs assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*1500 + 20*Decimal("1499.999") + 1500) assert_equal(self.nodes[1].getbalance(), 20*Decimal("1499.999")) assert_equal(self.nodes[2].getbalance(), 20*Decimal("1499.999")) self.nodes[0].generate(260) #block 423 sync_blocks(self.nodes) self.log.info("Verify default node can't accept any witness format txs before fork") # unsigned, no scriptsig self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False) # unsigned with redeem script self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) # signed self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V0][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V1][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V0][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V1][0], True) self.log.info("Verify witness txs are skipped for mining before the fork") self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424 self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 # TODO: An old node would see these txs without witnesses and be able to mine them self.log.info("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork") self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428 self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429 self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid") self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork") self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430 self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431 self.log.info("Verify previous witness txs skipped for mining can now be mined") assert_equal(len(self.nodes[2].getrawmempool()), 4) block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3) sync_blocks(self.nodes) assert_equal(len(self.nodes[2].getrawmempool()), 0) segwit_tx_list = self.nodes[2].getblock(block[0])["tx"] assert_equal(len(segwit_tx_list), 5) self.log.info("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag") assert(self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False)) assert(self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock(block[0], False)) for i in range(len(segwit_tx_list)): tx = FromHex(CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i])) assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i])) assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) == bytes_to_hex_str(tx.serialize_without_witness())) self.log.info("Verify witness txs without witness data are invalid after the fork") self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False) self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, witness_script(False, self.pubkey[2])) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, witness_script(True, self.pubkey[2])) self.log.info("Verify default node can now use witness txs") self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432 self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435 self.log.info("Verify sigops are counted in GBT with BIP141 rules after the fork") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']}) assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data assert(tmpl['weightlimit'] == 4000000) assert(tmpl['sigoplimit'] == 80000) assert(tmpl['transactions'][0]['txid'] == txid) assert(tmpl['transactions'][0]['sigops'] == 8) self.nodes[0].generate(1) # Mine a block to clear the gbt cache self.log.info("Non-segwit miners are able to use GBT response after activation.") # Create a 3-tx chain: tx1 (non-segwit input, paying to a segwit output) -> # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. txid1 = send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 1500), self.pubkey[0], False, Decimal("1499.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) assert(tx.wit.is_null()) # This should not be a segwit input assert(txid1 in self.nodes[0].getrawmempool()) # Now create tx2, which will spend from txid1. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b'')) tx.vout.append(CTxOut(int(1499.99*COIN), CScript([OP_TRUE]))) tx2_hex = self.nodes[0].signrawtransaction(ToHex(tx))['hex'] txid2 = self.nodes[0].sendrawtransaction(tx2_hex) tx = FromHex(CTransaction(), tx2_hex) assert(not tx.wit.is_null()) # Now create tx3, which will spend from txid2 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b"")) tx.vout.append(CTxOut(int(1499.95*COIN), CScript([OP_TRUE]))) # Huge fee tx.calc_sha256() txid3 = self.nodes[0].sendrawtransaction(ToHex(tx)) assert(tx.wit.is_null()) assert(txid3 in self.nodes[0].getrawmempool()) # Now try calling getblocktemplate() without segwit support. template = self.nodes[0].getblocktemplate() # Check that tx1 is the only transaction of the 3 in the template. template_txids = [ t['txid'] for t in template['transactions'] ] assert(txid2 not in template_txids and txid3 not in template_txids) assert(txid1 in template_txids) # Check that running with segwit support results in all 3 being included. template = self.nodes[0].getblocktemplate({"rules": ["segwit"]}) template_txids = [ t['txid'] for t in template['transactions'] ] assert(txid1 in template_txids) assert(txid2 in template_txids) assert(txid3 in template_txids) # Check that wtxid is properly reported in mempool entry assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) # Mine a block to clear the gbt cache again. self.nodes[0].generate(1) self.log.info("Verify behaviour of importaddress, addwitnessaddress and listunspent") # Some public keys to be used later pubkeys = [ "039bb34c57a8abefd7d47a59e64d4dd463d699185dd159aa3bfc9f02d357042386", # aW8LYZ1f1VJsrun3C1MuvderSrW8S9aBzSxc3yV1fewcsxoU3iL2 "02a61ce38b9ea2a74acdab516b961d9267e57352b57cd94691e404e4f9fc4c3f57", # aWBBj5wtGWXk9BnH3xKDc2j7YKoyb4YL7WwBsjtb46SmxsJnuiUK "042ab385efc26e50ecc1128fa57b8a5f495c83e715afed5462d3682a4c63e5145cc233232bbe71571790630645bfaf7d8d3b610bfc77eb3c0fb176a9c1275ff639", # 8bcCvz6wrE7QDwbss6VRkP69PSPbxNWY5MoKEBuTbhyjjwqfthM "0343c6de6832c84478b56d10e3e4285d7c3de0a470e3a3bd0e29f203987b2ef675", # aXE6Ak1EQFu93gjKZmgB6bTHr5noM5hsgAkUVYMizeVVy5w4vr4v "025a70aa5d62df56336fe78fe592e3add4fe0cba3e463f86cfcd3247619f47887d", # aYk5tGzTweesT1mhaNjXQGXoHbjWxnonZJyg2LGgp9LJ8Xsp6ZVx "03e89aff1a80a61c45f605f772e547f5c4a7ed44c39d34fe07bba8a512fca76fed", # aYiPa6VDWdRj4wXAxoppRwxhU2FyWZ933cN222vQ9DjPf5sakPz8 "04228fd4e8c01087398a3a9a03441020cefbd1478685a227041b031b5ba645c8f7c49313f206de3564ae9077bdc7189f173eaa13f561dcb2fbbeb825946a0996f6", # 8aY26rpLgonaKemih5wY3Vt6pp1WMcQUBpt25jLbCtTw7PNmyqJ ] # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey("8aSjqfzbcboezSLLfY25xw5C19pWDb4ZxPscqx5Y8bsHCSawxc4") uncompressed_spendable_address = ["Mmwmra5kw7Hdy2RidE2nxUoJukyo2pDnqj"] self.nodes[0].importprivkey("aUFuLfpUUkBmyrk2LkswqBhWeGXvST9o5RZu88qM1URM4r1rbfDi") compressed_spendable_address = ["MtCeg5Fc47Pbs6vWY33qM4WMfikRJtRVbi"] assert ((self.nodes[0].validateaddress(uncompressed_spendable_address[0])['iscompressed'] == False)) assert ((self.nodes[0].validateaddress(compressed_spendable_address[0])['iscompressed'] == True)) self.nodes[0].importpubkey(pubkeys[0]) compressed_solvable_address = [key_to_p2pkh(pubkeys[0])] self.nodes[0].importpubkey(pubkeys[1]) compressed_solvable_address.append(key_to_p2pkh(pubkeys[1])) self.nodes[0].importpubkey(pubkeys[2]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[2])] spendable_anytime = [] # These outputs should be seen anytime after importprivkey and addmultisigaddress spendable_after_importaddress = [] # These outputs should be seen after importaddress solvable_after_importaddress = [] # These outputs should be seen after importaddress but not spendable unsolvable_after_importaddress = [] # These outputs should be unsolvable after importaddress solvable_anytime = [] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])) compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])) unknown_address = ["MvVnKrGFSfQdWRyFsfLNsSCxvAvGjjK5vp", "2Foh6kht3KJZPpHDiEZcmnmnMik9UxNX8J9"] # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. # Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address. multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]]) script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG]) solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL])) for i in compressed_spendable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # bare and p2sh multisig with compressed keys should always be spendable spendable_anytime.extend([bare, p2sh]) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in uncompressed_spendable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # bare and p2sh multisig with uncompressed keys should always be spendable spendable_anytime.extend([bare, p2sh]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # witness with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in compressed_solvable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): # Multisig without private is not seen after addmultisigaddress, but seen after importaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # Base uncompressed multisig without private is not seen after addmultisigaddress, but seen after importaddress solvable_after_importaddress.extend([bare, p2sh]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # witness with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) op1 = CScript([OP_1]) op0 = CScript([OP_0]) # 2Fo5m5SkhHWGi5enk6B9cRqJumabN67BAZ9 is the P2SH(P2PKH) version of MtUx4SJXhEVgajoZw4BVsfCRaWMgSHov3K unsolvable_address = ["MtUx4SJXhEVgajoZw4BVsfCRaWMgSHov3K", "2Fo5m5SkhHWGi5enk6B9cRqJumabN67BAZ9", script_to_p2sh(op1), script_to_p2sh(op0)] unsolvable_address_key = hex_str_to_bytes("04ed059fa50f49fc2c1488b66aab1bbc3e18c3c4d88c0cb5f18cb8b16356ced5be7dfaebe8f03fa596787a7c898d918ee146db7ba8190fa77456140c7d17d7b516") unsolvablep2pkh = CScript([OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG]) unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)]) p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL]) p2wshop1 = CScript([OP_0, sha256(op1)]) unsolvable_after_importaddress.append(unsolvablep2pkh) unsolvable_after_importaddress.append(unsolvablep2wshp2pkh) unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script unsolvable_after_importaddress.append(p2wshop1) unseen_anytime.append(op0) # OP_0 will be imported as P2SH address with no script provided unsolvable_after_importaddress.append(p2shop0) spendable_txid = [] solvable_txid = [] spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime, 2)) solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime, 1)) self.mine_and_test_listunspent(spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, 0) importlist = [] for i in compressed_spendable_address + uncompressed_spendable_address + compressed_solvable_address + uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): bare = hex_str_to_bytes(v['hex']) importlist.append(bytes_to_hex_str(bare)) importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(bare)]))) else: pubkey = hex_str_to_bytes(v['pubkey']) p2pk = CScript([pubkey, OP_CHECKSIG]) p2pkh = CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG]) importlist.append(bytes_to_hex_str(p2pk)) importlist.append(bytes_to_hex_str(p2pkh)) importlist.append(bytes_to_hex_str(CScript([OP_0, hash160(pubkey)]))) importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(p2pk)]))) importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(p2pkh)]))) importlist.append(bytes_to_hex_str(unsolvablep2pkh)) importlist.append(bytes_to_hex_str(unsolvablep2wshp2pkh)) importlist.append(bytes_to_hex_str(op1)) importlist.append(bytes_to_hex_str(p2wshop1)) for i in importlist: # import all generated addresses. The wallet already has the private keys for some of these, so catch JSON RPC # exceptions and continue. try_rpc(-4, "The wallet already contains the private key for this address or script", self.nodes[0].importaddress, i, "", False, True) self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that no witness address should be returned by unsolvable addresses for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address: assert_raises_rpc_error(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # addwitnessaddress should return a witness addresses even if keys are not in the wallet self.nodes[0].addwitnessaddress(multisig_without_privkey_address) for i in compressed_spendable_address + compressed_solvable_address: witaddress = self.nodes[0].addwitnessaddress(i) # addwitnessaddress should return the same address if it is a known P2SH-witness address assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # Repeat some tests. This time we don't add witness scripts with importaddress # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey("8aRAba8AHow1V5FvtJkqqvTfbMhcpDbYJzhMmAcVcotnS8r2wU6") uncompressed_spendable_address = ["MiBh8daaNd1amQjKLig3sNA5N86KSVAG18"] self.nodes[0].importprivkey("aXp98JqJ4iX7MxZBMNn7vf6VtVCM7sNKYjKxemRtWYnd1LTXi1zH") compressed_spendable_address = ["MYTWn3p7Pgp2x5aK8CBPNgHnYiZJMw6RJt"] self.nodes[0].importpubkey(pubkeys[5]) compressed_solvable_address = [key_to_p2pkh(pubkeys[5])] self.nodes[0].importpubkey(pubkeys[6]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])] spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])) compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) premature_witaddress = [] for i in compressed_spendable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after addwitnessaddress spendable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH are spendable after addwitnessaddress spendable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) premature_witaddress.append(script_to_p2sh(p2wpkh)) for i in uncompressed_spendable_address + uncompressed_solvable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in compressed_solvable_address: v = self.nodes[0].validateaddress(i) if (v['isscript']): # P2WSH multisig without private key are seen after addwitnessaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after addwitnessaddress solvable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) premature_witaddress.append(script_to_p2sh(p2wpkh)) self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress # premature_witaddress are not accepted until the script is added with addwitnessaddress first for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress: # This will raise an exception assert_raises_rpc_error(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # after importaddress it should pass addwitnessaddress v = self.nodes[0].validateaddress(compressed_solvable_address[1]) self.nodes[0].importaddress(v['hex'],"",False,True) for i in compressed_spendable_address + compressed_solvable_address + premature_witaddress: witaddress = self.nodes[0].addwitnessaddress(i) assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress, 2)) solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1)) self.mine_and_test_listunspent(unseen_anytime, 0) # Check that spendable outputs are really spendable self.create_and_mine_tx_from_txids(spendable_txid) # import all the private keys so solvable addresses become spendable self.nodes[0].importprivkey("aW8LYZ1f1VJsrun3C1MuvderSrW8S9aBzSxc3yV1fewcsxoU3iL2") self.nodes[0].importprivkey("aWBBj5wtGWXk9BnH3xKDc2j7YKoyb4YL7WwBsjtb46SmxsJnuiUK") self.nodes[0].importprivkey("8bcCvz6wrE7QDwbss6VRkP69PSPbxNWY5MoKEBuTbhyjjwqfthM") self.nodes[0].importprivkey("aXE6Ak1EQFu93gjKZmgB6bTHr5noM5hsgAkUVYMizeVVy5w4vr4v") self.nodes[0].importprivkey("aYk5tGzTweesT1mhaNjXQGXoHbjWxnonZJyg2LGgp9LJ8Xsp6ZVx") self.nodes[0].importprivkey("aYiPa6VDWdRj4wXAxoppRwxhU2FyWZ933cN222vQ9DjPf5sakPz8") self.create_and_mine_tx_from_txids(solvable_txid)
def run_test(self): chain_height = self.nodes[0].getblockcount() assert_equal(chain_height, 200) self.log.debug("Mine a single block to get out of IBD") self.nodes[0].generate(1) self.sync_all() # Create funding transaction that pays to outputs that don't require signatures. out_value = 10000 ftx = CTransaction() ftx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) ftx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) ftxHex = self.nodes[2].fundrawtransaction( ToHex(ftx), {'changePosition': len(ftx.vout)})['hex'] ftxHex = self.nodes[2].signrawtransaction(ftxHex)['hex'] self.nodes[2].sendrawtransaction(ftxHex) ftx = FromHex(CTransaction(), ftxHex) ftx.rehash() # Create & send a couple of non-final txns. for i in range(2): parent_txid = ftx.sha256 send_value = out_value - 500 non_final_tx = CTransaction() non_final_tx.vin.append(CTxIn(COutPoint(parent_txid, i), b'', 0x01)) non_final_tx.vout.append( CTxOut(int(send_value), CScript([OP_TRUE]))) non_final_tx.nLockTime = int(time.time()) + 300 non_final_txHex = self.nodes[2].signrawtransaction( ToHex(non_final_tx))['hex'] self.nodes[2].sendrawtransaction(non_final_txHex) self.sync_all() self.log.debug( "Verify that all nodes have 2 transactions in their non-final mempools" ) assert_equal(len(self.nodes[0].getrawnonfinalmempool()), 2) assert_equal(len(self.nodes[1].getrawnonfinalmempool()), 2) assert_equal(len(self.nodes[2].getrawnonfinalmempool()), 2) self.log.debug( "Send another 4 transactions from node2 (to its own address)") for i in range(4): self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) self.sync_all() self.log.debug( "Verify that all nodes have 5 transactions in their main mempools") assert_equal(len(self.nodes[0].getrawmempool()), 5) assert_equal(len(self.nodes[1].getrawmempool()), 5) assert_equal(len(self.nodes[2].getrawmempool()), 5) self.log.debug( "Stop-start node0 and node1. Verify that node0 has the transactions in its mempools and node1 does not." ) self.stop_nodes() self.start_node(0) self.start_node(1) # Give bitcoind a second to reload the mempool time.sleep(1) wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) wait_until(lambda: len(self.nodes[0].getrawnonfinalmempool()) == 2) assert_equal(len(self.nodes[1].getrawmempool()), 0) assert_equal(len(self.nodes[1].getrawnonfinalmempool()), 0) self.log.debug( "Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file." ) self.stop_nodes() self.start_node(0, extra_args=["-persistmempool=0"]) # Give bitcoind a second to reload the mempool time.sleep(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(len(self.nodes[0].getrawnonfinalmempool()), 0) self.log.debug( "Stop-start node0. Verify that it has the transactions in its mempool." ) self.stop_nodes() self.start_node(0) wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) wait_until(lambda: len(self.nodes[0].getrawnonfinalmempool()) == 2)
def test_opt_in(self): """Replacing should only work if orig tx opted in""" tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a non-opting in transaction tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, n_sequence=0xffffffff)] tx1a.vout = [CTxOut(1 * COIN, CScript([b'a']))] tx1a_hex = tx_to_hex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True) # Shouldn't be able to double-spend tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, n_sequence=0)] tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b']))] tx1b_hex = tx_to_hex(tx1b) # This will raise an exception assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, True) tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a different non-opting in transaction tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, n_sequence=0xfffffffe)] tx2a.vout = [CTxOut(1 * COIN, CScript([b'a']))] tx2a_hex = tx_to_hex(tx2a) tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True) # Still shouldn't be able to double-spend tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, n_sequence=0)] tx2b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b']))] tx2b_hex = tx_to_hex(tx2b) # This will raise an exception assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, True) # Now create a new transaction that spends from tx1a and tx2a # opt-in on one of the inputs # Transaction should be replaceable on either input tx1a_txid = int(tx1a_txid, 16) tx2a_txid = int(tx2a_txid, 16) tx3a = CTransaction() tx3a.vin = [ CTxIn(COutPoint(tx1a_txid, 0), n_sequence=0xffffffff), CTxIn(COutPoint(tx2a_txid, 0), n_sequence=0xfffffffd) ] tx3a.vout = [ CTxOut(int(0.9 * COIN), CScript([b'c'])), CTxOut(int(0.9 * COIN), CScript([b'd'])) ] tx3a_hex = tx_to_hex(tx3a) self.nodes[0].sendrawtransaction(tx3a_hex, True) tx3b = CTransaction() tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), n_sequence=0)] tx3b.vout = [CTxOut(int(0.5 * COIN), CScript([b'e']))] tx3b_hex = tx_to_hex(tx3b) tx3c = CTransaction() tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), n_sequence=0)] tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f']))] tx3c_hex = tx_to_hex(tx3c) self.nodes[0].sendrawtransaction(tx3b_hex, True) # If tx3b was accepted, tx3c won't look like a replacement, # but make sure it is accepted anyway self.nodes[0].sendrawtransaction(tx3c_hex, True)
def make_large_invalid_tx(tx_to_spend, output_ndx): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, output_ndx), b"", 0xffffffff)) tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2000000, CScript([bytes(1000000), OP_DROP, OP_FALSE]))) tx.rehash() return tx
def run_test(self): self.nodes[0].generate(161) #block 161 self.log.info( "Verify sigops are counted in GBT with pre-BIP141 rules before the fork" ) txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({}) assert (tmpl['sizelimit'] == 100000) assert ('weightlimit' not in tmpl) assert (tmpl['sigoplimit'] == 2000) assert (tmpl['transactions'][0]['hash'] == txid) assert (tmpl['transactions'][0]['sigops'] == 2) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) assert (tmpl['sizelimit'] == 100000) assert ('weightlimit' not in tmpl) assert (tmpl['sigoplimit'] == 2000) assert (tmpl['transactions'][0]['hash'] == txid) assert (tmpl['transactions'][0]['sigops'] == 2) self.nodes[0].generate(1) #block 162 balance_presetup = self.nodes[0].getbalance() self.pubkey = [] p2sh_ids = [ ] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh wit_ids = [ ] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness for i in range(3): newaddress = self.nodes[i].getnewaddress() self.pubkey.append( self.nodes[i].getaddressinfo(newaddress)["pubkey"]) multiscript = CScript([ OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG ]) p2sh_addr = self.nodes[i].addwitnessaddress(newaddress) bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False) p2sh_ms_addr = self.nodes[i].addmultisigaddress( 1, [self.pubkey[-1]], '', 'p2sh-segwit')['address'] bip173_ms_addr = self.nodes[i].addmultisigaddress( 1, [self.pubkey[-1]], '', 'bech32')['address'] assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1])) assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1])) assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript)) assert_equal(bip173_ms_addr, script_to_p2wsh(multiscript)) p2sh_ids.append([]) wit_ids.append([]) for v in range(2): p2sh_ids[i].append([]) wit_ids[i].append([]) for i in range(5): for n in range(3): for v in range(2): wit_ids[n][v].append( send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) p2sh_ids[n][v].append( send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) self.nodes[0].generate(1) #block 163 sync_blocks(self.nodes) # Make sure all nodes recognize the transactions as theirs assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 * 50 + 20 * Decimal("49.999") + 50) assert_equal(self.nodes[1].getbalance(), 20 * Decimal("49.999")) assert_equal(self.nodes[2].getbalance(), 20 * Decimal("49.999")) self.nodes[0].generate(260) #block 423 sync_blocks(self.nodes) self.log.info( "Verify witness txs are skipped for mining before the fork") self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424 self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 self.log.info( "Verify unsigned p2sh witness txs without a redeem script are invalid" ) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) self.nodes[2].generate(4) # blocks 428-431 self.log.info( "Verify previous witness txs skipped for mining can now be mined") assert_equal(len(self.nodes[2].getrawmempool()), 4) block = self.nodes[2].generate( 1) #block 432 (first block with new rules; 432 = 144 * 3) sync_blocks(self.nodes) assert_equal(len(self.nodes[2].getrawmempool()), 0) segwit_tx_list = self.nodes[2].getblock(block[0])["tx"] assert_equal(len(segwit_tx_list), 5) self.log.info( "Verify default node can't accept txs with missing witness") # unsigned, no scriptsig self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False) # unsigned with redeem script self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) self.log.info( "Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag" ) assert (self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False)) assert (self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock( block[0], False)) for i in range(len(segwit_tx_list)): tx = FromHex( CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert (self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i])) assert (self.nodes[1].getrawtransaction( segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i])) assert (self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert (self.nodes[1].getrawtransaction( segwit_tx_list[i]) == self.nodes[2].gettransaction( segwit_tx_list[i])["hex"]) assert (self.nodes[0].getrawtransaction( segwit_tx_list[i]) == bytes_to_hex_str( tx.serialize_without_witness())) self.log.info( "Verify witness txs without witness data are invalid after the fork" ) self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False) self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, witness_script(False, self.pubkey[2])) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, witness_script(True, self.pubkey[2])) self.log.info("Verify default node can now use witness txs") self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432 self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435 self.log.info( "Verify sigops are counted in GBT with BIP141 rules after the fork" ) txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) assert ( tmpl['sizelimit'] >= 390000 ) # actual maximum size is lower due to minimum mandatory non-witness data assert (tmpl['weightlimit'] == 400000) assert (tmpl['sigoplimit'] == 8000) assert (tmpl['transactions'][0]['txid'] == txid) assert (tmpl['transactions'][0]['sigops'] == 8) self.nodes[0].generate(1) # Mine a block to clear the gbt cache self.log.info( "Non-segwit miners are able to use GBT response after activation.") # Create a 3-tx chain: tx1 (non-segwit input, paying to a segwit output) -> # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) assert (tx.wit.is_null()) # This should not be a segwit input assert (txid1 in self.nodes[0].getrawmempool()) # Now create tx2, which will spend from txid1. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b'')) tx.vout.append( CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex'] txid2 = self.nodes[0].sendrawtransaction(tx2_hex) tx = FromHex(CTransaction(), tx2_hex) assert (not tx.wit.is_null()) # Now create tx3, which will spend from txid2 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b"")) tx.vout.append( CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee tx.calc_sha256() txid3 = self.nodes[0].sendrawtransaction(ToHex(tx)) assert (tx.wit.is_null()) assert (txid3 in self.nodes[0].getrawmempool()) # Now try calling getblocktemplate() without segwit support. template = self.nodes[0].getblocktemplate() # Check that tx1 is the only transaction of the 3 in the template. template_txids = [t['txid'] for t in template['transactions']] assert (txid2 not in template_txids and txid3 not in template_txids) assert (txid1 in template_txids) # Check that running with segwit support results in all 3 being included. template = self.nodes[0].getblocktemplate({"rules": ["segwit"]}) template_txids = [t['txid'] for t in template['transactions']] assert (txid1 in template_txids) assert (txid2 in template_txids) assert (txid3 in template_txids) # Check that wtxid is properly reported in mempool entry assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) # Mine a block to clear the gbt cache again. self.nodes[0].generate(1) self.log.info( "Verify behaviour of importaddress, addwitnessaddress and listunspent" ) # Some public keys to be used later pubkeys = [ "0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # b4Vfz2Ly8GAubXRrhpSGF9ctmorBYVzdokEQcDrbV2EmnzB5LonH "02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # b4bVUqL7X7ZJpqzDnF6Ks32YM9GXbVdrEbmznQMRXcTixRM1AbGA "04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 8iW8cP2tV3YUkc8XrPz3v7CvFjV5VkhpzgKos82q1LWshZEooJo "02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # b4BabAFLEnDwVU4FB2SosQPc42WvquuCqaa1rE34tV8rmhbQbjQv "036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # b54DUJnyPL6VQMoCd4sXtvCBvhM1vG2vSCwqShSRE8ryS7Cuu9H1 "0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # b8HQcxqFUhg4BsdjE21bisYRkwT4jvKhTUmcYh5ege5SQbLsmrAz "0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ ] # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey( "8j9PwFko4f5TjUAyE9ssZAQSNmbCHXdV6sBwuh2ouxyeg41E8Vu") uncompressed_spendable_address = ["cg37jZdKe7YsxJMUVZNKD36EuaDpPdbZqe"] self.nodes[0].importprivkey( "b2yTVwqY6fX1PqXUEqWbUCYAaUo4YFQc8nRZavfUt9Ki77ewQaDr") compressed_spendable_address = ["cWjYG6zbUdBfsULfCHD8xQF928QYxcy4ZZ"] assert ((self.nodes[0].getaddressinfo( uncompressed_spendable_address[0])['iscompressed'] == False)) assert ((self.nodes[0].getaddressinfo( compressed_spendable_address[0])['iscompressed'] == True)) self.nodes[0].importpubkey(pubkeys[0]) compressed_solvable_address = [key_to_p2pkh(pubkeys[0])] self.nodes[0].importpubkey(pubkeys[1]) compressed_solvable_address.append(key_to_p2pkh(pubkeys[1])) self.nodes[0].importpubkey(pubkeys[2]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[2])] spendable_anytime = [ ] # These outputs should be seen anytime after importprivkey and addmultisigaddress spendable_after_importaddress = [ ] # These outputs should be seen after importaddress solvable_after_importaddress = [ ] # These outputs should be seen after importaddress but not spendable unsolvable_after_importaddress = [ ] # These outputs should be unsolvable after importaddress solvable_anytime = [ ] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], uncompressed_spendable_address[0] ])['address']) compressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [ compressed_spendable_address[0], uncompressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_solvable_address[0], compressed_solvable_address[1] ])['address']) unknown_address = [ "cdYTLJRxGc5wq6cptTiFCECCMnZBmhcdhq", "dZZ7MpuczL1VXDwHygXvpowoAZGxRs6dJs" ] # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. # Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address. multisig_without_privkey_address = self.nodes[0].addmultisigaddress( 2, [pubkeys[3], pubkeys[4]])['address'] script = CScript([ OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG ]) solvable_after_importaddress.append( CScript([OP_HASH160, hash160(script), OP_EQUAL])) for i in compressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # p2sh multisig with compressed keys should always be spendable spendable_anytime.extend([p2sh]) # bare multisig can be watched and signed, but is not treated as ours solvable_after_importaddress.extend([bare]) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([ p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # p2sh multisig with uncompressed keys should always be spendable spendable_anytime.extend([p2sh]) # bare multisig can be watched and signed, but is not treated as ours solvable_after_importaddress.extend([bare]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # Witness output types with uncompressed keys are never seen unseen_anytime.extend([ p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) for i in compressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): # Multisig without private is not seen after addmultisigaddress, but seen after importaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_importaddress.extend( [bare, p2sh, p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress solvable_after_importaddress.extend([ p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) for i in uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # Base uncompressed multisig without private is not seen after addmultisigaddress, but seen after importaddress solvable_after_importaddress.extend([bare, p2sh]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # Witness output types with uncompressed keys are never seen unseen_anytime.extend([ p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) op1 = CScript([OP_1]) op0 = CScript([OP_0]) # dTXLAVZMSwCLfWDF4us6U6F1FWbyWyBYwK is the P2SH(P2PKH) version of cV2MQNbEFyXpjGihDYNqf4s1RQGbS94jVC unsolvable_address = [ "cV2MQNbEFyXpjGihDYNqf4s1RQGbS94jVC", "dTXLAVZMSwCLfWDF4us6U6F1FWbyWyBYwK", script_to_p2sh(op1), script_to_p2sh(op0) ] unsolvable_address_key = hex_str_to_bytes( "02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D" ) unsolvablep2pkh = CScript([ OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG ]) unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)]) p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL]) p2wshop1 = CScript([OP_0, sha256(op1)]) unsolvable_after_importaddress.append(unsolvablep2pkh) unsolvable_after_importaddress.append(unsolvablep2wshp2pkh) unsolvable_after_importaddress.append( op1) # OP_1 will be imported as script unsolvable_after_importaddress.append(p2wshop1) unseen_anytime.append( op0 ) # OP_0 will be imported as P2SH address with no script provided unsolvable_after_importaddress.append(p2shop0) spendable_txid = [] solvable_txid = [] spendable_txid.append( self.mine_and_test_listunspent(spendable_anytime, 2)) solvable_txid.append( self.mine_and_test_listunspent(solvable_anytime, 1)) self.mine_and_test_listunspent( spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, 0) importlist = [] for i in compressed_spendable_address + uncompressed_spendable_address + compressed_solvable_address + uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): bare = hex_str_to_bytes(v['hex']) importlist.append(bytes_to_hex_str(bare)) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(bare)]))) else: pubkey = hex_str_to_bytes(v['pubkey']) p2pk = CScript([pubkey, OP_CHECKSIG]) p2pkh = CScript([ OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG ]) importlist.append(bytes_to_hex_str(p2pk)) importlist.append(bytes_to_hex_str(p2pkh)) importlist.append( bytes_to_hex_str(CScript([OP_0, hash160(pubkey)]))) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(p2pk)]))) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(p2pkh)]))) importlist.append(bytes_to_hex_str(unsolvablep2pkh)) importlist.append(bytes_to_hex_str(unsolvablep2wshp2pkh)) importlist.append(bytes_to_hex_str(op1)) importlist.append(bytes_to_hex_str(p2wshop1)) for i in importlist: # import all generated addresses. The wallet already has the private keys for some of these, so catch JSON RPC # exceptions and continue. try_rpc( -4, "The wallet already contains the private key for this address or script", self.nodes[0].importaddress, i, "", False, True) self.nodes[0].importaddress( script_to_p2sh(op0)) # import OP_0 as address only self.nodes[0].importaddress( multisig_without_privkey_address) # Test multisig_without_privkey spendable_txid.append( self.mine_and_test_listunspent( spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that no witness address should be returned by unsolvable addresses for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address: assert_raises_rpc_error( -4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # addwitnessaddress should return a witness addresses even if keys are not in the wallet self.nodes[0].addwitnessaddress(multisig_without_privkey_address) for i in compressed_spendable_address + compressed_solvable_address: witaddress = self.nodes[0].addwitnessaddress(i) # addwitnessaddress should return the same address if it is a known P2SH-witness address assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append( self.mine_and_test_listunspent( spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # Repeat some tests. This time we don't add witness scripts with importaddress # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey( "8id8M1PDTjZimEZBfxp2iYgp9xFZ865PHcVqdksDhja21H3kuZC") uncompressed_spendable_address = ["cS8VPRWos5pYHt6ay9WAnenT6LeDpfdtVP"] self.nodes[0].importprivkey( "b2QBP8LNcftKZAW4zx7DdZYa3FvxMmuAAuCvkgmKcvEptAiiFsvU") compressed_spendable_address = ["ckhW8KuyAKe1AvKYy5FXcP8JZrWA9n6u3g"] self.nodes[0].importpubkey(pubkeys[5]) compressed_solvable_address = [key_to_p2pkh(pubkeys[5])] self.nodes[0].importpubkey(pubkeys[6]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])] spendable_after_addwitnessaddress = [ ] # These outputs should be seen after importaddress solvable_after_addwitnessaddress = [ ] # These outputs should be seen after importaddress but not spendable unseen_anytime = [] # These outputs should never be seen solvable_anytime = [ ] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], uncompressed_spendable_address[0] ])['address']) compressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_solvable_address[0], uncompressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_solvable_address[0] ])['address']) premature_witaddress = [] for i in compressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after addwitnessaddress spendable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH are always spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address + uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in compressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): # P2WSH multisig without private key are seen after addwitnessaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable solvable_anytime.extend([p2wpkh, p2sh_p2wpkh]) self.mine_and_test_listunspent(spendable_anytime, 2) self.mine_and_test_listunspent(solvable_anytime, 1) self.mine_and_test_listunspent( spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress # premature_witaddress are not accepted until the script is added with addwitnessaddress first for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress: # This will raise an exception assert_raises_rpc_error( -4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # after importaddress it should pass addwitnessaddress v = self.nodes[0].getaddressinfo(compressed_solvable_address[1]) self.nodes[0].importaddress(v['hex'], "", False, True) for i in compressed_spendable_address + compressed_solvable_address + premature_witaddress: witaddress = self.nodes[0].addwitnessaddress(i) assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append( self.mine_and_test_listunspent( spendable_after_addwitnessaddress + spendable_anytime, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_after_addwitnessaddress + solvable_anytime, 1)) self.mine_and_test_listunspent(unseen_anytime, 0) # Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works v1_addr = program_to_witness(1, [3, 5]) v1_tx = self.nodes[0].createrawtransaction( [getutxo(spendable_txid[0])], {v1_addr: 1}) v1_decoded = self.nodes[1].decoderawtransaction(v1_tx) assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr) assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305") # Check that spendable outputs are really spendable self.create_and_mine_tx_from_txids(spendable_txid) # import all the private keys so solvable addresses become spendable self.nodes[0].importprivkey( "b4Vfz2Ly8GAubXRrhpSGF9ctmorBYVzdokEQcDrbV2EmnzB5LonH") self.nodes[0].importprivkey( "b4bVUqL7X7ZJpqzDnF6Ks32YM9GXbVdrEbmznQMRXcTixRM1AbGA") self.nodes[0].importprivkey( "8iW8cP2tV3YUkc8XrPz3v7CvFjV5VkhpzgKos82q1LWshZEooJo") self.nodes[0].importprivkey( "b4BabAFLEnDwVU4FB2SosQPc42WvquuCqaa1rE34tV8rmhbQbjQv") self.nodes[0].importprivkey( "b54DUJnyPL6VQMoCd4sXtvCBvhM1vG2vSCwqShSRE8ryS7Cuu9H1") self.nodes[0].importprivkey( "b8HQcxqFUhg4BsdjE21bisYRkwT4jvKhTUmcYh5ege5SQbLsmrAz") self.create_and_mine_tx_from_txids(solvable_txid) # Test that importing native P2WPKH/P2WSH scripts works for use_p2wsh in [False, True]: if use_p2wsh: scriptPubKey = "00203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a" transaction = "01000000000100e1f505000000002200203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a00000000" else: scriptPubKey = "a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d87" transaction = "01000000000100e1f5050000000017a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d8700000000" self.nodes[1].importaddress(scriptPubKey, "", False) rawtxfund = self.nodes[1].fundrawtransaction(transaction)['hex'] rawtxfund = self.nodes[1].signrawtransactionwithwallet( rawtxfund)["hex"] txid = self.nodes[1].sendrawtransaction(rawtxfund) assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid) assert_equal( self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid) # Assert it is properly saved self.stop_node(1) self.start_node(1) assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid) assert_equal( self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
def run_test(self): self.nodes[0].generate(161) #block 161 self.log.info( "Verify sigops are counted in GBT with pre-BIP141 rules before the fork" ) txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({}) assert (tmpl['sizelimit'] == 1000000) assert ('weightlimit' not in tmpl) assert (tmpl['sigoplimit'] == 20000) assert (tmpl['transactions'][0]['hash'] == txid) assert (tmpl['transactions'][0]['sigops'] == 2) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) assert (tmpl['sizelimit'] == 1000000) assert ('weightlimit' not in tmpl) assert (tmpl['sigoplimit'] == 20000) assert (tmpl['transactions'][0]['hash'] == txid) assert (tmpl['transactions'][0]['sigops'] == 2) self.nodes[0].generate(1) #block 162 balance_presetup = self.nodes[0].getbalance() self.pubkey = [] p2sh_ids = [ ] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh wit_ids = [ ] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness for i in range(3): newaddress = self.nodes[i].getnewaddress() self.pubkey.append( self.nodes[i].getaddressinfo(newaddress)["pubkey"]) multiscript = CScript([ OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG ]) p2sh_addr = self.nodes[i].addwitnessaddress(newaddress) bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False) p2sh_ms_addr = self.nodes[i].addmultisigaddress( 1, [self.pubkey[-1]], '', 'p2sh-segwit')['address'] bip173_ms_addr = self.nodes[i].addmultisigaddress( 1, [self.pubkey[-1]], '', 'bech32')['address'] assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1])) assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1])) assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript)) assert_equal(bip173_ms_addr, script_to_p2wsh(multiscript)) p2sh_ids.append([]) wit_ids.append([]) for v in range(2): p2sh_ids[i].append([]) wit_ids[i].append([]) for i in range(5): for n in range(3): for v in range(2): wit_ids[n][v].append( send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) p2sh_ids[n][v].append( send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) self.nodes[0].generate(1) #block 163 sync_blocks(self.nodes) # Make sure all nodes recognize the transactions as theirs assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 * 50 + 20 * Decimal("49.999") + 50) assert_equal(self.nodes[1].getbalance(), 20 * Decimal("49.999")) assert_equal(self.nodes[2].getbalance(), 20 * Decimal("49.999")) self.nodes[0].generate(260) #block 423 sync_blocks(self.nodes) self.log.info( "Verify default node can't accept any witness format txs before fork" ) # unsigned, no scriptsig self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False) # unsigned with redeem script self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) # signed self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V0][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V1][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V0][0], True) self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V1][0], True) self.log.info( "Verify witness txs are skipped for mining before the fork") self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424 self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 self.log.info( "Verify unsigned p2sh witness txs without a redeem script are invalid" ) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) self.nodes[2].generate(4) # blocks 428-431 self.log.info( "Verify previous witness txs skipped for mining can now be mined") assert_equal(len(self.nodes[2].getrawmempool()), 4) block = self.nodes[2].generate( 1) #block 432 (first block with new rules; 432 = 144 * 3) sync_blocks(self.nodes) assert_equal(len(self.nodes[2].getrawmempool()), 0) segwit_tx_list = self.nodes[2].getblock(block[0])["tx"] assert_equal(len(segwit_tx_list), 5) self.log.info( "Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag" ) assert (self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False)) assert (self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock( block[0], False)) for i in range(len(segwit_tx_list)): tx = FromHex( CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert (self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i])) assert (self.nodes[1].getrawtransaction( segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i])) assert (self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"]) assert (self.nodes[1].getrawtransaction( segwit_tx_list[i]) == self.nodes[2].gettransaction( segwit_tx_list[i])["hex"]) assert (self.nodes[0].getrawtransaction( segwit_tx_list[i]) == bytes_to_hex_str( tx.serialize_without_witness())) self.log.info( "Verify witness txs without witness data are invalid after the fork" ) self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False) self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, witness_script(False, self.pubkey[2])) self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, witness_script(True, self.pubkey[2])) self.log.info("Verify default node can now use witness txs") self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432 self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435 self.log.info( "Verify sigops are counted in GBT with BIP141 rules after the fork" ) txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) assert ( tmpl['sizelimit'] >= 3999577 ) # actual maximum size is lower due to minimum mandatory non-witness data assert (tmpl['weightlimit'] == 4000000) assert (tmpl['sigoplimit'] == 80000) assert (tmpl['transactions'][0]['txid'] == txid) assert (tmpl['transactions'][0]['sigops'] == 8) self.nodes[0].generate(1) # Mine a block to clear the gbt cache self.log.info( "Non-segwit miners are able to use GBT response after activation.") # Create a 3-tx chain: tx1 (non-segwit input, paying to a segwit output) -> # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) assert (tx.wit.is_null()) # This should not be a segwit input assert (txid1 in self.nodes[0].getrawmempool()) # Now create tx2, which will spend from txid1. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b'')) tx.vout.append( CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex'] txid2 = self.nodes[0].sendrawtransaction(tx2_hex) tx = FromHex(CTransaction(), tx2_hex) assert (not tx.wit.is_null()) # Now create tx3, which will spend from txid2 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b"")) tx.vout.append( CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee tx.calc_sha256() txid3 = self.nodes[0].sendrawtransaction(ToHex(tx)) assert (tx.wit.is_null()) assert (txid3 in self.nodes[0].getrawmempool()) # Now try calling getblocktemplate() without segwit support. template = self.nodes[0].getblocktemplate() # Check that tx1 is the only transaction of the 3 in the template. template_txids = [t['txid'] for t in template['transactions']] assert (txid2 not in template_txids and txid3 not in template_txids) assert (txid1 in template_txids) # Check that running with segwit support results in all 3 being included. template = self.nodes[0].getblocktemplate({"rules": ["segwit"]}) template_txids = [t['txid'] for t in template['transactions']] assert (txid1 in template_txids) assert (txid2 in template_txids) assert (txid3 in template_txids) # Check that wtxid is properly reported in mempool entry assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) # Mine a block to clear the gbt cache again. self.nodes[0].generate(1) self.log.info( "Verify behaviour of importaddress, addwitnessaddress and listunspent" ) # Some public keys to be used later pubkeys = [ "0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb "02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97 "04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV "02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd "036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66 "0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K "0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ ] # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey( "92e6XLo5jVAVwrQKPNTs93oQco8f8sDNBcpv73Dsrs397fQtFQn") uncompressed_spendable_address = ["mvozP4UwyGD2mGZU4D2eMvMLPB9WkMmMQu"] self.nodes[0].importprivkey( "cNC8eQ5dg3mFAVePDX4ddmPYpPbw41r9bm2jd1nLJT77e6RrzTRR") compressed_spendable_address = ["mmWQubrDomqpgSYekvsU7HWEVjLFHAakLe"] assert ((self.nodes[0].getaddressinfo( uncompressed_spendable_address[0])['iscompressed'] == False)) assert ((self.nodes[0].getaddressinfo( compressed_spendable_address[0])['iscompressed'] == True)) self.nodes[0].importpubkey(pubkeys[0]) compressed_solvable_address = [key_to_p2pkh(pubkeys[0])] self.nodes[0].importpubkey(pubkeys[1]) compressed_solvable_address.append(key_to_p2pkh(pubkeys[1])) self.nodes[0].importpubkey(pubkeys[2]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[2])] spendable_anytime = [ ] # These outputs should be seen anytime after importprivkey and addmultisigaddress spendable_after_importaddress = [ ] # These outputs should be seen after importaddress solvable_after_importaddress = [ ] # These outputs should be seen after importaddress but not spendable unsolvable_after_importaddress = [ ] # These outputs should be unsolvable after importaddress solvable_anytime = [ ] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], uncompressed_spendable_address[0] ])['address']) compressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [ compressed_spendable_address[0], uncompressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_solvable_address[0], compressed_solvable_address[1] ])['address']) unknown_address = [ "mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx" ] # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. # Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address. multisig_without_privkey_address = self.nodes[0].addmultisigaddress( 2, [pubkeys[3], pubkeys[4]])['address'] script = CScript([ OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG ]) solvable_after_importaddress.append( CScript([OP_HASH160, hash160(script), OP_EQUAL])) for i in compressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # p2sh multisig with compressed keys should always be spendable spendable_anytime.extend([p2sh]) # bare multisig can be watched and signed, but is not treated as ours solvable_after_importaddress.extend([bare]) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([ p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # p2sh multisig with uncompressed keys should always be spendable spendable_anytime.extend([p2sh]) # bare multisig can be watched and signed, but is not treated as ours solvable_after_importaddress.extend([bare]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # Witness output types with uncompressed keys are never seen unseen_anytime.extend([ p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) for i in compressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): # Multisig without private is not seen after addmultisigaddress, but seen after importaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_importaddress.extend( [bare, p2sh, p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress solvable_after_importaddress.extend([ p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) for i in uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # Base uncompressed multisig without private is not seen after addmultisigaddress, but seen after importaddress solvable_after_importaddress.extend([bare, p2sh]) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) # Witness output types with uncompressed keys are never seen unseen_anytime.extend([ p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ]) op1 = CScript([OP_1]) op0 = CScript([OP_0]) # 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V unsolvable_address = [ "mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V", "2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe", script_to_p2sh(op1), script_to_p2sh(op0) ] unsolvable_address_key = hex_str_to_bytes( "02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D" ) unsolvablep2pkh = CScript([ OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG ]) unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)]) p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL]) p2wshop1 = CScript([OP_0, sha256(op1)]) unsolvable_after_importaddress.append(unsolvablep2pkh) unsolvable_after_importaddress.append(unsolvablep2wshp2pkh) unsolvable_after_importaddress.append( op1) # OP_1 will be imported as script unsolvable_after_importaddress.append(p2wshop1) unseen_anytime.append( op0 ) # OP_0 will be imported as P2SH address with no script provided unsolvable_after_importaddress.append(p2shop0) spendable_txid = [] solvable_txid = [] spendable_txid.append( self.mine_and_test_listunspent(spendable_anytime, 2)) solvable_txid.append( self.mine_and_test_listunspent(solvable_anytime, 1)) self.mine_and_test_listunspent( spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, 0) importlist = [] for i in compressed_spendable_address + uncompressed_spendable_address + compressed_solvable_address + uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): bare = hex_str_to_bytes(v['hex']) importlist.append(bytes_to_hex_str(bare)) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(bare)]))) else: pubkey = hex_str_to_bytes(v['pubkey']) p2pk = CScript([pubkey, OP_CHECKSIG]) p2pkh = CScript([ OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG ]) importlist.append(bytes_to_hex_str(p2pk)) importlist.append(bytes_to_hex_str(p2pkh)) importlist.append( bytes_to_hex_str(CScript([OP_0, hash160(pubkey)]))) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(p2pk)]))) importlist.append( bytes_to_hex_str(CScript([OP_0, sha256(p2pkh)]))) importlist.append(bytes_to_hex_str(unsolvablep2pkh)) importlist.append(bytes_to_hex_str(unsolvablep2wshp2pkh)) importlist.append(bytes_to_hex_str(op1)) importlist.append(bytes_to_hex_str(p2wshop1)) for i in importlist: # import all generated addresses. The wallet already has the private keys for some of these, so catch JSON RPC # exceptions and continue. try_rpc( -4, "The wallet already contains the private key for this address or script", self.nodes[0].importaddress, i, "", False, True) self.nodes[0].importaddress( script_to_p2sh(op0)) # import OP_0 as address only self.nodes[0].importaddress( multisig_without_privkey_address) # Test multisig_without_privkey spendable_txid.append( self.mine_and_test_listunspent( spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that no witness address should be returned by unsolvable addresses for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address: assert_raises_rpc_error( -4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # addwitnessaddress should return a witness addresses even if keys are not in the wallet self.nodes[0].addwitnessaddress(multisig_without_privkey_address) for i in compressed_spendable_address + compressed_solvable_address: witaddress = self.nodes[0].addwitnessaddress(i) # addwitnessaddress should return the same address if it is a known P2SH-witness address assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append( self.mine_and_test_listunspent( spendable_anytime + spendable_after_importaddress, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_anytime + solvable_after_importaddress, 1)) self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) self.mine_and_test_listunspent(unseen_anytime, 0) # Repeat some tests. This time we don't add witness scripts with importaddress # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey( "927pw6RW8ZekycnXqBQ2JS5nPyo1yRfGNN8oq74HeddWSpafDJH") uncompressed_spendable_address = ["mguN2vNSCEUh6rJaXoAVwY3YZwZvEmf5xi"] self.nodes[0].importprivkey( "cMcrXaaUC48ZKpcyydfFo8PxHAjpsYLhdsp6nmtB3E2ER9UUHWnw") compressed_spendable_address = ["n1UNmpmbVUJ9ytXYXiurmGPQ3TRrXqPWKL"] self.nodes[0].importpubkey(pubkeys[5]) compressed_solvable_address = [key_to_p2pkh(pubkeys[5])] self.nodes[0].importpubkey(pubkeys[6]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])] spendable_after_addwitnessaddress = [ ] # These outputs should be seen after importaddress solvable_after_addwitnessaddress = [ ] # These outputs should be seen after importaddress but not spendable unseen_anytime = [] # These outputs should never be seen solvable_anytime = [ ] # These outputs should be solvable after importpubkey unseen_anytime = [] # These outputs should never be seen uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [ uncompressed_spendable_address[0], uncompressed_spendable_address[0] ])['address']) compressed_spendable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_spendable_address[0] ])['address']) uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_solvable_address[0], uncompressed_solvable_address[0] ])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress( 2, [compressed_spendable_address[0], compressed_solvable_address[0] ])['address']) premature_witaddress = [] for i in compressed_spendable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after addwitnessaddress spendable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH are always spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in uncompressed_spendable_address + uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh]) for i in compressed_solvable_address: v = self.nodes[0].getaddressinfo(i) if (v['isscript']): # P2WSH multisig without private key are seen after addwitnessaddress [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) premature_witaddress.append(script_to_p2sh(p2wsh)) else: [ p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh ] = self.p2pkh_address_to_script(v) # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable solvable_anytime.extend([p2wpkh, p2sh_p2wpkh]) self.mine_and_test_listunspent(spendable_anytime, 2) self.mine_and_test_listunspent(solvable_anytime, 1) self.mine_and_test_listunspent( spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) # addwitnessaddress should refuse to return a witness address if an uncompressed key is used # note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress # premature_witaddress are not accepted until the script is added with addwitnessaddress first for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress: # This will raise an exception assert_raises_rpc_error( -4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # after importaddress it should pass addwitnessaddress v = self.nodes[0].getaddressinfo(compressed_solvable_address[1]) self.nodes[0].importaddress(v['hex'], "", False, True) for i in compressed_spendable_address + compressed_solvable_address + premature_witaddress: witaddress = self.nodes[0].addwitnessaddress(i) assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) spendable_txid.append( self.mine_and_test_listunspent( spendable_after_addwitnessaddress + spendable_anytime, 2)) solvable_txid.append( self.mine_and_test_listunspent( solvable_after_addwitnessaddress + solvable_anytime, 1)) self.mine_and_test_listunspent(unseen_anytime, 0) # Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works v1_addr = program_to_witness(1, [3, 5]) v1_tx = self.nodes[0].createrawtransaction( [getutxo(spendable_txid[0])], {v1_addr: 1}) v1_decoded = self.nodes[1].decoderawtransaction(v1_tx) assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr) assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305") # Check that spendable outputs are really spendable self.create_and_mine_tx_from_txids(spendable_txid) # import all the private keys so solvable addresses become spendable self.nodes[0].importprivkey( "cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb") self.nodes[0].importprivkey( "cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97") self.nodes[0].importprivkey( "91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV") self.nodes[0].importprivkey( "cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd") self.nodes[0].importprivkey( "cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66") self.nodes[0].importprivkey( "cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K") self.create_and_mine_tx_from_txids(solvable_txid) # Test that importing native P2WPKH/P2WSH scripts works for use_p2wsh in [False, True]: if use_p2wsh: scriptPubKey = "00203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a" transaction = "01000000000100e1f505000000002200203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a00000000" else: scriptPubKey = "a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d87" transaction = "01000000000100e1f5050000000017a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d8700000000" self.nodes[1].importaddress(scriptPubKey, "", False) rawtxfund = self.nodes[1].fundrawtransaction(transaction)['hex'] rawtxfund = self.nodes[1].signrawtransactionwithwallet( rawtxfund)["hex"] txid = self.nodes[1].sendrawtransaction(rawtxfund) assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid) assert_equal( self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid) # Assert it is properly saved self.stop_node(1) self.start_node(1) assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid) assert_equal( self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
def test_orphan_tx_handling(self, base_tx, resolve_via_block): node = self.nodes[0] # convenience reference to the node # Create a root transaction that we withold until all dependend transactions # are sent out and in the orphan cache tx_withhold = CTransaction() tx_withhold.vin.append(CTxIn(outpoint=COutPoint(base_tx, 0))) tx_withhold.vout.append( CTxOut(nValue=50 * COIN - 12000, scriptPubKey=b'\x51')) tx_withhold.calc_sha256() # Our first orphan tx with some outputs to create further orphan txs tx_orphan_1 = CTransaction() tx_orphan_1.vin.append( CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0))) tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51')] * 3 tx_orphan_1.calc_sha256() # A valid transaction with low fee tx_orphan_2_no_fee = CTransaction() tx_orphan_2_no_fee.vin.append( CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0))) tx_orphan_2_no_fee.vout.append( CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51')) # A valid transaction with sufficient fee tx_orphan_2_valid = CTransaction() tx_orphan_2_valid.vin.append( CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1))) tx_orphan_2_valid.vout.append( CTxOut(nValue=10 * COIN - 12000, scriptPubKey=b'\x51')) tx_orphan_2_valid.calc_sha256() # An invalid transaction with negative fee tx_orphan_2_invalid = CTransaction() tx_orphan_2_invalid.vin.append( CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2))) tx_orphan_2_invalid.vout.append( CTxOut(nValue=11 * COIN, scriptPubKey=b'\x51')) self.log.info('Send the orphans ... ') # Send valid orphan txs from p2ps[0] node.p2p.send_txs_and_test( [tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid], node, success=False) # Send invalid tx from p2ps[1] node.p2ps[1].send_txs_and_test([tx_orphan_2_invalid], node, success=False) assert_equal(0, node.getmempoolinfo()['size']) # Mempool should be empty assert_equal(2, len(node.getpeerinfo())) # p2ps[1] is still connected self.log.info('Send the withhold tx ... ') if resolve_via_block: # Test orphan handling/resolution by publishing the withhold TX via a mined block prev_block = node.getblockheader(node.getbestblockhash()) block = create_block(int(prev_block['hash'], 16), create_coinbase(prev_block['height'] + 1), prev_block["time"] + 1) block.vtx.append(tx_withhold) block.hashMerkleRoot = block.calc_merkle_root() block.solve() node.p2p.send_blocks_and_test([block], node, success=True) else: # Test orphan handling/resolution by publishing the withhold TX via the mempool node.p2p.send_txs_and_test([tx_withhold], node, success=True) # Transactions that should end up in the mempool expected_mempool = { t.hash for t in [ tx_withhold, # The transaction that is the root for all orphans tx_orphan_1, # The orphan transaction that splits the coins tx_orphan_2_valid, # The valid transaction (with sufficient fee) ] } # Transactions that do not end up in the mempool # tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx) # tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx) if resolve_via_block: # This TX has appeared in a block instead of being broadcasted via the mempool expected_mempool.remove(tx_withhold.hash) wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected assert_equal(expected_mempool, set(node.getrawmempool()))
def run_test(self): # Connect to node0 node0 = BaseNode() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) node0.add_connection(connections[0]) NetworkThread().start() # Start up network handling in another thread node0.wait_for_verack() # Build the blockchain self.tip = int(self.nodes[0].getbestblockhash(), 16) self.block_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time'] + 1 self.blocks = [] # Get a pubkey for the coinbase TXO coinbase_key = CECKey() coinbase_key.set_secretbytes(b"horsebattery") coinbase_pubkey = coinbase_key.get_pubkey() # Create the first block with a coinbase output to our key height = 1 block = create_block(self.tip, create_coinbase(height, coinbase_pubkey), self.block_time) self.blocks.append(block) self.block_time += 1 block.solve() # Save the coinbase for later self.block1 = block self.tip = block.sha256 height += 1 # Bury the block 100 deep so the coinbase output is spendable for i in range(100): block = create_block(self.tip, create_coinbase(height), self.block_time) block.solve() self.blocks.append(block) self.tip = block.sha256 self.block_time += 1 height += 1 # Create a transaction spending the coinbase output with an invalid (null) signature tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.block1.vtx[0].sha256, 0), scriptSig=b"")) tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE]))) tx.calc_sha256() block102 = create_block(self.tip, create_coinbase(height), self.block_time) self.block_time += 1 block102.vtx.extend([tx]) block102.hashMerkleRoot = block102.calc_merkle_root() block102.rehash() block102.solve() self.blocks.append(block102) self.tip = block102.sha256 self.block_time += 1 height += 1 # Bury the assumed valid block 2100 deep for i in range(2100): block = create_block(self.tip, create_coinbase(height), self.block_time) block.nVersion = 4 block.solve() self.blocks.append(block) self.tip = block.sha256 self.block_time += 1 height += 1 # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)]) node1 = BaseNode() # connects to node1 connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1)) node1.add_connection(connections[1]) node1.wait_for_verack() self.start_node(2, extra_args=["-assumevalid=" + hex(block102.sha256)]) node2 = BaseNode() # connects to node2 connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2)) node2.add_connection(connections[2]) node2.wait_for_verack() # send header lists to all three nodes node0.send_header_for_blocks(self.blocks[0:2000]) node0.send_header_for_blocks(self.blocks[2000:]) node1.send_header_for_blocks(self.blocks[0:2000]) node1.send_header_for_blocks(self.blocks[2000:]) node2.send_header_for_blocks(self.blocks[0:200]) # Send blocks to node0. Block 102 will be rejected. self.send_blocks_until_disconnected(node0) self.assert_blockchain_height(self.nodes[0], 101) # Send all blocks to node1. All blocks will be accepted. for i in range(2202): node1.send_message(msg_block(self.blocks[i])) # Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync. node1.sync_with_ping(120) assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) # Send blocks to node2. Block 102 will be rejected. self.send_blocks_until_disconnected(node2) self.assert_blockchain_height(self.nodes[2], 101)
def make_invalid_p2sh_tx(tx_to_spend, output_ndx): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, output_ndx), b"", 0xffffffff)) tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2000, CScript([OP_HASH160, hash160(b'123'), OP_EQUAL]))) tx.rehash() return tx