示例#1
0
 def mine_and_test_listunspent(self, script_list, ismine):
     utxo = find_unspent(self.nodes[0], 50)
     tx = CTransaction()
     tx.vin.append(CTxIn(COutPoint(int("0x" + utxo["txid"], 0), utxo["vout"])))
     for i in script_list:
         tx.vout.append(CTxOut(10000000, i))
     tx.rehash()
     signresults = self.nodes[0].signrawtransaction(bytes_to_hex_str(tx.serialize_without_witness()))["hex"]
     txid = self.nodes[0].sendrawtransaction(signresults, True)
     self.nodes[0].generate(1)
     sync_blocks(self.nodes)
     watchcount = 0
     spendcount = 0
     for i in self.nodes[0].listunspent():
         if i["txid"] == txid:
             watchcount += 1
             if i["spendable"] == True:
                 spendcount += 1
     if ismine == 2:
         assert_equal(spendcount, len(script_list))
     elif ismine == 1:
         assert_equal(watchcount, len(script_list))
         assert_equal(spendcount, 0)
     else:
         assert_equal(watchcount, 0)
     return txid
示例#2
0
 def mine_and_test_listunspent(self, script_list, ismine):
     utxo = find_spendable_utxo(self.nodes[0], 50)
     tx = CTransaction()
     tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout'])))
     for i in script_list:
         tx.vout.append(CTxOut(10000000, i))
     tx.rehash()
     signresults = self.nodes[0].signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
     txid = self.nodes[0].sendrawtransaction(signresults, True)
     self.nodes[0].generate(1)
     sync_blocks(self.nodes)
     watchcount = 0
     spendcount = 0
     for i in self.nodes[0].listunspent():
         if (i['txid'] == txid):
             watchcount += 1
             if (i['spendable'] == True):
                 spendcount += 1
     if (ismine == 2):
         assert_equal(spendcount, len(script_list))
     elif (ismine == 1):
         assert_equal(watchcount, len(script_list))
         assert_equal(spendcount, 0)
     else:
         assert_equal(watchcount, 0)
     return txid
示例#3
0
 def create_and_mine_tx_from_txids(self, txids, success = True):
     tx = CTransaction()
     for i in txids:
         txtmp = CTransaction()
         txraw = self.nodes[0].getrawtransaction(i)
         f = BytesIO(hex_str_to_bytes(txraw))
         txtmp.deserialize(f)
         for j in range(len(txtmp.vout)):
             tx.vin.append(CTxIn(COutPoint(int('0x'+i,0), j)))
     tx.vout.append(CTxOut(0, CScript()))
     tx.rehash()
     signresults = self.nodes[0].signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
     self.nodes[0].sendrawtransaction(signresults, True)
     self.nodes[0].generate(1)
     sync_blocks(self.nodes)
示例#4
0
    def create_tx(self, outpoints, noutput):
        tx = CTransaction()
        total_input = 0
        for parent_tx, n in outpoints:
            tx.vin.append(
                CTxIn(COutPoint(parent_tx.sha256, n), b"", 0xffffffff))
            total_input += parent_tx.vout[n].nValue

        for _ in range(noutput):
            tx.vout.append(
                CTxOut(total_input // noutput - 1000,
                       CScript([b"X" * 200, OP_DROP, OP_TRUE])))

        tx.rehash()
        return tx
示例#5
0
 def create_and_mine_tx_from_txids(self, txids, success = True):
     tx = CTransaction()
     for i in txids:
         txtmp = CTransaction()
         txraw = self.nodes[0].getrawtransaction(i)
         f = BytesIO(hex_str_to_bytes(txraw))
         txtmp.deserialize(f)
         for j in range(len(txtmp.vout)):
             tx.vin.append(CTxIn(COutPoint(int('0x'+i,0), j)))
     tx.vout.append(CTxOut(0, CScript()))
     tx.rehash()
     signresults = self.nodes[0].signrawtransaction(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
     self.nodes[0].sendrawtransaction(signresults, True)
     self.nodes[0].generate(1)
     sync_blocks(self.nodes)
    def test_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())
示例#7
0
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
示例#8
0
    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
示例#9
0
def new_transaction(utxokey, utxo, target_tx_size):
    ndx, tx_to_spend = utxo                
    padding_size = target_tx_size
    while True:
        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, ndx), b''))
        tx.vin[0].scriptSig = b''
        tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2 * target_tx_size, SIMPLE_OUTPUT_SCRIPT))
        tx.vout.append(CTxOut(1, CScript([OP_FALSE,OP_RETURN] + [bytes(1) * padding_size])))
        sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, tx_to_spend.vout[0].nValue)
        sig = utxokey.sign(sighash) + bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
        tx.vin[0].scriptSig = CScript([sig])        
        tx.rehash()

        diff = target_tx_size - len(tx.serialize())
        if diff == 0:
            return tx
        padding_size += diff
示例#10
0
 def create_and_mine_tx_from_txids(self, txids, success=True):
     tx = CTransaction()
     for txid in txids:
         txtmp = CTransaction()
         txraw = self.nodes[0].getrawtransaction(txid)
         f = BytesIO(hex_str_to_bytes(txraw))
         txtmp.deserialize(f)
         for j in range(len(txtmp.vout)):
             tx.vin.append(CTxIn(COutPoint(int('0x' + txid, 0), j)))
     tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
     tx.rehash()
     signresultfull = self.nodes[0].signrawtransaction(
         bytes_to_hex_str(tx.serialize_without_witness()))
     signresult = signresultfull['hex']
     assert_equal(signresultfull['complete'], True)
     self.nodes[0].sendrawtransaction(signresult, True)
     self.nodes[0].generate(1)
     sync_blocks(self.nodes)
示例#11
0
def create_transaction(node, coinbase, to_address, amount, expiry_height):
    from_txid = node.getblock(coinbase)['tx'][0]
    inputs = [{"txid": from_txid, "vout": 0}]
    outputs = {to_address: amount}
    rawtx = node.createrawtransaction(inputs, outputs)
    tx = CTransaction()

    # Set the expiry height
    f = cStringIO.StringIO(unhexlify(rawtx))
    tx.deserialize(f)
    tx.nExpiryHeight = expiry_height
    rawtx = hexlify(tx.serialize())

    signresult = node.signrawtransaction(rawtx)
    f = cStringIO.StringIO(unhexlify(signresult['hex']))
    tx.deserialize(f)
    tx.rehash()
    return tx
def spend_tx_to_data(tx_to_spend, key_for_tx_to_spend):
    "Create and send block with coinbase, returns conbase (tx, key) tuple"
    tx = CTransaction()
    tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, 0), b"", 0xffffffff))

    amount = tx_to_spend.vout[0].nValue - 2000
    tx.vout.append(CTxOut(amount, OP_TRUE_OP_RETURN_SCRIPT))

    sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey, tx, 0,
                                  SIGHASH_ALL | SIGHASH_FORKID,
                                  tx_to_spend.vout[0].nValue)
    tx.vin[0].scriptSig = CScript([
        key_for_tx_to_spend.sign(sighash) +
        bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
    ])

    tx.rehash()
    return tx
