def test_api_errors(self, blockNode, otherNode): candidate = blockNode.getminingcandidate() block = CBlock() block.nVersion = candidate["version"] block.hashPrevBlock = int(candidate["prevhash"], 16) block.nTime = candidate["time"] block.nBits = int(candidate["nBits"], 16) block.nNonce = 0 # Submit with wrong ID self.log.info("Submitting to wrong node with unknown ID") assert_raises_rpc_error(-22, "Block candidate ID not found", otherNode.submitminingsolution, { 'id': candidate['id'], 'nonce': block.nNonce }) # Omit nonce self.log.info("Submitting without nonce") assert_raises_rpc_error(-22, "nonce not found", blockNode.submitminingsolution, {'id': candidate['id']}) # Bad coinbase self.log.info("Submitting with bad coinbase") assert_raises_rpc_error( -22, "coinbase decode failed", blockNode.submitminingsolution, { 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': 'ALoadOfRubbish' }) # Bad POW self.log.info("Submitting with bad POW") coinbase_tx = create_coinbase(height=int(candidate["height"]) + 1) coinbase_tx.rehash() block.vtx = [coinbase_tx] block.hashMerkleRoot = merkle_root_from_merkle_proof( coinbase_tx.sha256, candidate["merkleProof"]) solve_bad(block) submitResult = blockNode.submitminingsolution({ 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': '{}'.format(ToHex(coinbase_tx)) }) assert submitResult == 'high-hash'
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 run_scenario4(self, conn, num_of_chains, chain_length, spend, allowhighfees=False, dontcheckfee=False, timeout=30): # Create and send tx chains. txchains, bad, orphan = self.get_txchains_n(num_of_chains, chain_length, spend, num_of_bad_chains=0) # Prepare duplicated inputs for sendrawtransactions rpc_txs_bulk_input = [] for tx in range(len(txchains)): rpc_txs_bulk_input.append({ 'hex': ToHex(txchains[tx]), 'allowhighfees': allowhighfees, 'dontcheckfee': dontcheckfee }) rpc_txs_bulk_input.append({ 'hex': ToHex(txchains[tx]), 'allowhighfees': allowhighfees, 'dontcheckfee': dontcheckfee }) # Shuffle inputs. random.shuffle(rpc_txs_bulk_input) # Submit bulk input. rejected_txns = conn.rpc.sendrawtransactions(rpc_txs_bulk_input) # There should be rejected known transactions. assert_equal(len(rejected_txns), 1) assert_equal(len(rejected_txns['known']), num_of_chains * chain_length) assert (set(rejected_txns['known']) == {t.hash for t in txchains}) # Check if required transactions are accepted by the mempool. self.check_mempool(conn.rpc, txchains, timeout)
def test_case(self, rpcsend=None, conn=None): # 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 self.send_txn(rpcsend, conn, 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. self.send_txn(rpcsend, conn, 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. self.send_txn(rpcsend, conn, 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 cltv_validate(node, tx, height): '''Modify the signature in vin 0 of the tx to pass CLTV Prepends <height> CLTV DROP in the scriptSig, and sets the locktime to height''' tx.vin[0].nSequence = 0 tx.nLockTime = height # Need to re-sign, since nSequence and nLockTime changed signed_result = node.signrawtransaction(ToHex(tx)) new_tx = CTransaction() new_tx.deserialize(BytesIO(hex_str_to_bytes(signed_result['hex']))) new_tx.vin[0].scriptSig = CScript( [CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP] + list(CScript(new_tx.vin[0].scriptSig))) return new_tx
def send_generic_input_tx(self, node, coins): coin = coins.pop() amount = coin['amount'] - FEE return { 'txid': node.sendrawtransaction( ToHex( self.sign_transaction( node, self.create_transaction(node, coin, self.nodeaddress, amount)))), 'vout': 0, 'amount': amount }
def make_funding_transaction(node, n_outputs=30, value=100000000): ftx = CTransaction() for i in range(n_outputs): ftx.vout.append(CTxOut(value, CScript([OP_TRUE]))) # fund the transcation: ftxHex = node.fundrawtransaction(ToHex(ftx), {'changePosition': len(ftx.vout)})['hex'] ftxHex = node.signrawtransaction(ftxHex)['hex'] ftx = FromHex(CTransaction(), ftxHex) ftx.rehash() node.sendrawtransaction(ftxHex) node.generate(1) return ftx
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 mine_using_template(self, nodeidx=0): tmpl = self.nodes[nodeidx].getblocktemplate() assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"])) block = CBlock() block.nVersion = int(tmpl["version"]) block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 # extended block block.nStakeDifficulty = int(tmpl["stakedifficulty"], 16) block.nVoteBits = tmpl["votebits"] block.nTicketPoolSize = tmpl["ticketpoolsize"] block.ticketLotteryState = tmpl["ticketlotterystate"] block.nVoters = tmpl["voters"] block.nFreshStake = tmpl["freshstake"] block.nRevocations = tmpl["revocations"] block.extraData = tmpl["extradata"] block.nStakeVersion = tmpl["stakeversion"] block.vtx = [coinbase_tx] for tx in tmpl["transactions"]: ctx = CTransaction() ctx.deserialize(BytesIO(hex_str_to_bytes(tx['data']))) ctx.rehash() block.vtx.append(ctx) block.hashMerkleRoot = block.calc_merkle_root() add_witness_commitment(block) block.solve() print("-------------") print("mine using template on node:", nodeidx) print('solved hash', block.hash) # print("submit for height", idx) submit_result = self.nodes[nodeidx].submitblock(ToHex(block)) print(submit_result) assert (submit_result in [None, "inconclusive"]) return block.hash
def _create_and_submit_block(self, node, candidate, get_coinbase): # Do POW for mining candidate and submit solution block, coinbase_tx = create_block_from_candidate( candidate, get_coinbase) self.log.info("block hash before submit: " + str(block.hash)) if (get_coinbase): self.log.info("Checking submission with provided coinbase") return node.submitminingsolution({ 'id': candidate['id'], 'nonce': block.nNonce }) else: self.log.info("Checking submission with generated coinbase") return node.submitminingsolution({ 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': '{}'.format(ToHex(coinbase_tx)) })
def run_scenario3(self, conn, num_of_chains, chain_length, spend, allowhighfees=False, dontcheckfee=False, timeout=30): # Create and send tx chains. txchains, bad, orphan = self.get_txchains_n(num_of_chains, chain_length, spend, num_of_bad_chains=0) # Prepare inputs for sendrawtransactions rpc_txs_bulk_input = [] for tx in range(len(txchains)): # Collect txn input data for bulk submit through rpc interface. rpc_txs_bulk_input.append({'hex': ToHex(txchains[tx]), 'allowhighfees': allowhighfees, 'dontcheckfee': dontcheckfee}) # Send a txn, one by one, through p2p interface. conn.send_message(msg_tx(txchains[tx])) # Check if there is an expected number of transactions in the validation queues # - this scenario relies on ptv delayed processing wait_until(lambda: conn.rpc.getblockchainactivity()["transactions"] == num_of_chains * chain_length, timeout=timeout) # Submit a batch of txns through rpc interface. rejected_txns = conn.rpc.sendrawtransactions(rpc_txs_bulk_input) # There should be num_of_chains * chain_length rejected transactions. # - there are num_of_chains*chain_length known transactions # - due to the fact that all were received through the p2p interface # - all are waiting in the ptv queues assert_equal(len(rejected_txns['known']), num_of_chains * chain_length) # No transactions should be in the mempool. assert_equal(conn.rpc.getmempoolinfo()['size'], 0)
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) if (sign): signed = node.signrawtransaction(tx_to_witness) assert ("errors" not in signed or len(["errors"]) == 0) return node.sendrawtransaction(signed["hex"]) else: if (insert_redeem_script): tx = FromHex(CTransaction(), tx_to_witness) tx.vin[0].scriptSig += CScript( [hex_str_to_bytes(insert_redeem_script)]) tx_to_witness = ToHex(tx) return node.sendrawtransaction(tx_to_witness)
def test_with_submitminingsolution(self): """ Verify getminincandidate and submitminingsolution """ blockhashes = self.nodes[0].generate(5) b2_hash = blockhashes[1] b3_hash = blockhashes[2] self.nodes[0].softrejectblock(b3_hash, 2) assert_equal(self.nodes[0].getbestblockhash(), b2_hash) candidate = self.nodes[0].getminingcandidate(True) block, coinbase_tx = create_block_from_candidate(candidate, True) self.nodes[0].submitminingsolution({ 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': '{}'.format(ToHex(coinbase_tx)) }) assert_equal(self.nodes[0].getbestblockhash(), block.hash) assert_equal(self.nodes[0].getblockcount(), 3)
def test_end_to_end_block_relay(self, node, listeners): utxo = self.utxos.pop(0) block = self.build_block_with_transactions(node, utxo, 10) [l.clear_block_announcement() for l in listeners] # ToHex() won't serialize with witness, but this block has no witnesses # anyway. TODO: repeat this test with witness tx's to a segwit node. node.submitblock(ToHex(block)) for l in listeners: wait_until(lambda: l.received_block_announcement(), timeout=30, lock=mininode_lock) with mininode_lock: for l in listeners: assert "cmpctblock" in l.last_message l.last_message[ "cmpctblock"].header_and_shortids.header.calc_sha256() assert_equal( l.last_message["cmpctblock"].header_and_shortids.header. sha256, block.sha256)
def test_with_submitblock(self): """ 1. mine blocks b1->b2 and call softrejectblock(b1_hash, 1) 2. make block b3 with b2 as parent and send it via submitblock assert: b3 should be active """ blockhashes = self.nodes[0].generate(2) b1_hash = blockhashes[0] b2_hash = blockhashes[1] tip = int(b2_hash, 16) tip_blocktime = self.nodes[0].getblockheader(b2_hash)["time"] height = self.nodes[0].getblockcount() b3 = create_block(tip, create_coinbase(height), tip_blocktime + 1) b3.nVersion = 3 b3.hashMerkleRoot = b3.calc_merkle_root() b3.solve() b3.rehash() self.nodes[0].softrejectblock(b1_hash, 1) assert_equal(self.nodes[0].getblockcount(), 0) self.nodes[0].submitblock(ToHex(b3)) assert_equal(self.nodes[0].getbestblockhash(), b3.hash)
def sign_transaction(self, node, unsignedtx): rawtx = ToHex(unsignedtx) signresult = node.signrawtransaction(rawtx) tx = FromHex(CTransaction(), signresult['hex']) return tx
def send_generic_input_tx(self, node, coinbases): amount = Decimal("99.99") return node.sendrawtransaction(ToHex(self.sign_transaction(node, self.create_transaction(node, node.getblock(coinbases.pop())['tx'][0], self.nodeaddress, amount))))
def run_test(self): blocks = [] self.bl_count = 0 blocks.append(self.nodes[1].getblockhash(0)) small_target_h = 3 s = " Node1 generates %d blocks" % (CBH_DELTA + small_target_h) print(s) print self.mark_logs(s) blocks.extend(self.nodes[1].generate(CBH_DELTA + small_target_h)) self.sync_all() #------------------------------------------------------------------------------------------------------- print "Trying to send a tx with a scriptPubKey referencing a block too recent..." #------------------------------------------------------------------------------------------------------- # Create a tx having in its scriptPubKey a custom referenced block in the CHECKBLOCKATHEIGHT part # select necessary utxos for doing the PAYMENT usp = self.nodes[1].listunspent() PAYMENT = Decimal('1.0') FEE = Decimal('0.00005') amount = Decimal('0') inputs = [] print " Node1 sends %f coins to Node2" % PAYMENT for x in usp: amount += Decimal(x['amount']) inputs.append({"txid": x['txid'], "vout": x['vout']}) if amount >= PAYMENT + FEE: break outputs = { self.nodes[1].getnewaddress(): (Decimal(amount) - PAYMENT - FEE), self.nodes[2].getnewaddress(): PAYMENT } rawTx = self.nodes[1].createrawtransaction(inputs, outputs) # build an object from the raw tx in order to be able to modify it tx_01 = CTransaction() f = cStringIO.StringIO(unhexlify(rawTx)) tx_01.deserialize(f) decodedScriptOrig = self.nodes[1].decodescript( binascii.hexlify(tx_01.vout[1].scriptPubKey)) scriptOrigAsm = decodedScriptOrig['asm'] # print "Original scriptPubKey asm 1: ", scriptOrigAsm # print # store the hashed script, it is reused params = scriptOrigAsm.split() hash_script = hex_str_to_bytes(params[2]) # new referenced block height modTargetHeigth = CBH_DELTA + small_target_h - FINALITY_MIN_AGE + 5 # new referenced block hash modTargetHash = hex_str_to_bytes( self.swap_bytes(blocks[modTargetHeigth])) # build modified script modScriptPubKey = CScript([ OP_DUP, OP_HASH160, hash_script, OP_EQUALVERIFY, OP_CHECKSIG, modTargetHash, modTargetHeigth, OP_CHECKBLOCKATHEIGHT ]) tx_01.vout[1].scriptPubKey = modScriptPubKey tx_01.rehash() decodedScriptMod = self.nodes[1].decodescript( binascii.hexlify(tx_01.vout[1].scriptPubKey)) print " Modified scriptPubKey in tx 1: ", decodedScriptMod['asm'] signedRawTx = self.nodes[1].signrawtransaction(ToHex(tx_01)) h = self.nodes[1].getblockcount() assert_greater_than(FINALITY_MIN_AGE, h - modTargetHeigth) #raw_input("\npress enter to go on ..") try: txid = self.nodes[1].sendrawtransaction(signedRawTx['hex']) print " Tx sent: ", txid # should fail, therefore force test failure assert_equal(True, False) except JSONRPCException, e: print " ==> tx has been rejected as expected:" print " referenced block height=%d, chainActive.height=%d, minimumAge=%d" % ( modTargetHeigth, h, FINALITY_MIN_AGE) print
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): # Mine some coins self.nodes[0].generate(110) # Get some addresses from the two nodes addr1 = [self.nodes[1].getnewaddress() for i in range(3)] addr2 = [self.nodes[2].getnewaddress() for i in range(3)] addrs = addr1 + addr2 # Send 1 + 0.5 coin to each address [self.nodes[0].sendtoaddress(addr, 1.0) for addr in addrs] [self.nodes[0].sendtoaddress(addr, 0.5) for addr in addrs] self.nodes[0].generate(1) self.sync_all() # For each node, send 0.2 coins back to 0; # - node[1] should pick one 0.5 UTXO and leave the rest # - node[2] should pick one (1.0 + 0.5) UTXO group corresponding to a # given address, and leave the rest txid1 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) tx1 = self.nodes[1].getrawtransaction(txid1, True) # txid1 should have 1 input and 2 outputs assert_equal(1, len(tx1["vin"])) assert_equal(2, len(tx1["vout"])) # one output should be 0.2, the other should be ~0.3 v = [vout["value"] for vout in tx1["vout"]] v.sort() assert_approx(v[0], 0.2) assert_approx(v[1], 0.3, 0.0001) txid2 = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) tx2 = self.nodes[2].getrawtransaction(txid2, True) # txid2 should have 2 inputs and 2 outputs assert_equal(2, len(tx2["vin"])) assert_equal(2, len(tx2["vout"])) # one output should be 0.2, the other should be ~1.3 v = [vout["value"] for vout in tx2["vout"]] v.sort() assert_approx(v[0], 0.2) assert_approx(v[1], 1.3, 0.0001) # Empty out node2's wallet self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), subtractfeefromamount=True) self.sync_all() self.nodes[0].generate(1) # Fill node2's wallet with 10000 outputs corresponding to the same # scriptPubKey for i in range(5): raw_tx = self.nodes[0].createrawtransaction([{"txid":"0"*64, "vout":0}], [{addr2[0]: 0.05}]) tx = FromHex(CTransaction(), raw_tx) tx.vin = [] tx.vout = [tx.vout[0]] * 2000 funded_tx = self.nodes[0].fundrawtransaction(ToHex(tx)) signed_tx = self.nodes[0].signrawtransactionwithwallet(funded_tx['hex']) self.nodes[0].sendrawtransaction(signed_tx['hex']) self.nodes[0].generate(1) self.sync_all() # Check that we can create a transaction that only requires ~100 of our # utxos, without pulling in all outputs and creating a transaction that # is way too big. assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5)
def test_invalidblock(self): """ Verify situation when receiving invalid block, which is no longer considered soft rejected, via p2p """ self.nodes[0].generate(101) # create spendable tx tx_spendable = CTransaction() tx_spendable.vout = [CTxOut(4500000000, CScript([OP_TRUE]))] tx_hex_funded = self.nodes[0].fundrawtransaction( ToHex(tx_spendable), {'changePosition': len(tx_spendable.vout)})['hex'] tx_hex = self.nodes[0].signrawtransaction(tx_hex_funded)['hex'] self.nodes[0].sendrawtransaction(tx_hex, True) tx_spendable = FromHex(CTransaction(), tx_hex) tx_spendable.rehash() b1_hash = self.nodes[0].generate(1)[0] b2_hash = self.nodes[0].generate(1)[0] b3_hash = self.nodes[0].generate(1)[0] sync_blocks(self.nodes) self.nodes[0].softrejectblock(b2_hash, 1) assert_equal(self.nodes[0].getbestblockhash(), b1_hash) assert_equal(self.nodes[0].getblockcount(), 102) # Create a P2P connection to node0 that will be used to send blocks self.stop_node(0) with self.run_node_with_connections( title="test_invalidblock", node_index=0, args=["-whitelist=127.0.0.1"], # Need to whilelist localhost, so that node accepts any block number_of_connections=1) as connections: conn0 = connections[0] self.nodes[0].waitforblockheight(102) # create and send block (child of b3) with coinbase tx that pays to much coinbase_tx = create_coinbase(103) coinbase_tx.vout[0].nValue = 60 * COIN coinbase_tx.rehash() b4_invalid = create_block(int(b3_hash, 16), coinbase_tx) b4_invalid.hashMerkleRoot = b4_invalid.calc_merkle_root() b4_invalid.solve() b4_invalid.rehash() conn0.cb.send_message(msg_block(b4_invalid)) # b1 must still be at the tip self.wait_for_chain_tips(self.nodes[0], {b1_hash, b4_invalid.hash}) wait_until( lambda: self.nodes[0].getbestblockhash() == b1_hash ) # NOTE: need to wait, since reorg back to b1 can take a while even after chaintips are already as expected # create and send block b2 (child of b1) that creates a new chain b2a = create_block(int(b1_hash, 16), create_coinbase(102)) b2a.solve() b2a.rehash() conn0.cb.send_message(msg_block(b2a)) # b2a must become new tip self.wait_for_chain_tips(self.nodes[0], {b2a.hash, b4_invalid.hash}) assert_equal(self.nodes[0].getbestblockhash(), b2a.hash) # create and send block (child of b3) containing an invalid txn b4a_invalid = create_block(int(b3_hash, 16), create_coinbase(103)) b4a_invalid.vtx.append( create_transaction(tx_spendable, 0, CScript([OP_RETURN]), 100000)) # invalid unlock script b4a_invalid.hashMerkleRoot = b4a_invalid.calc_merkle_root() b4a_invalid.solve() b4a_invalid.rehash() conn0.cb.send_message(msg_block(b4a_invalid)) # b2a must still be at the tip self.wait_for_chain_tips( self.nodes[0], {b2a.hash, b4_invalid.hash, b4a_invalid.hash}) wait_until(lambda: self.nodes[0].getbestblockhash() == b2a.hash)
def get_tests(self): node = self.nodes[0] self.chain.set_genesis_hash(int(node.getbestblockhash(), 16)) # shorthand for functions block = self.chain.next_block # Create a new block block(0) self.chain.save_spendable_output() yield self.accepted() # Now we need that block to mature so we can spend the coinbase. test = TestInstance(sync_every_block=False) for i in range(99): block(5000 + i) test.blocks_and_transactions.append([self.chain.tip, True]) self.chain.save_spendable_output() yield test block_size = 100000 block = block(1, spend=self.chain.get_spendable_output(), block_size=block_size) yield self.accepted() #rest json self.getBlock(block, block_size, "json") #rest binary self.getBlock(block, block_size, "bin") #rest hex self.getBlock(block, block_size, "hex") #rpc hex assert_equal(ToHex(block), self.nodes[0].getblock(block.hash, 0)) #rpc json with no tx details checkJsonBlock(self.nodes[0].getblock(block.hash, 1), False, block.hash) #rpc json with tx details checkJsonBlock(self.nodes[0].getblock(block.hash, 2), True, block.hash) #check help getblockHelpMessage = "getblock \"blockhash\" ( verbosity )" assert_equal(getblockHelpMessage in self.nodes[0].help("getblock"), True) #check help when wrong parameters are used assert_raises_rpc_error(-1, getblockHelpMessage, self.nodes[0].getblock, "a", "b", "c") #check getblock errors still work assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblock, "somehash") #check errors still work batch = self.nodes[0].batch([ self.nodes[0].getblock.get_request(block.hash), self.nodes[0].getblock.get_request("somehash"), self.nodes[0].getblockcount.get_request(), self.nodes[0].undefinedmethod.get_request() ]) checkJsonBlock(batch[0]["result"], False, block.hash) assert_equal(batch[0]["error"], None) assert_equal(batch[1]["result"], None) assert_equal(batch[1]["error"]["message"], "Block not found") assert_equal(batch[2]["error"], None) assert_equal(batch[3]["result"], None) assert_equal(batch[3]["error"]["message"], "Method not found")
def sign_transaction(self, node, unsignedtx): rawtx = ToHex(unsignedtx) signresult = node.signrawtransaction(rawtx) return CTransaction().deserialize(signresult['hex'])
def bloat_raw_tx(rawtx_hex, min_size=None): tx = CTransaction() FromHex(tx, rawtx_hex) bloat_tx(tx, min_size) return ToHex(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'] == 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 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 _process_rpc_accepts(self, connection, to_accept): for tx in to_accept: connection.rpc.sendrawtransaction( ToHex(tx)) # will raise if not successful
def mine_block(self, node, vtx=[], miner_address=None, mn_payee=None, mn_amount=None, use_mnmerkleroot_from_tip=False, expected_error=None): bt = node.getblocktemplate() height = bt['height'] tip_hash = bt['previousblockhash'] tip_block = node.getblock(tip_hash) coinbasevalue = bt['coinbasevalue'] if miner_address is None: miner_address = node.getnewaddress() if mn_payee is None: if isinstance(bt['masternode'], list): mn_payee = bt['masternode'][0]['payee'] else: mn_payee = bt['masternode']['payee'] # we can't take the masternode payee amount from the template here as we might have additional fees in vtx # calculate fees that the block template included (we'll have to remove it from the coinbase as we won't # include the template's transactions bt_fees = 0 for tx in bt['transactions']: bt_fees += tx['fee'] new_fees = 0 for tx in vtx: in_value = 0 out_value = 0 for txin in tx.vin: txout = node.gettxout("%064x" % txin.prevout.hash, txin.prevout.n, False) in_value += int(txout['value'] * COIN) for txout in tx.vout: out_value += txout.nValue new_fees += in_value - out_value # fix fees coinbasevalue -= bt_fees coinbasevalue += new_fees if mn_amount is None: mn_amount = get_masternode_payment(height, coinbasevalue) miner_amount = coinbasevalue - mn_amount outputs = {miner_address: str(Decimal(miner_amount) / COIN)} if mn_amount > 0: outputs[mn_payee] = str(Decimal(mn_amount) / COIN) coinbase = FromHex(CTransaction(), node.createrawtransaction([], outputs)) coinbase.vin = create_coinbase(height).vin # We can't really use this one as it would result in invalid merkle roots for masternode lists if len(bt['coinbase_payload']) != 0: cbtx = FromHex(CCbTx(version=1), bt['coinbase_payload']) if use_mnmerkleroot_from_tip: if 'cbTx' in tip_block: cbtx.merkleRootMNList = int( tip_block['cbTx']['merkleRootMNList'], 16) else: cbtx.merkleRootMNList = 0 coinbase.nVersion = 3 coinbase.nType = 5 # CbTx coinbase.vExtraPayload = cbtx.serialize() coinbase.calc_sha256() block = create_block(int(tip_hash, 16), coinbase) block.vtx += vtx # Add quorum commitments from template for tx in bt['transactions']: tx2 = FromHex(CTransaction(), tx['data']) if tx2.nType == 6: block.vtx.append(tx2) block.hashMerkleRoot = block.calc_merkle_root() block.solve() result = node.submitblock(ToHex(block)) if expected_error is not None and result != expected_error: raise AssertionError( 'mining the block should have failed with error %s, but submitblock returned %s' % (expected_error, result)) elif expected_error is None and result is not None: raise AssertionError('submitblock returned %s' % (result))
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) node0utxos = self.nodes[0].listunspent(1) tx1 = self.nodes[0].createrawtransaction( [node0utxos.pop()], {self.nodes[1].getnewaddress(): 49.99}) txid1 = self.nodes[0].sendrawtransaction( self.nodes[0].signrawtransaction(tx1)["hex"]) tx2 = self.nodes[0].createrawtransaction( [node0utxos.pop()], {self.nodes[1].getnewaddress(): 49.99}) txid2 = self.nodes[0].sendrawtransaction( self.nodes[0].signrawtransaction(tx2)["hex"]) # This will raise an exception because the transaction is not yet in a block assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[0].gettxoutproof, [txid1]) self.nodes[0].generate(1) blockhash = self.nodes[0].getblockhash(chain_height + 1) self.sync_all() txlist = [] blocktxn = self.nodes[0].getblock(blockhash, True)["tx"] txlist.append(blocktxn[1]) txlist.append(blocktxn[2]) assert_equal( self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1 ])), [txid1]) assert_equal( self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid1, txid2])), txlist) assert_equal( self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid1, txid2], blockhash)), txlist) txin_spent = self.nodes[1].listunspent(1).pop() tx3 = self.nodes[1].createrawtransaction( [txin_spent], {self.nodes[0].getnewaddress(): 49.98}) txid3 = self.nodes[0].sendrawtransaction( self.nodes[1].signrawtransaction(tx3)["hex"]) self.nodes[0].generate(1) self.sync_all() txid_spent = txin_spent["txid"] txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 # We can't find the block from a fully-spent tx assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent]) # We can get the proof if we specify the block assert_equal( self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid_spent], blockhash)), [txid_spent]) # We can't get the proof if we specify a non-existent block assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000") # We can get the proof if the transaction is unspent assert_equal( self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid_unspent])), [txid_unspent]) # We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter. assert_equal( sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid1, txid2]))), sorted(txlist)) assert_equal( sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof( [txid2, txid1]))), sorted(txlist)) # We can always get a proof if we have a -txindex assert_equal( self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof( [txid_spent])), [txid_spent]) # We can't get a proof if we specify transactions from different blocks assert_raises_rpc_error( -5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3]) # Now we'll try tweaking a proof. proof = self.nodes[3].gettxoutproof([txid1, txid2]) assert txid1 in self.nodes[0].verifytxoutproof(proof) assert txid2 in self.nodes[1].verifytxoutproof(proof) tweaked_proof = FromHex(CMerkleBlock(), proof) # Make sure that our serialization/deserialization is working assert txid1 in self.nodes[2].verifytxoutproof(ToHex(tweaked_proof)) # Check to see if we can go up the merkle tree and pass this off as a # single-transaction block tweaked_proof.txn.nTransactions = 1 tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot] tweaked_proof.txn.vBits = [True] + [False] * 7 for n in self.nodes: assert not n.verifytxoutproof(ToHex(tweaked_proof))