Example #1
0
    def set_test_params(self):
        self.setup_clean_chain = True
        self.num_nodes = 1
        self.supports_cli = True

        self.pubkeys = [
        CPubKey(hex_str_to_bytes ("037150aad31bae4c20121de4e2355bdb4ae8c736cc24dd1d5489f6354d70329d3e")), 
        CPubKey(hex_str_to_bytes("03a5290286cec13e7dff0e9015c295f542f93ec0ddd7b1aaf4011718b2781d090e")), 
        CPubKey(hex_str_to_bytes("0366baa3dda0f960b12519172ebcd5c68d0b958f46bef25843d5b8bd5581f7360d"))]

        self.invalidKeys = [
            "d61cb76ffd678c98320f6c9c5b341c41141add40d5804f6e7de4cabc9ab2f1c2",
            "e81469726d9662adea8a47f4f91cace6309e97635e4a5c7ee34792fba293c6e7",
            "2403c6a86bda076901ed94fb705f40b2c5229efe3d1e079a23cdae8c0eae6121"]

        self.privateKeys = [
        "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
        "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
        "0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1",
        "c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c",
        "388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418",
        "659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63"]  
Example #2
0
    def run_test(self):
        node = self.nodes[0]

        # Generate 6 keys.
        rawkeys = []
        pubkeys = []
        for i in range(6):
            raw_key = CECKey()
            raw_key.set_secretbytes(('privkey%d' % i).encode('ascii'))
            rawkeys.append(raw_key)
        pubkeys = [CPubKey(key.get_pubkey()) for key in rawkeys]

        # Create a 4-of-6 multi-sig wallet with CLTV.
        height = 210
        redeem_script = CScript(
            [CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP] +  # CLTV (lock_time >= 210)
            [OP_4] + pubkeys +  [OP_6, OP_CHECKMULTISIG])  # multi-sig
        hex_redeem_script = bytes_to_hex_str(redeem_script)
        p2sh_address = script_to_p2sh(redeem_script, main=False)

        # Send 1 coin to the mult-sig wallet.
        txid = node.sendtoaddress(p2sh_address, 1.0)
        raw_tx = node.getrawtransaction(txid, True)
        try:
            node.importaddress(hex_redeem_script, 'cltv', True, True)
        except Exception as err:
            pass
        assert_equal(sig(node.getreceivedbyaddress(p2sh_address, 0) - Decimal(1.0)), 0)

        # Mine one block to confirm the transaction.
        node.generate(1)  # block 201
        assert_equal(sig(node.getreceivedbyaddress(p2sh_address, 1) - Decimal(1.0)), 0)

        # Try to spend the coin.
        addr_to = node.getnewaddress('')

        # (1) Find the UTXO
        for vout in raw_tx['vout']:
            if vout['scriptPubKey']['addresses'] == [p2sh_address]:
                vout_n = vout['n']
        hex_script_pubkey = raw_tx['vout'][vout_n]['scriptPubKey']['hex']
        value = raw_tx['vout'][vout_n]['value']

        # (2) Create a tx
        inputs = [{
            "txid": txid,
            "vout": vout_n,
            "scriptPubKey": hex_script_pubkey,
            "redeemScript": hex_redeem_script,
            "amount": value,
        }]
        outputs = {addr_to: 0.999}
        lock_time = height
        hex_spend_raw_tx = node.createrawtransaction(inputs, outputs, lock_time)
        hex_funding_raw_tx = node.getrawtransaction(txid, False)

        # (3) Try to sign the spending tx.
        tx0 = CTransaction()
        tx0.deserialize(io.BytesIO(hex_str_to_bytes(hex_funding_raw_tx)))
        tx1 = CTransaction()
        tx1.deserialize(io.BytesIO(hex_str_to_bytes(hex_spend_raw_tx)))
        self.sign_tx(tx1, tx0, vout_n, redeem_script, 0, rawkeys[:4])  # Sign with key[0:4]

        # Mine some blocks to pass the lock time.
        node.generate(10)

        # Spend the CLTV multi-sig coins.
        raw_tx1 = tx1.serialize()
        hex_raw_tx1 = bytes_to_hex_str(raw_tx1)
        node.sendrawtransaction(hex_raw_tx1)

        # Check the tx is accepted by mempool but not confirmed.
        assert_equal(sig(node.getreceivedbyaddress(addr_to, 0) - Decimal(0.999)), 0)
        assert_equal(sig(node.getreceivedbyaddress(addr_to, 1)), 0)

        # Mine a block to confirm the tx.
        node.generate(1)
        assert_equal(sig(node.getreceivedbyaddress(addr_to, 1) - Decimal(0.999)), 0)