示例#13
0
def create_children_txs(parent_tx1, keys1, parent_tx2, keys2, invalidity=None):
    ret = []
    for n, (txout1, key1, txout2, key2) in enumerate(
            zip(parent_tx1.vout, keys1, parent_tx2.vout, keys2)):
        amount1 = txout1.nValue if invalidity == "low_fee" else int(
            0.99 * txout1.nValue)
        amount2 = txout2.nValue if invalidity == "low_fee" else int(
            0.99 * txout2.nValue)

        amount = amount1 + amount2

        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(parent_tx1.sha256, n), b"", 0xffffffff))
        tx.vin.append(CTxIn(COutPoint(parent_tx2.sha256, n), b"", 0xffffffff))

        k = CECKey()
        k.set_secretbytes(b"x" * (n + 1))
        tx.vout.append(CTxOut(amount, CScript([k.get_pubkey(), OP_CHECKSIG])))
        tx.calc_sha256()

        sighash1 = SignatureHashForkId(parent_tx1.vout[n].scriptPubKey, tx, 0,
                                       SIGHASH_ALL | SIGHASH_FORKID,
                                       parent_tx1.vout[n].nValue)
        tx.vin[0].scriptSig = CScript([
            key1.sign(sighash1) +
            bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
        ])

        if invalidity == "bad_signature":
            sighash2 = b"\xff" * 32
        else:
            sighash2 = SignatureHashForkId(parent_tx2.vout[n].scriptPubKey, tx,
                                           1, SIGHASH_ALL | SIGHASH_FORKID,
                                           parent_tx2.vout[n].nValue)

        tx.vin[1].scriptSig = CScript([
            key2.sign(sighash2) +
            bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
        ])

        tx.rehash()
        ret.append(tx)

    return ret
示例#14
0
def make_utxo(node, amount, confirmed=True, script_pub_key=CScript([1])):
    """Create a txout with a given amount and scriptPubKey

    Mines coins as needed.

    confirmed - txouts created will be confirmed in the blockchain;
                unconfirmed otherwise.
    """
    fee = 1 * COIN
    while node.getbalance() < satoshi_round((amount + fee) / COIN):
        node.generate(100)

    new_addr = node.getnewaddress()
    txid = node.sendtoaddress(new_addr, satoshi_round((amount + fee) / COIN))
    tx1 = node.getrawtransaction(txid, 1)
    txid = int(txid, 16)
    i = None

    for i, txout in enumerate(tx1['vout']):
        if txout['scriptPubKey']['addresses'] == [new_addr]:
            break
    assert i is not None

    tx2 = CTransaction()
    tx2.vin = [CTxIn(COutPoint(txid, i))]
    tx2.vout = [CTxOut(amount, script_pub_key)]
    tx2.rehash()

    signed_tx = node.signrawtransaction(tx_to_hex(tx2))

    txid = node.sendrawtransaction(signed_tx['hex'], True)

    # If requested, ensure txouts are confirmed.
    if confirmed:
        mempool_size = len(node.getrawmempool())
        while mempool_size > 0:
            node.generate(1)
            new_size = len(node.getrawmempool())
            # Error out if we have something stuck in the mempool, as this
            # would likely be a bug.
            assert (new_size < mempool_size)
            mempool_size = new_size

    return COutPoint(int(txid, 16), 0)
