def stake_block(self, node_id, nVersion, nHeight, prevHash, prevModifier, finalsaplingroot, stakeableUtxos, startTime, privKeyWIF, vtx, fDoubleSpend):
    ' manually stakes a block selecting the coinstake input from a list of candidates\n        :param   node_id:           (int) index of the CTestNode used as rpc connection. Must own stakeableUtxos.\n                 nVersion:          (int) version of the block being produced (7 or 8)\n                 nHeight:           (int) height of the block being produced\n                 prevHash:          (string) hex string of the previous block hash\n                 prevModifier       (string) hex string of the previous block stake modifier\n                 finalsaplingroot   (string) hex string of the previous block sapling root (blocks V8)\n                 stakeableUtxos:    ({bytes --> (int, bytes, int)} dictionary)\n                                    maps CStake "uniqueness" (i.e. serialized COutPoint)\n                                    to (amount, prevScript, timeBlockFrom).\n                 startTime:         (int) epoch time to be used as blocktime (iterated in solve_stake)\n                 privKeyWIF:        (string) private key to be used for staking/signing\n                                    If empty string, it will be used the pk from the stake input\n                                    (dumping the sk from rpc_conn). If None, then the DUMMY_KEY will be used.\n                 vtx:               ([CTransaction] list) transactions to add to block.vtx\n                 fDoubleSpend:      (bool) wether any tx in vtx is allowed to spend the coinstake input\n        :return: block:             (CBlock) block produced, must be manually relayed\n        '
    assert_greater_than(len(self.nodes), node_id)
    rpc_conn = self.nodes[node_id]
    if (not (len(stakeableUtxos) > 0)):
        raise Exception('Need at least one stakeable utxo to stake a block!')
    if (startTime is None):
        startTime = time.time()
    nTime = (int(startTime) & 4294967280)
    coinbaseTx = create_coinbase_pos(nHeight)
    block = create_block(int(prevHash, 16), coinbaseTx, nTime, nVersion, int(finalsaplingroot, 16))
    block.nVersion = nVersion
    block.solve_stake(stakeableUtxos, int(prevModifier, 16))
    block_sig_key = CECKey()
    coinstakeTx_unsigned = CTransaction()
    prevout = COutPoint()
    prevout.deserialize_uniqueness(BytesIO(block.prevoutStake))
    coinstakeTx_unsigned.vin.append(CTxIn(prevout, b'', 4294967295))
    coinstakeTx_unsigned.vout.append(CTxOut())
    (amount, prevScript, _) = stakeableUtxos[block.prevoutStake]
    outNValue = int((amount + (250 * COIN)))
    coinstakeTx_unsigned.vout.append(CTxOut(outNValue, hex_str_to_bytes(prevScript)))
    if (privKeyWIF == ''):
        if (not hasattr(self, 'DUMMY_KEY')):
            self.init_dummy_key()
        block_sig_key = self.DUMMY_KEY
        coinstakeTx_unsigned.vout[1].scriptPubKey = CScript([block_sig_key.get_pubkey(), OP_CHECKSIG])
    else:
        if (privKeyWIF == None):
            rawtx = rpc_conn.getrawtransaction('{:064x}'.format(prevout.hash), True)
            privKeyWIF = rpc_conn.dumpprivkey(rawtx['vout'][prevout.n]['scriptPubKey']['addresses'][0])
        (privKey, compressed) = wif_to_privkey(privKeyWIF)
        block_sig_key.set_compressed(compressed)
        block_sig_key.set_secretbytes(bytes.fromhex(privKey))
    stake_tx_signed_raw_hex = rpc_conn.signrawtransaction(bytes_to_hex_str(coinstakeTx_unsigned.serialize()))['hex']
    coinstakeTx = CTransaction()
    coinstakeTx.from_hex(stake_tx_signed_raw_hex)
    block.vtx.append(coinstakeTx)
    for tx in vtx:
        if ((not fDoubleSpend) and tx.spends(prevout)):
            continue
        block.vtx.append(tx)
    block.hashMerkleRoot = block.calc_merkle_root()
    block.rehash()
    block.sign_block(block_sig_key)
    return block
manually stakes a block selecting the coinstake input from a list of candidates
:param   node_id:           (int) index of the CTestNode used as rpc connection. Must own stakeableUtxos.
         nVersion:          (int) version of the block being produced (7 or 8)
         nHeight:           (int) height of the block being produced
         prevHash:          (string) hex string of the previous block hash
         prevModifier       (string) hex string of the previous block stake modifier
         finalsaplingroot   (string) hex string of the previous block sapling root (blocks V8)
         stakeableUtxos:    ({bytes --> (int, bytes, int)} dictionary)
                            maps CStake "uniqueness" (i.e. serialized COutPoint)
                            to (amount, prevScript, timeBlockFrom).
         startTime:         (int) epoch time to be used as blocktime (iterated in solve_stake)
         privKeyWIF:        (string) private key to be used for staking/signing
                            If empty string, it will be used the pk from the stake input
                            (dumping the sk from rpc_conn). If None, then the DUMMY_KEY will be used.
         vtx:               ([CTransaction] list) transactions to add to block.vtx
         fDoubleSpend:      (bool) wether any tx in vtx is allowed to spend the coinstake input