Example #3
0
    def run_test(self):
        # init node
        self.nodes[0].importprivkey(
            "cTnxkovLhGbp7VRhMhGThYt8WDwviXgaVAD8DjaVa5G5DApwC6tF"
        )  # assets location
        self.nodes[0].generate(101)
        self.sync_all()
        genesis = self.nodes[0].getblockhash(0)

        args = Args()
        challenge = Challenge(args)

        # Test check_for_request method
        assert (not challenge.check_for_request()
                )  # return False when no request

        # Make request
        requesttxid1 = make_request(self.nodes[0])
        self.nodes[0].generate(1)
        assert_equal(len(self.nodes[0].getrequests()), 1)

        # Test check_for_request method sets challenge.request
        assert (challenge.check_for_request())
        assert_equal(challenge.request["genesisBlock"],
                     genesis)  # return request

        # Make another request with different genesis
        blockcount = self.nodes[0].getblockcount()
        unspent = self.nodes[0].listunspent(1, 9999999, [], True, "PERMISSION")
        pubkey = self.nodes[0].validateaddress(
            self.nodes[0].getnewaddress())["pubkey"]
        new_genesis = "e9a934a8ae2587fbe6b661e69115a5b7b9d624d73a248e9b2bce15e7d1cd48eb"
        inputs = {"txid": unspent[0]["txid"], "vout": unspent[0]["vout"]}
        outputs = {
            "decayConst": 10,
            "endBlockHeight": blockcount + 20,
            "fee": 1,
            "genesisBlockHash": new_genesis,
            "startBlockHeight": blockcount + 10,
            "tickets": 10,
            "startPrice": 5,
            "value": unspent[0]["amount"],
            "pubkey": pubkey
        }
        tx = self.nodes[0].createrawrequesttx(inputs, outputs)
        signedtx = self.nodes[0].signrawtransaction(tx)
        requesttxid2 = self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)
        assert_equal(len(self.nodes[0].getrequests()), 2)

        # Check correct request fetched for each genesis
        assert (challenge.check_for_request())
        assert_equal(challenge.request["genesisBlock"], genesis)
        challenge.genesis = new_genesis
        assert (challenge.check_for_request())
        assert_equal(challenge.request["genesisBlock"], new_genesis)

        # Test check_for_bid_from_wallet() method
        # No bids
        assert_equal(challenge.check_for_bid_from_wallet(), None)

        # make bid with different wallet receive address
        tx = self.nodes[0].listunspent(1, 9999999, [], True, "CBT")[0]
        change = float(tx["amount"]) - 5 - 0.001
        addr = self.nodes[1].getnewaddress(
        )  # receive address not in service_ocean wallet
        pubkey = self.nodes[1].validateaddress(addr)["pubkey"]
        input = [{"txid": tx["txid"], "vout": tx["vout"]}]
        bidtxraw = self.nodes[0].createrawbidtx(
            input, {
                "feePubkey": pubkey,
                "pubkey": pubkey,
                "value": 5,
                "change": change,
                "changeAddress": addr,
                "fee": 0.001,
                "endBlockHeight": blockcount + 20,
                "requestTxid": requesttxid2
            })
        nonwalletbidtx = self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(bidtxraw)["hex"])
        self.nodes[0].generate(1)

        # Test un-owned bid returns no bid_txid
        assert_equal(challenge.check_for_bid_from_wallet(), None)

        # Test check_ready_for_bid()
        assert (challenge.check_ready_for_bid())  # ready to bid - return true
        # make bid
        tx = self.nodes[0].listunspent(100, 9999999, [], False, "CBT")[0]
        change = float(tx["amount"]) - 5 - 0.001
        addr = self.nodes[0].getnewaddress()
        pubkey = self.nodes[0].validateaddress(addr)["pubkey"]
        input = [{"txid": tx["txid"], "vout": tx["vout"]}]
        bidtxraw = self.nodes[0].createrawbidtx(
            input, {
                "feePubkey": pubkey,
                "pubkey": pubkey,
                "value": 5,
                "change": change,
                "changeAddress": addr,
                "fee": 0.001,
                "endBlockHeight": blockcount + 20,
                "requestTxid": requesttxid2
            })
        challenge.bid_txid = self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(bidtxraw)["hex"])
        self.nodes[0].generate(1)
        assert (not challenge.check_ready_for_bid()
                )  # bid already made - return false
        # all tickets sold
        challenge.request["numTickets"] = 1
        assert (not challenge.check_ready_for_bid()
                )  # all tickets sold - return false
        challenge.request["numTickets"] = 10

        # Test check_for_bid_from_wallet() wallet-owned bid returns bid_txid
        assert_equal(challenge.check_for_bid_from_wallet(), challenge.bid_txid)
        # check key set to corresponding priv key to bids feepubkey
        request = self.nodes[0].getrequestbids(challenge.request["txid"])
        bidfeepubkey = next(bid["feePubKey"] for bid in request["bids"]
                            if bid["txid"] == challenge.bid_txid)
        assert_equal(CPubKey(challenge.key.get_pubkey()).hex(), bidfeepubkey)

        # Test with unconfirmed tx
        # make bid on first request but do not mine
        challenge.genesis = genesis
        challenge.check_for_request()  # update request
        tx = self.nodes[0].listunspent(100, 9999999, [], False, "CBT")[0]
        change = float(tx["amount"]) - 5 - 0.001
        input = [{"txid": tx["txid"], "vout": tx["vout"]}]
        bidtxraw = self.nodes[0].createrawbidtx(
            input, {
                "feePubkey": pubkey,
                "pubkey": pubkey,
                "value": 5,
                "change": change,
                "changeAddress": addr,
                "fee": 0.001,
                "endBlockHeight": blockcount + 19,
                "requestTxid": requesttxid1
            })
        challenge.bid_txid = self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(bidtxraw)["hex"])
        assert_equal(challenge.check_for_bid_from_wallet(),
                     challenge.bid_txid)  # bid tx found
        # check key set to corresponding priv key to bids feepubkey
        self.nodes[0].generate(
            1)  # mine bid tx for easy access to bid feepubkey
        request = self.nodes[0].getrequestbids(challenge.request["txid"])
        bidfeepubkey = next(bid["feePubKey"] for bid in request["bids"]
                            if bid["txid"] == challenge.bid_txid)
        assert_equal(CPubKey(challenge.key.get_pubkey()).hex(), bidfeepubkey)

        # Test gen_feepubkey() and set_key()
        addr = challenge.gen_feepubkey()
        assert_is_hex_string(challenge.client_fee_pubkey)  # check exists
        # Check resulting priv key corresponds to fee pub key
        assert_equal(
            CPubKey(challenge.key.get_pubkey()).hex(),
            challenge.client_fee_pubkey)

        # Test set_key_from_feepubkey()
        addr = self.nodes[0].getnewaddress()
        pubkey = self.nodes[0].validateaddress(addr)["pubkey"]
        challenge.set_key_from_feepubkey(pubkey)
        assert_equal(CPubKey(challenge.key.get_pubkey()).hex(), pubkey)

        # Test asset_in_block()
        assets = []
        for issuance in self.nodes[0].listissuances():  # grab each asset
            assets.append(issuance["asset"])
        # test each asset identified in genesis
        for asset in assets:
            assert (asset_in_block(self.nodes[0], hex_str_rev_hex_str(asset),
                                   0))
        self.nodes[0].generate(1)
        # test none found in empty block
        for asset in assets:
            assert_equal(
                asset_in_block(self.nodes[0], asset,
                               self.nodes[0].getblockcount()), None)
        # test invalid asset argument
        assert_equal(asset_in_block(self.nodes[0], None, 0), None)
        assert_equal(asset_in_block(self.nodes[0], 1234, 0), None)
        assert_equal(asset_in_block(self.nodes[0], 0, 0), None)

        # Test await_challenge()
        block_count = self.nodes[0].getblockcount()
        challenge.last_block_height = block_count
        challenge.request = {
            "endBlockHeight": block_count + 2,
            "startBlockHeight": block_count + 1,
            "txid": "1234"
        }
        # Check request not yet started
        assert_equal(challenge.await_challenge(), True)
        # Check Challenge asset check called
        self.nodes[0].generate(1)
        assert_equal(challenge.await_challenge(), True)
        # Check request ended
        self.nodes[0].generate(2)
        assert (not challenge.await_challenge())

        # Test generate_response()
        challenge.bid_txid = requesttxid2
        data, headers = challenge.generate_response(requesttxid2)
        assert (data)
        assert (headers)
        # Check sig against public key
        pubkey = CPubKey(hex_str_to_bytes(challenge.client_fee_pubkey))
        sig = data[data.find("sig") + 7:-2]
        assert (pubkey.verify(hex_str_to_rev_bytes(requesttxid2),
                              hex_str_to_bytes(sig)))