示例#15
0
 def test_submitbranchblockinfo(self):
     '''
     submitbranchblockinfo "CTransaction hex data"
     Include branch block data to a transaction, then send to main chain
     :return:
     '''
     self.log.info(sys._getframe().f_code.co_name)
     txid = self.node0.sendtoaddress(self.node0.getnewaddress(), 1)
     tx_hex = self.node0.getrawtransaction(txid)
     assert_raises_rpc_error(-32602, 'Invalid transaction data',
                             self.node0.submitbranchblockinfo, tx_hex)
     assert_raises_rpc_error(
         -32602, 'This rpc api can not be called in branch chain',
         self.snode0.submitbranchblockinfo, tx_hex)
     tx = CTransaction()
     tx.nVersion = 9
     tx.rehash()
     assert_raises_rpc_error(-4, 'DecodeHexTx tx hex fail',
                             self.node0.submitbranchblockinfo, tx.hash)
    def create_tx(self,
                  outpoints,
                  noutput,
                  feerate,
                  make_long_eval_script=False):
        """creates p2pk transaction always using the same key (created in constructor), if make_long_eval_script is set
        we are prepending long evaluating script to the locking script
        """
        pre_script = MemepoolAcceptingTransactionsDuringReorg.long_eval_script if make_long_eval_script else []

        tx = CTransaction()
        total_input = 0
        for parent_tx, n in outpoints:
            tx.vin.append(
                CTxIn(COutPoint(parent_tx.sha256, n), CScript([b"0" * 72]),
                      0xffffffff))
            total_input += parent_tx.vout[n].nValue

        for _ in range(noutput):
            tx.vout.append(
                CTxOut(total_input // noutput,
                       CScript(pre_script + [self.public_key, OP_CHECKSIG])))

        tx.rehash()

        tx_size = len(tx.serialize())
        fee_per_output = int(tx_size * feerate // noutput)

        for output in tx.vout:
            output.nValue -= fee_per_output

        for input, (parent_tx, n) in zip(tx.vin, outpoints):
            sighash = SignatureHashForkId(parent_tx.vout[n].scriptPubKey, tx,
                                          0, SIGHASH_ALL | SIGHASH_FORKID,
                                          parent_tx.vout[n].nValue)
            input.scriptSig = CScript([
                self.private_key.sign(sighash) +
                bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
            ])

        tx.rehash()
        return tx
示例#17
0
    def create_tx(self, outpoints, noutput, feerate):
        tx = CTransaction()
        total_input = 0
        for parent_tx, n in outpoints:
            tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, n), b"", 0xffffffff))
            total_input += parent_tx.vout[n].nValue

        for _ in range(noutput):
            tx.vout.append(CTxOut(total_input//noutput, CScript([b"X"*200, OP_DROP, OP_TRUE])))

        tx.rehash()

        tx_size = len(tx.serialize())
        fee_per_output = int(tx_size * feerate // noutput)

        for output in tx.vout:
            output.nValue -= fee_per_output

        tx.rehash()
        return tx
    def create_tx(self,
                  outpoints,
                  noutput,
                  feerate,
                  totalSize=0,
                  size_of_nonpayin_txs=0):
        tx = CTransaction()
        total_input = 0
        for parent_tx, n in outpoints:
            tx.vin.append(
                CTxIn(COutPoint(parent_tx.sha256, n), b"", 0xffffffff))
            total_input += parent_tx.vout[n].nValue

        for _ in range(noutput):
            tx.vout.append(CTxOut(total_input // noutput, CScript([OP_TRUE])))

        if totalSize:
            tx.rehash()
            missingSize = totalSize - self.tx_size(tx)
            assert missingSize >= 0
            tx.vout[0].scriptPubKey = CScript(
                [b"X" * (missingSize - 10), OP_DROP, OP_TRUE])

        tx.rehash()
        overall_size = self.tx_size(tx) + size_of_nonpayin_txs
        fee_per_output = ceil(overall_size * feerate / noutput)

        for output in tx.vout:
            output.nValue -= fee_per_output

        tx.rehash()
        return 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
示例#20
0
    def run_test(self):
        self.log.info("Mining blocks...")
        self.nodes[0].generate(105)
        self.sync_all()

        chain_height = self.nodes[1].getblockcount()
        assert_equal(chain_height, 105)

        self.log.info("Testing transaction index...")

        #privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
        #address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
        address_hash = bytes([
            11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190,
            49, 25, 70, 218, 220
        ])
        script_pub_key = CScript(
            [OP_DUP, OP_HASH160, address_hash, OP_EQUALVERIFY, OP_CHECKSIG])
        unspent = self.nodes[0].listunspent()
        tx = CTransaction()
        amount = int(unspent[0]["amount"] * 10000000)
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        tx.vout = [CTxOut(amount, script_pub_key)]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()

        # Check verbose raw transaction results
        verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1)
        assert_equal(verbose["vout"][0]["valueSat"], 500000000000)
        assert_equal(verbose["vout"][0]["value"], 5000)

        self.log.info("All Tests Passed")
    def make_utxos(self):
        # Doesn't matter which node we use, just use node0.
        block = self.build_block_on_tip(self.nodes[0])
        self.test_node.send_and_ping(MsgBlock(block))
        assert (int(self.nodes[0].getbestblockhash(), 16) == block.sha256)
        self.nodes[0].generate(100)

        total_value = block.vtx[0].vout[0].nValue
        out_value = total_value // 10
        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b''))
        for _ in range(10):
            tx.vout.append(CTxOut(out_value, CScript([OP_TRUE])))
        tx.rehash()

        block2 = self.build_block_on_tip(self.nodes[0])
        block2.vtx.append(tx)
        block2.hashMerkleRoot = block2.calc_merkle_root()
        block2.solve()
        self.test_node.send_and_ping(MsgBlock(block2))
        assert_equal(int(self.nodes[0].getbestblockhash(), 16), block2.sha256)
        self.utxos.extend([[tx.x16r, i, out_value] for i in range(10)])
        return
示例#22
0
def spend_separator_tx(tx_sep_tx, keys_for_sep_tx):
    """spends Transaction with scriptPubKey in form of:
    <pk1> OP_CHECKSIGVERIFY OP_CODESEPARATOR <pk2> OP_CHECKSIGVERIFY OP_CODESEPARATOR ... <pk N_signings> OP_CHECKSIG
    """

    tx = CTransaction()

    tx.vin.append(CTxIn(COutPoint(tx_sep_tx.sha256, 0), b"", 0xffffffff))

    k = CECKey()
    k.set_secretbytes(b"horsebattery")

    amount = tx_sep_tx.vout[0].nValue - 2000

    script_lists = [[]]

    for item in list(tx_sep_tx.vout[0].scriptPubKey):
        for l in script_lists:
            l.append(item)
        if item == OP_CODESEPARATOR:
            script_lists.append([])

    tx.vout.append(CTxOut(amount, CScript([k.get_pubkey(), OP_CHECKSIG])))

    flags = bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))

    sign_list = []
    for sc, key in zip(script_lists, keys_for_sep_tx):
        sighash = SignatureHashForkId(CScript(sc), tx, 0,
                                      SIGHASH_ALL | SIGHASH_FORKID,
                                      tx_sep_tx.vout[0].nValue)
        sign_list.append(key.sign(sighash) + flags)

    tx.vin[0].scriptSig = CScript(reversed(sign_list))
    tx.rehash()
    return tx, k
    def prepare_for_test(self, height, label, coinbases, connections):
        transactions = []
        n_generated_utxos = 0
        while n_generated_utxos < self._NUMBER_OF_UTXOS_PER_HEIGHT:
            tx_to_spend = coinbases()

            tx = CTransaction()
            transactions.append(tx)
            tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, 0), b''))

            locking_key = self._UTXO_KEY
            cscript = CScript([locking_key.get_pubkey(), OP_CHECKSIG
                               ]) if locking_key else CScript([OP_TRUE])
            for x in range(24):
                coinbaseoutput = CTxOut(2 * COIN, cscript)
                tx.vout.append(coinbaseoutput)
                n_generated_utxos += 1

            if self.COINBASE_KEY:
                tx.rehash()
                sighash = SignatureHashForkId(tx_to_spend.vout[0].scriptPubKey,
                                              tx, 0,
                                              SIGHASH_ALL | SIGHASH_FORKID,
                                              tx_to_spend.vout[0].nValue)
                sig = self._coinbase_key.sign(sighash) + bytes(
                    bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
                tx.vin[0].scriptSig = CScript([sig])
            else:
                tx.vin[0].scriptSig = CScript([OP_TRUE])

            tx.rehash()
            self.log.info(
                f"Created UTXO Tx {loghash(tx.hash)} with {n_generated_utxos} outputs"
            )

        return transactions, None
def make_invalid_p2sh_tx(tx_to_spend, output_ndx):
    tx = CTransaction()
    tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, output_ndx), b"", 0xffffffff))
    tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2000, CScript([OP_HASH160, hash160(b'123'), OP_EQUAL])))
    tx.rehash()
    return tx
