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"]
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)
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)))
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)