Example #4
0
    def run_test(self):
        node = self.nodes[0]  # convenience reference to the node

        self.bootstrap_p2p()  # Add one p2p connection to the node

        best_block = self.nodes[0].getbestblockhash()
        tip = int(best_block, 16)
        best_block_time = self.nodes[0].getblock(best_block)['time']
        block_time = best_block_time + 1

        privkey = b"aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7"
        key = CECKey()
        key.set_secretbytes(privkey)
        key.set_compressed(True)
        pubkey = CPubKey(key.get_pubkey())
        pubkeyhash = hash160(pubkey)
        SCRIPT_PUB_KEY = CScript([
            CScriptOp(OP_DUP),
            CScriptOp(OP_HASH160), pubkeyhash,
            CScriptOp(OP_EQUALVERIFY),
            CScriptOp(OP_CHECKSIG)
        ])

        self.log.info("Create a new block with an anyone-can-spend coinbase.")
        height = 1
        block = create_block(tip, create_coinbase(height, pubkey), block_time)
        block.solve(self.signblockprivkey)
        # Save the coinbase for later
        block1 = block
        tip = block.sha256
        node.p2p.send_blocks_and_test([block], node, success=True)

        # b'\x64' is OP_NOTIF
        # Transaction will be rejected with code 16 (REJECT_INVALID)
        self.log.info('Test a transaction that is rejected')
        tx1 = create_tx_with_script(block1.vtx[0],
                                    0,
                                    script_sig=b'\x64' * 35,
                                    amount=50 * COIN - 12000)
        node.p2p.send_txs_and_test([tx1],
                                   node,
                                   success=False,
                                   expect_disconnect=False)

        # Make two p2p connections to provide the node with orphans
        # * p2ps[0] will send valid orphan txs (one with low fee)
        # * p2ps[1] will send an invalid orphan tx (and is later disconnected for that)
        self.reconnect_p2p(num_connections=2)

        self.log.info('Test orphan transaction handling ... ')
        # Create a root transaction that we withhold until all dependend transactions
        # are sent out and in the orphan cache
        tx_withhold = CTransaction()
        tx_withhold.vin.append(
            CTxIn(outpoint=COutPoint(block1.vtx[0].malfixsha256, 0)))
        tx_withhold.vout.append(
            CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY))
        tx_withhold.calc_sha256()
        (sighash, err) = SignatureHash(CScript([pubkey, OP_CHECKSIG]),
                                       tx_withhold, 0, SIGHASH_ALL)
        signature = key.sign(sighash) + b'\x01'  # 0x1 is SIGHASH_ALL
        tx_withhold.vin[0].scriptSig = CScript([signature])

        # Our first orphan tx with some outputs to create further orphan txs
        tx_orphan_1 = CTransaction()
        tx_orphan_1.vin.append(
            CTxIn(outpoint=COutPoint(tx_withhold.malfixsha256, 0)))
        tx_orphan_1.vout = [
            CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY)
        ] * 3
        tx_orphan_1.calc_sha256()
        (sighash, err) = SignatureHash(SCRIPT_PUB_KEY, tx_orphan_1, 0,
                                       SIGHASH_ALL)
        signature = key.sign(sighash) + b'\x01'  # 0x1 is SIGHASH_ALL
        tx_orphan_1.vin[0].scriptSig = CScript([signature, pubkey])

        # A valid transaction with low fee
        tx_orphan_2_no_fee = CTransaction()
        tx_orphan_2_no_fee.vin.append(
            CTxIn(outpoint=COutPoint(tx_orphan_1.malfixsha256, 0)))
        tx_orphan_2_no_fee.vout.append(
            CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY))
        (sighash, err) = SignatureHash(SCRIPT_PUB_KEY, tx_orphan_2_no_fee, 0,
                                       SIGHASH_ALL)
        signature = key.sign(sighash) + b'\x01'  # 0x1 is SIGHASH_ALL
        tx_orphan_2_no_fee.vin[0].scriptSig = CScript([signature, pubkey])

        # A valid transaction with sufficient fee
        tx_orphan_2_valid = CTransaction()
        tx_orphan_2_valid.vin.append(
            CTxIn(outpoint=COutPoint(tx_orphan_1.malfixsha256, 1)))
        tx_orphan_2_valid.vout.append(
            CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY))
        tx_orphan_2_valid.calc_sha256()
        (sighash, err) = SignatureHash(SCRIPT_PUB_KEY, tx_orphan_2_valid, 0,
                                       SIGHASH_ALL)
        signature = key.sign(sighash) + b'\x01'  # 0x1 is SIGHASH_ALL
        tx_orphan_2_valid.vin[0].scriptSig = CScript([signature, pubkey])

        # An invalid transaction with negative fee
        tx_orphan_2_invalid = CTransaction()
        tx_orphan_2_invalid.vin.append(
            CTxIn(outpoint=COutPoint(tx_orphan_1.malfixsha256, 2)))
        tx_orphan_2_invalid.vout.append(
            CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY))
        (sighash, err) = SignatureHash(SCRIPT_PUB_KEY, tx_orphan_2_invalid, 0,
                                       SIGHASH_ALL)
        signature = key.sign(sighash) + b'\x01'  # 0x1 is SIGHASH_ALL
        tx_orphan_2_invalid.vin[0].scriptSig = CScript([signature, pubkey])

        self.log.info('Send the orphans ... ')
        # Send valid orphan txs from p2ps[0]
        node.p2p.send_txs_and_test(
            [tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid],
            node,
            success=False)
        # Send invalid tx from p2ps[1]
        node.p2ps[1].send_txs_and_test([tx_orphan_2_invalid],
                                       node,
                                       success=False)

        assert_equal(0,
                     node.getmempoolinfo()['size'])  # Mempool should be empty
        assert_equal(2, len(node.getpeerinfo()))  # p2ps[1] is still connected

        self.log.info('Send the withhold tx ... ')
        node.p2p.send_txs_and_test([tx_withhold], node, success=True)

        # Transactions that should end up in the mempool
        expected_mempool = {
            t.hashMalFix
            for t in [
                tx_withhold,  # The transaction that is the root for all orphans
                tx_orphan_1,  # The orphan transaction that splits the coins
                tx_orphan_2_valid,  # The valid transaction (with sufficient fee)
            ]
        }
        # Transactions that do not end up in the mempool
        # tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
        # tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)

        wait_until(lambda: 1 == len(node.getpeerinfo()),
                   timeout=12)  # p2ps[1] is no longer connected
        assert_equal(expected_mempool, set(node.getrawmempool()))

        # restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
        self.log.info(
            'Test a transaction that is rejected, with BIP61 disabled')
        self.restart_node(0, ['-enablebip61=0', '-persistmempool=0'])
        self.reconnect_p2p(num_connections=1)
        node.p2p.send_txs_and_test([tx1],
                                   node,
                                   success=False,
                                   expect_disconnect=False)
        # send_txs_and_test will have waited for disconnect, so we can safely check that no reject has been received
        assert_equal(node.p2p.reject_code_received, None)