示例#25
0
    def run_test(self):
        print "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)

        addr1 = "zrCBKy4Uoy1X5jws6cxLqrMuE1ukuctSqfS"
        addr2 = "ztano5XjpquCJdSipz7VRGFgdLqNjXmV9cD"

        # Check that balances are correct
        balance0 = self.nodes[1].getaddressbalance(addr1)
        assert_equal(balance0["balance"], 0)

        # Check p2pkh and p2sh address indexes
        print "Testing p2pkh and p2sh address index..."

        txid0 = self.nodes[0].sendtoaddress(addr2, 10)
        self.nodes[0].generate(1)

        txidb0 = self.nodes[0].sendtoaddress(addr1, 10)
        self.nodes[0].generate(1)

        txid1 = self.nodes[0].sendtoaddress(addr2, 15)
        self.nodes[0].generate(1)

        txidb1 = self.nodes[0].sendtoaddress(addr1, 15)
        self.nodes[0].generate(1)

        txid2 = self.nodes[0].sendtoaddress(addr2, 20)
        self.nodes[0].generate(1)

        txidb2 = self.nodes[0].sendtoaddress(addr1, 20)
        self.nodes[0].generate(1)

        self.sync_all()

        txids = self.nodes[1].getaddresstxids(addr2)
        assert_equal(len(txids), 3)
        assert_equal(txids[0], txid0)
        assert_equal(txids[1], txid1)
        assert_equal(txids[2], txid2)

        txidsb = self.nodes[1].getaddresstxids(addr1)
        assert_equal(len(txidsb), 3)
        assert_equal(txidsb[0], txidb0)
        assert_equal(txidsb[1], txidb1)
        assert_equal(txidsb[2], txidb2)

        # Check that limiting by height works
        print "Testing querying txids by range of block heights.."
        height_txids = self.nodes[1].getaddresstxids({
            "addresses": [addr1],
            "start": 105,
            "end": 110
        })
        assert_equal(len(height_txids), 2)
        assert_equal(height_txids[0], txidb0)
        assert_equal(height_txids[1], txidb1)

        # Check that multiple addresses works
        multitxids = self.nodes[1].getaddresstxids(
            {"addresses": [addr1, addr2]})
        assert_equal(len(multitxids), 6)
        assert_equal(multitxids[0], txid0)
        assert_equal(multitxids[1], txidb0)
        assert_equal(multitxids[2], txid1)
        assert_equal(multitxids[3], txidb1)
        assert_equal(multitxids[4], txid2)
        assert_equal(multitxids[5], txidb2)

        # Check that balances are correct
        balance0 = self.nodes[1].getaddressbalance(addr1)
        assert_equal(balance0["balance"], 45 * 100000000)

        # Check that outputs with the same address will only return one txid
        print "Testing for txid uniqueness..."
        op_hash160 = "a9"
        op_push_20_bytes_onto_the_stack = "14"
        addressHash = "6349a418fc4578d10a372b54b45c280cc8c4382f"
        op_equal = "87"
        genesisCbah = "20bb1acf2c1fc1228967a611c7db30632098f0c641855180b5fe23793b72eea50d00b4"
        scriptPubKey = binascii.unhexlify(op_hash160 +
                                          op_push_20_bytes_onto_the_stack +
                                          addressHash + op_equal + genesisCbah)
        unspent = self.nodes[0].listunspent()
        unspent.sort(key=lambda x: x["amount"], reverse=True)
        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        tx.vout = [CTxOut(10, scriptPubKey), CTxOut(11, scriptPubKey)]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)

        self.nodes[0].generate(1)
        self.sync_all()

        txidsmany = self.nodes[1].getaddresstxids(addr1)
        assert_equal(len(txidsmany), 4)
        assert_equal(txidsmany[3], sent_txid)

        # Check that balances are correct
        print "Testing balances..."
        balance0 = self.nodes[1].getaddressbalance(addr1)
        assert_equal(balance0["balance"], 45 * 100000000 + 21)

        # Check that balances are correct after spending
        print "Testing balances after spending..."
        privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
        address2 = "ztUB6YWTcj2uUe5Rbucnc7oFevn7wCKyN63"
        op_dup = "76"
        addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc"
        op_equalverify = "88"
        op_checksig = "ac"
        scriptPubKey2 = binascii.unhexlify(op_dup + op_hash160 +
                                           op_push_20_bytes_onto_the_stack +
                                           addressHash2 + op_equalverify +
                                           op_checksig + genesisCbah)
        self.nodes[0].importprivkey(privkey2)

        unspent = self.nodes[0].listunspent()
        unspent.sort(key=lambda x: x["amount"], reverse=True)
        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        amount = unspent[0]["amount"] * 100000000
        tx.vout = [CTxOut(amount, scriptPubKey2)]
        tx.rehash()
        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        spending_txid = self.nodes[0].sendrawtransaction(
            signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()
        balance1 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance1["balance"], amount)

        tx = CTransaction()
        tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))]
        send_amount = 1 * 100000000 + 12840
        change_amount = amount - send_amount - 10000
        tx.vout = [
            CTxOut(change_amount, scriptPubKey2),
            CTxOut(send_amount, scriptPubKey)
        ]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()

        balance2 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance2["balance"], change_amount)

        # Check that deltas are returned correctly
        deltas = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start": 1,
            "end": 200
        })
        balance3 = 0
        for delta in deltas:
            balance3 += delta["satoshis"]
        assert_equal(balance3, change_amount)
        assert_equal(deltas[0]["address"], address2)
        assert_equal(deltas[0]["blockindex"], 1)

        # Check that entire range will be queried
        deltasAll = self.nodes[1].getaddressdeltas({"addresses": [address2]})
        assert_equal(len(deltasAll), len(deltas))

        # Check that deltas can be returned from range of block heights
        deltas = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start": 113,
            "end": 113
        })
        assert_equal(len(deltas), 1)

        # Check that unspent outputs can be queried
        print "Testing utxos..."
        utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos), 1)
        assert_equal(utxos[0]["satoshis"], change_amount)

        # Check that indexes will be updated with a reorg
        print "Testing reorg..."

        best_hash = self.nodes[0].getbestblockhash()
        self.nodes[0].invalidateblock(best_hash)
        self.nodes[1].invalidateblock(best_hash)
        self.nodes[2].invalidateblock(best_hash)
        self.nodes[3].invalidateblock(best_hash)
        self.sync_all()

        balance4 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance4, balance1)

        utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos2), 1)
        assert_equal(utxos2[0]["satoshis"], amount)

        # Check sorting of utxos
        self.nodes[2].generate(150)

        self.nodes[2].sendtoaddress(address2, 50)
        self.nodes[2].generate(1)
        self.nodes[2].sendtoaddress(address2, 50)
        self.nodes[2].generate(1)
        self.sync_all()

        utxos3 = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos3), 3)
        assert_equal(utxos3[0]["height"], 114)
        assert_equal(utxos3[1]["height"], 264)
        assert_equal(utxos3[2]["height"], 265)

        # Check mempool indexing
        print "Testing mempool indexing..."

        privKey3 = "cVfUn53hAbRrDEuMexyfgDpZPhF7KqXpS8UZevsyTDaugB7HZ3CD"
        address3 = "ztihzFwiPbcoMVWzvMAHf37o8jw9VSHdLtC"
        addressHash3 = "aa9872b5bbcdb511d89e0e11aa27da73fd2c3f50"
        scriptPubKey3 = binascii.unhexlify(op_dup + op_hash160 +
                                           op_push_20_bytes_onto_the_stack +
                                           addressHash3 + op_equalverify +
                                           op_checksig + genesisCbah)
        #address4 = "zrJgNMHvfLY26avAQCeHk8NAQxubq7CExqH"
        scriptPubKey4 = binascii.unhexlify(op_hash160 +
                                           op_push_20_bytes_onto_the_stack +
                                           addressHash3 + op_equal +
                                           genesisCbah)
        unspent = self.nodes[2].listunspent()
        unspent.sort(key=lambda x: x["amount"], reverse=True)

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        amount = unspent[0]["amount"] * 100000000
        tx.vout = [CTxOut(amount, scriptPubKey3)]
        tx.rehash()
        signed_tx = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        memtxid1 = self.nodes[2].sendrawtransaction(signed_tx["hex"], True)
        time.sleep(2)

        tx2 = CTransaction()
        tx2.vin = [
            CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))
        ]
        amount = unspent[1]["amount"] * 100000000
        tx2.vout = [
            CTxOut(amount / 4, scriptPubKey3),
            CTxOut(amount / 4, scriptPubKey3),
            CTxOut(amount / 4, scriptPubKey4),
            CTxOut(amount / 4, scriptPubKey4)
        ]
        tx2.rehash()
        signed_tx2 = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx2.serialize()).decode("utf-8"))
        memtxid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True)
        time.sleep(2)

        mempool = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool), 3)
        assert_equal(mempool[0]["txid"], memtxid1)
        assert_equal(mempool[0]["address"], address3)
        assert_equal(mempool[0]["index"], 0)
        assert_equal(mempool[1]["txid"], memtxid2)
        assert_equal(mempool[1]["index"], 0)
        assert_equal(mempool[2]["txid"], memtxid2)
        assert_equal(mempool[2]["index"], 1)

        self.nodes[2].generate(1)
        self.sync_all()
        mempool2 = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool2), 0)

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(memtxid2, 16), 0)),
            CTxIn(COutPoint(int(memtxid2, 16), 1))
        ]
        tx.vout = [CTxOut(amount / 2 - 10000, scriptPubKey2)]
        tx.rehash()
        self.nodes[2].importprivkey(privKey3)
        signed_tx3 = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[2].sendrawtransaction(signed_tx3["hex"], True)
        time.sleep(2)

        mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool3), 2)
        assert_equal(mempool3[0]["prevtxid"], memtxid2)
        assert_equal(mempool3[0]["prevout"], 0)
        assert_equal(mempool3[1]["prevtxid"], memtxid2)
        assert_equal(mempool3[1]["prevout"], 1)

        # sending and receiving to the same address
        privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8"
        address1 = "ztkoUySJkS8SMoQEjR6SkSgmDXtMB531yiw"
        address1hash = "c192bff751af8efec15135d42bfeedf91a6f3e34"
        address1script = binascii.unhexlify(op_dup + op_hash160 +
                                            op_push_20_bytes_onto_the_stack +
                                            address1hash + op_equalverify +
                                            op_checksig + genesisCbah)

        self.nodes[0].sendtoaddress(address1, 10)
        self.nodes[0].generate(1)
        self.sync_all()

        utxos = self.nodes[1].getaddressutxos({"addresses": [address1]})
        assert_equal(len(utxos), 1)

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(utxos[0]["txid"], 16),
                            utxos[0]["outputIndex"]))
        ]
        amount = utxos[0]["satoshis"] - 1000
        tx.vout = [CTxOut(amount, address1script)]
        tx.rehash()
        self.nodes[0].importprivkey(privkey1)
        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[0].sendrawtransaction(signed_tx["hex"], True)

        self.sync_all()
        mempool_deltas = self.nodes[2].getaddressmempool(
            {"addresses": [address1]})
        assert_equal(len(mempool_deltas), 2)

        # Include chaininfo in results
        print "Testing results with chain info..."

        deltas_with_info = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start":
            1,
            "end":
            200,
            "chainInfo":
            True
        })
        start_block_hash = self.nodes[1].getblockhash(1)
        end_block_hash = self.nodes[1].getblockhash(200)
        assert_equal(deltas_with_info["start"]["height"], 1)
        assert_equal(deltas_with_info["start"]["hash"], start_block_hash)
        assert_equal(deltas_with_info["end"]["height"], 200)
        assert_equal(deltas_with_info["end"]["hash"], end_block_hash)

        utxos_with_info = self.nodes[1].getaddressutxos({
            "addresses": [address2],
            "chainInfo": True
        })
        expected_tip_block_hash = self.nodes[1].getblockhash(267)
        assert_equal(utxos_with_info["height"], 267)
        assert_equal(utxos_with_info["hash"], expected_tip_block_hash)

        # Check that indexes don't get updated when checking a new block (e.g. when calling getBlockTemplate)

        # Initial balance is 0 and no index has been stored for addr3
        addr3 = self.nodes[1].getnewaddress()
        addr3_balance = self.nodes[2].getaddressbalance(addr3)
        addr3_txs = self.nodes[2].getaddresstxids(addr3)
        addr3_utxos = self.nodes[2].getaddressutxos(addr3)
        addr3_mempool = self.nodes[2].getaddressmempool(addr3)

        # The initial balance must be 0
        assert_equal(addr3_balance["balance"], 0)

        # At the beginning no address index must be stored
        assert_equal(addr3_txs, [])

        # At the beginning no unspent index must be stored
        assert_equal(addr3_utxos, [])

        # At the beginning no address mempool index must be stored
        assert_equal(addr3_mempool, [])

        # Add to mempool a transaction that sends money to addr3
        addr3_amount = 0.1
        addr3_txid = self.nodes[2].sendtoaddress(addr3, addr3_amount)
        addr3_balance = self.nodes[2].getaddressbalance(addr3)
        addr3_txs = self.nodes[2].getaddresstxids(addr3)
        addr3_utxos = self.nodes[2].getaddressutxos(addr3)
        addr3_mempool = self.nodes[2].getaddressmempool(addr3)

        # The balance must still be 0
        assert_equal(addr3_balance["balance"], 0)

        # The address index must still be empty
        assert_equal(addr3_txs, [])

        # The unspent index must still be empty
        assert_equal(addr3_utxos, [])

        # The address mempool index must contain the new transaction
        assert_equal(len(addr3_mempool), 1)
        assert_equal(addr3_mempool[0]["txid"], addr3_txid)

        # Call getBlockTemplate to trigger a call to VerifyBlock() => ConnectBlock()
        # It should not update any index
        self.nodes[2].getblocktemplate()
        addr3_balance = self.nodes[2].getaddressbalance(addr3)
        addr3_txs = self.nodes[2].getaddresstxids(addr3)
        addr3_utxos = self.nodes[2].getaddressutxos(addr3)
        addr3_mempool = self.nodes[2].getaddressmempool(addr3)

        # The balance must still be 0
        assert_equal(addr3_balance["balance"], 0)

        # The address index must still be empty
        assert_equal(addr3_txs, [])

        # The unspent index must still be empty
        assert_equal(addr3_utxos, [])

        # The address mempool index must still be empty
        assert_equal(len(addr3_mempool), 1)
        assert_equal(addr3_mempool[0]["txid"], addr3_txid)

        # Connect a new block "validating" the transaction sending money to addr3
        self.nodes[2].generate(1)
        self.sync_all()
        addr3_balance = self.nodes[2].getaddressbalance(addr3)
        addr3_txs = self.nodes[2].getaddresstxids(addr3)
        addr3_utxos = self.nodes[2].getaddressutxos(addr3)
        addr3_mempool = self.nodes[2].getaddressmempool(addr3)

        # The balance must be updated
        assert_equal(addr3_balance["balance"], 0.1 * 1e8)

        # The address index must contain only the new transaction
        assert_equal(len(addr3_txs), 1)
        assert_equal(addr3_txs[0], addr3_txid)

        # The unspent index must contain only the new transaction
        assert_equal(len(addr3_utxos), 1)
        assert_equal(addr3_utxos[0]["txid"], addr3_txid)

        # The address mempool index must be empty again
        assert_equal(addr3_mempool, [])

        print "Passed\n"
    def run_test(self):
        self.log.info("Mining blocks...")
        self.nodes[0].generate(105)
        self.sync_all()

        chain_height = self.nodes[1].getblockcount()
        assert_equal(chain_height, 105)
        assert_equal(self.nodes[1].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 0)

        # Check that balances are correct
        balance0 = self.nodes[1].getaddressbalance(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
        assert_equal(balance0["balance"], 0)

        # Check p2pkh and p2sh address indexes
        self.log.info("Testing p2pkh and p2sh address index...")

        tx_id0 = self.nodes[0].sendtoaddress(
            "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 10)
        self.nodes[0].generate(1)

        tx_idb0 = self.nodes[0].sendtoaddress(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 10)
        self.nodes[0].generate(1)

        tx_id1 = self.nodes[0].sendtoaddress(
            "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 15)
        self.nodes[0].generate(1)

        tx_idb1 = self.nodes[0].sendtoaddress(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 15)
        self.nodes[0].generate(1)

        tx_id2 = self.nodes[0].sendtoaddress(
            "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 20)
        self.nodes[0].generate(1)

        tx_idb2 = self.nodes[0].sendtoaddress(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 20)
        self.nodes[0].generate(1)

        self.sync_all()

        txids = self.nodes[1].getaddresstxids(
            "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs")
        assert_equal(len(txids), 3)
        assert_equal(txids[0], tx_id0)
        assert_equal(txids[1], tx_id1)
        assert_equal(txids[2], tx_id2)

        tx_idsb = self.nodes[1].getaddresstxids(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
        assert_equal(len(tx_idsb), 3)
        assert_equal(tx_idsb[0], tx_idb0)
        assert_equal(tx_idsb[1], tx_idb1)
        assert_equal(tx_idsb[2], tx_idb2)

        # Check that limiting by height works
        self.log.info("Testing querying txids by range of block heights..")
        height_txids = self.nodes[1].getaddresstxids({
            "addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br"],
            "start":
            105,
            "end":
            110
        })
        assert_equal(len(height_txids), 2)
        assert_equal(height_txids[0], tx_idb0)
        assert_equal(height_txids[1], tx_idb1)

        # Check that multiple addresses works
        multi_tx_ids = self.nodes[1].getaddresstxids({
            "addresses": [
                "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
                "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs"
            ]
        })
        assert_equal(len(multi_tx_ids), 6)
        assert_equal(multi_tx_ids[0], tx_id0)
        assert_equal(multi_tx_ids[1], tx_idb0)
        assert_equal(multi_tx_ids[2], tx_id1)
        assert_equal(multi_tx_ids[3], tx_idb1)
        assert_equal(multi_tx_ids[4], tx_id2)
        assert_equal(multi_tx_ids[5], tx_idb2)

        # Check that balances are correct
        balance0 = self.nodes[1].getaddressbalance(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
        assert_equal(balance0["balance"], 45 * 100000000)

        # Check that outputs with the same address will only return one txid
        self.log.info("Testing for txid uniqueness...")
        address_hash = bytes([
            99, 73, 164, 24, 252, 69, 120, 209, 10, 55, 43, 84, 180, 92, 40,
            12, 200, 196, 56, 47
        ])
        script_pub_key = CScript([OP_HASH160, address_hash, OP_EQUAL])
        unspent = self.nodes[0].listunspent()
        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        tx.vout = [CTxOut(10, script_pub_key), CTxOut(11, script_pub_key)]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)

        self.nodes[0].generate(1)
        self.sync_all()

        tx_ids_many = self.nodes[1].getaddresstxids(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
        assert_equal(len(tx_ids_many), 4)
        assert_equal(tx_ids_many[3], sent_txid)

        # Check that balances are correct
        self.log.info("Testing balances...")
        balance0 = self.nodes[1].getaddressbalance(
            "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
        assert_equal(balance0["balance"], 45 * 100000000 + 21)

        # Check that balances are correct after spending
        self.log.info("Testing balances after spending...")
        privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
        address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
        address_hash2 = bytes([
            11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190,
            49, 25, 70, 218, 220
        ])
        script_pub_key2 = CScript(
            [OP_DUP, OP_HASH160, address_hash2, OP_EQUALVERIFY, OP_CHECKSIG])
        self.nodes[0].importprivkey(privkey2)

        unspent = self.nodes[0].listunspent()
        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        amount = int(unspent[0]["amount"] * 100000000 - 230000)
        tx.vout = [CTxOut(amount, script_pub_key2)]
        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        spending_txid = self.nodes[0].sendrawtransaction(
            signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()
        balance1 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance1["balance"], amount)

        tx = CTransaction()
        tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))]
        send_amount = 1 * 100000000 + 12840
        change_amount = amount - send_amount - 230000
        tx.vout = [
            CTxOut(change_amount, script_pub_key2),
            CTxOut(send_amount, script_pub_key)
        ]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()

        balance2 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance2["balance"], change_amount)

        # Check that deltas are returned correctly
        deltas = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start": 1,
            "end": 200
        })
        balance3 = 0
        for delta in deltas:
            balance3 += delta["satoshis"]
        assert_equal(balance3, change_amount)
        assert_equal(deltas[0]["address"], address2)
        assert_equal(deltas[0]["blockindex"], 1)

        # Check that entire range will be queried
        deltas_all = self.nodes[1].getaddressdeltas({"addresses": [address2]})
        assert_equal(len(deltas_all), len(deltas))

        # Check that deltas can be returned from range of block heights
        deltas = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start": 113,
            "end": 113
        })
        assert_equal(len(deltas), 1)

        # Check that unspent outputs can be queried
        self.log.info("Testing utxos...")
        utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos), 1)
        assert_equal(utxos[0]["satoshis"], change_amount)

        # Check that indexes will be updated with a reorg
        self.log.info("Testing reorg...")

        best_hash = self.nodes[0].getbestblockhash()
        self.nodes[0].invalidateblock(best_hash)
        self.nodes[1].invalidateblock(best_hash)
        self.nodes[2].invalidateblock(best_hash)
        self.nodes[3].invalidateblock(best_hash)
        self.sync_all()

        balance4 = self.nodes[1].getaddressbalance(address2)
        assert_equal(balance4, balance1)

        utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos2), 1)
        assert_equal(utxos2[0]["satoshis"], amount)

        # Check sorting of utxos
        self.nodes[2].generate(150)

        self.nodes[2].sendtoaddress(address2, 50)
        self.nodes[2].generate(1)
        self.nodes[2].sendtoaddress(address2, 50)
        self.nodes[2].generate(1)
        self.sync_all()

        utxos3 = self.nodes[1].getaddressutxos({"addresses": [address2]})
        assert_equal(len(utxos3), 3)
        assert_equal(utxos3[0]["height"], 114)
        assert_equal(utxos3[1]["height"], 264)
        assert_equal(utxos3[2]["height"], 265)

        # Check mempool indexing
        self.log.info("Testing mempool indexing...")

        priv_key3 = "cVfUn53hAbRrDEuMexyfgDpZPhF7KqXpS8UZevsyTDaugB7HZ3CD"
        address3 = "mw4ynwhS7MmrQ27hr82kgqu7zryNDK26JB"
        address_hash3 = bytes([
            170, 152, 114, 181, 187, 205, 181, 17, 216, 158, 14, 17, 170, 39,
            218, 115, 253, 44, 63, 80
        ])
        script_pub_key3 = CScript(
            [OP_DUP, OP_HASH160, address_hash3, OP_EQUALVERIFY, OP_CHECKSIG])
        #address4 = "2N8oFVB2vThAKury4vnLquW2zVjsYjjAkYQ"
        script_pub_key4 = CScript([OP_HASH160, address_hash3, OP_EQUAL])
        unspent = self.nodes[2].listunspent()

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        amount = int(unspent[0]["amount"] * 100000000 - 230000)
        tx.vout = [CTxOut(amount, script_pub_key3)]
        tx.rehash()
        signed_tx = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        mem_txid1 = self.nodes[2].sendrawtransaction(signed_tx["hex"], True)
        time.sleep(2)

        tx2 = CTransaction()
        tx2.vin = [
            CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))
        ]
        amount = int(unspent[1]["amount"] * 100000000 - 300000)
        tx2.vout = [
            CTxOut(int(amount / 4), script_pub_key3),
            CTxOut(int(amount / 4), script_pub_key3),
            CTxOut(int(amount / 4), script_pub_key4),
            CTxOut(int(amount / 4), script_pub_key4)
        ]
        tx2.rehash()
        signed_tx2 = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx2.serialize()).decode("utf-8"))
        mem_txid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True)
        time.sleep(2)

        mempool = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool), 3)
        assert_equal(mempool[0]["txid"], mem_txid1)
        assert_equal(mempool[0]["address"], address3)
        assert_equal(mempool[0]["index"], 0)
        assert_equal(mempool[1]["txid"], mem_txid2)
        assert_equal(mempool[1]["index"], 0)
        assert_equal(mempool[2]["txid"], mem_txid2)
        assert_equal(mempool[2]["index"], 1)

        self.nodes[2].generate(1)
        self.sync_all()
        mempool2 = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool2), 0)

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(mem_txid2, 16), 0)),
            CTxIn(COutPoint(int(mem_txid2, 16), 1))
        ]
        tx.vout = [CTxOut(int(amount / 2 - 340000), script_pub_key2)]
        tx.rehash()
        self.nodes[2].importprivkey(priv_key3)
        signed_tx3 = self.nodes[2].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[2].sendrawtransaction(signed_tx3["hex"], True)
        time.sleep(2)

        mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]})
        assert_equal(len(mempool3), 2)
        assert_equal(mempool3[0]["prevtxid"], mem_txid2)
        assert_equal(mempool3[0]["prevout"], 0)
        assert_equal(mempool3[1]["prevtxid"], mem_txid2)
        assert_equal(mempool3[1]["prevout"], 1)

        # sending and receiving to the same address
        privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8"
        address1 = "myAUWSHnwsQrhuMWv4Br6QsCnpB41vFwHn"
        address1hash = bytes([
            193, 146, 191, 247, 81, 175, 142, 254, 193, 81, 53, 212, 43, 254,
            237, 249, 26, 111, 62, 52
        ])
        address1script = CScript(
            [OP_DUP, OP_HASH160, address1hash, OP_EQUALVERIFY, OP_CHECKSIG])

        self.nodes[0].sendtoaddress(address1, 10)
        self.nodes[0].generate(1)
        self.sync_all()

        utxos = self.nodes[1].getaddressutxos({"addresses": [address1]})
        assert_equal(len(utxos), 1)

        tx = CTransaction()
        tx.vin = [
            CTxIn(COutPoint(int(utxos[0]["txid"], 16),
                            utxos[0]["outputIndex"]))
        ]
        amount = int(utxos[0]["satoshis"] - 200000)
        tx.vout = [CTxOut(amount, address1script)]
        tx.rehash()
        self.nodes[0].importprivkey(privkey1)
        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        self.nodes[0].sendrawtransaction(signed_tx["hex"], True)

        self.sync_all()
        mempool_deltas = self.nodes[2].getaddressmempool(
            {"addresses": [address1]})
        assert_equal(len(mempool_deltas), 2)

        # Include chaininfo in results
        self.log.info("Testing results with chain info...")

        deltas_with_info = self.nodes[1].getaddressdeltas({
            "addresses": [address2],
            "start":
            1,
            "end":
            200,
            "chainInfo":
            True
        })
        start_block_hash = self.nodes[1].getblockhash(1)
        end_block_hash = self.nodes[1].getblockhash(200)
        assert_equal(deltas_with_info["start"]["height"], 1)
        assert_equal(deltas_with_info["start"]["hash"], start_block_hash)
        assert_equal(deltas_with_info["end"]["height"], 200)
        assert_equal(deltas_with_info["end"]["hash"], end_block_hash)

        utxos_with_info = self.nodes[1].getaddressutxos({
            "addresses": [address2],
            "chainInfo": True
        })
        expected_tip_block_hash = self.nodes[1].getblockhash(267)
        assert_equal(utxos_with_info["height"], 267)
        assert_equal(utxos_with_info["hash"], expected_tip_block_hash)

        self.log.info("All Tests Passed")