:return: block:             (CBlock) block produced, must be manually relayed
def stake_block(self, node_id, nVersion, nHeight, prevHash, prevModifier, finalsaplingroot, stakeableUtxos, startTime, privKeyWIF, vtx, fDoubleSpend):
    ' manually stakes a block selecting the coinstake input from a list of candidates\n        :param   node_id:           (int) index of the CTestNode used as rpc connection. Must own stakeableUtxos.\n                 nVersion:          (int) version of the block being produced (7 or 8)\n                 nHeight:           (int) height of the block being produced\n                 prevHash:          (string) hex string of the previous block hash\n                 prevModifier       (string) hex string of the previous block stake modifier\n                 finalsaplingroot   (string) hex string of the previous block sapling root (blocks V8)\n                 stakeableUtxos:    ({bytes --> (int, bytes, int)} dictionary)\n                                    maps CStake "uniqueness" (i.e. serialized COutPoint)\n                                    to (amount, prevScript, timeBlockFrom).\n                 startTime:         (int) epoch time to be used as blocktime (iterated in solve_stake)\n                 privKeyWIF:        (string) private key to be used for staking/signing\n                                    If empty string, it will be used the pk from the stake input\n                                    (dumping the sk from rpc_conn). If None, then the DUMMY_KEY will be used.\n                 vtx:               ([CTransaction] list) transactions to add to block.vtx\n                 fDoubleSpend:      (bool) wether any tx in vtx is allowed to spend the coinstake input\n        :return: block:             (CBlock) block produced, must be manually relayed\n        '
    assert_greater_than(len(self.nodes), node_id)
    rpc_conn = self.nodes[node_id]
    if (not (len(stakeableUtxos) > 0)):
        raise Exception('Need at least one stakeable utxo to stake a block!')
    if (startTime is None):
        startTime = time.time()
    nTime = (int(startTime) & 4294967280)
    coinbaseTx = create_coinbase_pos(nHeight)
    block = create_block(int(prevHash, 16), coinbaseTx, nTime, nVersion, int(finalsaplingroot, 16))
    block.nVersion = nVersion
    block.solve_stake(stakeableUtxos, int(prevModifier, 16))
    block_sig_key = CECKey()
    coinstakeTx_unsigned = CTransaction()
    prevout = COutPoint()
    prevout.deserialize_uniqueness(BytesIO(block.prevoutStake))
    coinstakeTx_unsigned.vin.append(CTxIn(prevout, b, 4294967295))
    coinstakeTx_unsigned.vout.append(CTxOut())
    (amount, prevScript, _) = stakeableUtxos[block.prevoutStake]
    outNValue = int((amount + (250 * COIN)))
    coinstakeTx_unsigned.vout.append(CTxOut(outNValue, hex_str_to_bytes(prevScript)))
    if (privKeyWIF == ):
        if (not hasattr(self, 'DUMMY_KEY')):
            self.init_dummy_key()
        block_sig_key = self.DUMMY_KEY
        coinstakeTx_unsigned.vout[1].scriptPubKey = CScript([block_sig_key.get_pubkey(), OP_CHECKSIG])
    else:
        if (privKeyWIF == None):
            rawtx = rpc_conn.getrawtransaction('{:064x}'.format(prevout.hash), True)
            privKeyWIF = rpc_conn.dumpprivkey(rawtx['vout'][prevout.n]['scriptPubKey']['addresses'][0])
        (privKey, compressed) = wif_to_privkey(privKeyWIF)
        block_sig_key.set_compressed(compressed)
        block_sig_key.set_secretbytes(bytes.fromhex(privKey))
    stake_tx_signed_raw_hex = rpc_conn.signrawtransaction(bytes_to_hex_str(coinstakeTx_unsigned.serialize()))['hex']
    coinstakeTx = CTransaction()
    coinstakeTx.from_hex(stake_tx_signed_raw_hex)
    block.vtx.append(coinstakeTx)
    for tx in vtx:
        if ((not fDoubleSpend) and tx.spends(prevout)):
            continue
        block.vtx.append(tx)
    block.hashMerkleRoot = block.calc_merkle_root()
    block.rehash()
    block.sign_block(block_sig_key)
    return block