示例#27
0
    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
示例#28
0
    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)

        # Check that
        self.log.info("Testing spent index...")

        fee_satoshis = 192000
        privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
        #address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
        address_hash = bytes([
            11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190,
            49, 25, 70, 218, 220
        ])
        script_pub_key = CScript(
            [OP_DUP, OP_HASH160, address_hash, OP_EQUALVERIFY, OP_CHECKSIG])
        unspent = self.nodes[0].listunspent()
        tx = CTransaction()
        amount = int(unspent[0]["amount"] * 100000000 - fee_satoshis)
        tx.vin = [
            CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))
        ]
        tx.vout = [CTxOut(amount, script_pub_key)]
        tx.rehash()

        signed_tx = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx.serialize()).decode("utf-8"))
        txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
        self.nodes[0].generate(1)
        self.sync_all()

        self.log.info("Testing getspentinfo method...")

        # Check that the spentinfo works standalone
        info = self.nodes[1].getspentinfo({
            "txid": unspent[0]["txid"],
            "index": unspent[0]["vout"]
        })
        assert_equal(info["txid"], txid)
        assert_equal(info["index"], 0)
        assert_equal(info["height"], 106)

        self.log.info("Testing getrawtransaction method...")

        # Check that verbose raw transaction includes spent info
        tx_verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1)
        assert_equal(tx_verbose["vout"][unspent[0]["vout"]]["spentTxId"], txid)
        assert_equal(tx_verbose["vout"][unspent[0]["vout"]]["spentIndex"], 0)
        assert_equal(tx_verbose["vout"][unspent[0]["vout"]]["spentHeight"],
                     106)

        # Check that verbose raw transaction includes input values
        tx_verbose2 = self.nodes[3].getrawtransaction(txid, 1)
        assert_equal(float(tx_verbose2["vin"][0]["value"]),
                     (amount + fee_satoshis) / 100000000)
        assert_equal(tx_verbose2["vin"][0]["valueSat"], amount + fee_satoshis)

        # Check that verbose raw transaction includes address values and input values
        #privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
        address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
        address_hash2 = bytes([
            11, 47, 10, 12, 49, 191, 224, 64, 107, 12, 204, 19, 129, 253, 190,
            49, 25, 70, 218, 220
        ])
        script_pub_key2 = CScript(
            [OP_DUP, OP_HASH160, address_hash2, OP_EQUALVERIFY, OP_CHECKSIG])
        tx2 = CTransaction()
        tx2.vin = [CTxIn(COutPoint(int(txid, 16), 0))]
        amount = int(amount - fee_satoshis)
        tx2.vout = [CTxOut(amount, script_pub_key2)]
        tx.rehash()
        self.nodes[0].importprivkey(privkey)
        signed_tx2 = self.nodes[0].signrawtransaction(
            binascii.hexlify(tx2.serialize()).decode("utf-8"))
        txid2 = self.nodes[0].sendrawtransaction(signed_tx2["hex"], True)

        # Check the mempool index
        self.sync_all()
        tx_verbose3 = self.nodes[1].getrawtransaction(txid2, 1)
        assert_equal(tx_verbose3["vin"][0]["address"], address2)
        assert_equal(tx_verbose3["vin"][0]["valueSat"], amount + fee_satoshis)
        assert_equal(float(tx_verbose3["vin"][0]["value"]),
                     (amount + fee_satoshis) / 100000000)

        # Check the database index
        block_hash = self.nodes[0].generate(1)
        self.sync_all()

        tx_verbose4 = self.nodes[3].getrawtransaction(txid2, 1)
        assert_equal(tx_verbose4["vin"][0]["address"], address2)
        assert_equal(tx_verbose4["vin"][0]["valueSat"], amount + fee_satoshis)
        assert_equal(float(tx_verbose4["vin"][0]["value"]),
                     (amount + fee_satoshis) / 100000000)

        # Check block deltas
        self.log.info("Testing getblockdeltas...")

        block = self.nodes[3].getblockdeltas(block_hash[0])
        assert_equal(len(block["deltas"]), 2)
        assert_equal(block["deltas"][0]["index"], 0)
        assert_equal(len(block["deltas"][0]["inputs"]), 0)
        assert_equal(len(block["deltas"][0]["outputs"]), 0)
        assert_equal(block["deltas"][1]["index"], 1)
        assert_equal(block["deltas"][1]["txid"], txid2)
        assert_equal(block["deltas"][1]["inputs"][0]["index"], 0)
        assert_equal(block["deltas"][1]["inputs"][0]["address"],
                     "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW")
        assert_equal(block["deltas"][1]["inputs"][0]["satoshis"],
                     (amount + fee_satoshis) * -1)
        assert_equal(block["deltas"][1]["inputs"][0]["prevtxid"], txid)
        assert_equal(block["deltas"][1]["inputs"][0]["prevout"], 0)
        assert_equal(block["deltas"][1]["outputs"][0]["index"], 0)
        assert_equal(block["deltas"][1]["outputs"][0]["address"],
                     "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW")
        assert_equal(block["deltas"][1]["outputs"][0]["satoshis"], amount)

        self.log.info("All Tests Passed")
示例#29
0
    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 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 make_large_invalid_tx(tx_to_spend, output_ndx):
    tx = CTransaction()
    tx.vin.append(CTxIn(COutPoint(tx_to_spend.sha256, output_ndx), b"", 0xffffffff))
    tx.vout.append(CTxOut(tx_to_spend.vout[0].nValue - 2000000, CScript([bytes(1000000), OP_DROP, OP_FALSE])))
    tx.rehash()
    return tx
示例#32
0
    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)
示例#33
0
    def test_prioritised_transactions(self):
        # Ensure that fee deltas used via prioritisetransaction are
        # correctly used by replacement logic

        # 1. Check that feeperkb uses modified fees
        tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN))

        tx1a = CTransaction()
        tx1a.vin = [CTxIn(tx0_outpoint, n_sequence=0)]
        tx1a.vout = [CTxOut(1 * COIN, CScript([b'a']))]
        tx1a_hex = tx_to_hex(tx1a)
        tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)

        # Higher fee, but the actual fee per KB is much lower.
        tx1b = CTransaction()
        tx1b.vin = [CTxIn(tx0_outpoint, n_sequence=0)]
        tx1b.vout = [CTxOut(int(0.001 * COIN), CScript([b'a' * 740000]))]
        tx1b_hex = tx_to_hex(tx1b)

        # Verify tx1b cannot replace tx1a.
        assert_raises_rpc_error(-26, "insufficient fee",
                                self.nodes[0].sendrawtransaction, tx1b_hex,
                                True)

        # Use prioritisetransaction to set tx1a's fee to 0.
        self.nodes[0].prioritisetransaction(txid=tx1a_txid,
                                            fee_delta=int(-0.1 * COIN))

        # Now tx1b should be able to replace tx1a
        tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)

        assert (tx1b_txid in self.nodes[0].getrawmempool())

        # 2. Check that absolute fee checks use modified fee.
        tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN))

        tx2a = CTransaction()
        tx2a.vin = [CTxIn(tx1_outpoint, n_sequence=0)]
        tx2a.vout = [CTxOut(1 * COIN, CScript([b'a']))]
        tx2a_hex = tx_to_hex(tx2a)
        self.nodes[0].sendrawtransaction(tx2a_hex, True)

        # Lower fee, but we'll prioritise it
        tx2b = CTransaction()
        tx2b.vin = [CTxIn(tx1_outpoint, n_sequence=0)]
        tx2b.vout = [CTxOut(int(1.01 * COIN), CScript([b'a']))]
        tx2b.rehash()
        tx2b_hex = tx_to_hex(tx2b)

        # Verify tx2b cannot replace tx2a.
        assert_raises_rpc_error(-26, "insufficient fee",
                                self.nodes[0].sendrawtransaction, tx2b_hex,
                                True)

        # Now prioritise tx2b to have a higher modified fee
        self.nodes[0].prioritisetransaction(txid=tx2b.hash,
                                            fee_delta=int(0.1 * COIN))

        # tx2b should now be accepted
        tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)

        assert (tx2b_txid in self.nodes[0].getrawmempool())