Пример #1
0
def process_block(node_from, block):
    """

    :param node_from:
    :param block:
    :type block: Block.PyBlock
    :return:
    """
    # Check for duplicate
    block_hash = block.get_hash()
    if block_hash in ctx.dictBlockIndex:
        print("ProcessBlock() : already have block %d %s" %
              (ctx.dictBlockIndex[block_hash].height,
               serialize.hexser_uint256(block_hash)))
        return False
    if block_hash in ctx.dictOrphanBlocks:
        print("ProcessBlock() : already have block (orphan) %s" %
              serialize.hexser_uint256(block_hash))
        return False

    # Preliminary checks
    if not block.check_block():
        del block
        print("ProcessBlock() : CheckBlock FAILED")
        return False

    # If don't already have its previous block, shunt it off to holding area until we get it
    if block.hash_prev_block not in ctx.dictBlockIndex:
        print("ProcessBlock: ORPHAN BLOCK, prev=%s" %
              serialize.hexser_uint256(block.hash_prev_block)[:14])
        ctx.dictOrphanBlocks[block_hash] = block
        ctx.dictOrphanBlocksByPrev[block_hash] = block
        # Ask this guy to fill in what we're missing
        if node_from:
            node_from.push_message(netbase.COMMAND_GETBLOCKS,
                                   Block.PyBlockLocator(ctx.indexBest),
                                   (Block.get_orphan_root(block), "uint256"))
        return True

    # store to disk
    if not block.accept_block():
        del block
        print("ProcessBlock() : AcceptBlock FAILED")
        return False

    del block

    # Recursively process any orphan blocks that depended on this one
    work_queue = list()
    work_queue.append(block_hash)
    for hash_prev in iter(work_queue):
        for block_orphan in ctx.dictOrphanBlocksByPrev[hash_prev]:
            if block_orphan.accept_block():
                work_queue.append(block_orphan.get_hash())
            ctx.dictOrphanBlocks.pop(block_orphan.get_hash(), None)
            del block_orphan
        ctx.dictOrphanBlocksByPrev.pop(hash_prev, None)
    print("ProcessBlock: ACCEPTED\n")
    return True
Пример #2
0
def genesis_block():
    timestamp = "The Times 22/Mar/2017 Chancellor on brink of second bailout for banks"
    tx_new = Tx.PyTransaction()
    txin = Tx.PyTxIn()
    init_nbits = 0x1f00ffff
    sig = Script.PyScript().append(init_nbits).append_num(4).extend(timestamp)
    # script << nbits << extra_nonce
    txin.script_sig = sig
    txout = Tx.PyTxOut()
    txout.value = 50 * cfg.COIN
    # scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;   Hash160(pubkey)  # txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
    # txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
    txout.script_pubkey = Script.PyScript().extend(binascii.unhexlify(cfg.GENESIS_PUBKEY)) \
        .append(Script.OpCodeType.OP_CHECKSIG)

    tx_new.l_in.append(txin)
    tx_new.l_out.append(txout)
    block = Block.PyBlock()
    block.l_tx.append(tx_new)
    block.hash_prev_block = 0
    block.hash_merkle_root = block.build_merkle_tree()
    block.version = 1
    block.time = 1490092537
    # block.bits = 0x2000ffff  #
    block.bits = init_nbits  # nonce:45164 hash:2e72d19b7558bd6ec869e5601c3613cc7a6b3f24118773d7aaaa3c285493fdfc
    # block.bits = 0x1e00ffff  # nonce:xxx (cast almost 5 min)
    block.nonce = 0
    hash_target = BN.PyBigNum.set_compact(block.bits).get_uint256()
    target_hex = serialize.hexser_uint256(hash_target)
    # target_hex = long(hash_target)
    time1 = timeutil.get_time()
    print 'start time:', time1
    while True:
        block_hash = cryptoutil.Hash(block.serialize())
        print 'nonce:', block.nonce
        print 'now hash:'
        print serialize.hexser_uint256(block_hash)
        # print long(block_hash)
        print 'target'
        print target_hex
        if block_hash <= hash_target:
            print 'current nonce:'
            print block.nonce
            print binascii.hexlify(serialize.ser_uint256(block.get_hash()))
            print block.get_hash('hex')
            print long(hash_target)
            break
        block.nonce += 1
    time2 = timeutil.get_time()
    print 'end time:', time2
    diff = time2 - time1
    print("%d:%d" % (diff / 60, diff % 60))
Пример #3
0
    def InsertLine(self, f_new, index, tx_hash, str_sort, *strs):
        data = hash(tx_hash)
        hexformat = serialize.hexser_uint256(tx_hash)
        if f_new:
            # index = self.m_listCtrl_txs.InsertItem(0, str_sort)
            index = self.m_listCtrl_txs.InsertStringItem(0, str_sort)
        else:
            if index == -1:
                # find item
                index = self.m_listCtrl_txs.FindItemData(index, data)
                while index != -1:
                    if get_item_text(self.m_listCtrl_txs, index,
                                     1) == hexformat:
                        break
                    index = self.m_listCtrl_txs.FindItemData(index, data)
                if index == -1:
                    print(
                        "MainFrame::InsertLine : Couldn't find item to be updated"
                    )
                    return
            # If sort key changed, must delete and reinsert to make it relocate
            if get_item_text(self.m_listCtrl_txs, index, 0) != str_sort:
                self.m_listCtrl_txs.DeleteItem(index)
                # index = self.m_listCtrl_txs.InsertItem(0, str_sort)
                index = self.m_listCtrl_txs.InsertStringItem(0, str_sort)

        # self.m_listCtrl_txs.SetItem(index, 1, hexformat)
        self.m_listCtrl_txs.SetStringItem(index, 1, hexformat)
        for i in range(2, min(7, len(strs))):
            # self.m_listCtrl_txs.SetItem(index, i, strs[i - 2])
            self.m_listCtrl_txs.SetStringItem(index, i, strs[i - 2])
        self.m_listCtrl_txs.SetItemData(index, data)
Пример #4
0
def test_nbits():
    n = PyBigNum.set_compact(0x1f00ffff)
    print serialize.hexser_uint256(n)

    n = PyBigNum.set_compact(0x1d00ffff)
    print serialize.hexser_uint256(n)

    n = PyBigNum(ctx.proofOfWorkLimit)
    print serialize.hexser_uint256(n)
    print serialize.hexser_uint256(PyBigNum.set_compact(n.get_compact()))
    pass
Пример #5
0
def send_money(script_pubkey, value, wtx_new, ignoreui=True):
    """
    发送 value 的coin
    :param script_pubkey:
    :param value:
    :param wtx_new:
    :type wtx_new: Block.PyWalletTx
    :return:
    :rtype bool
    """
    with ctx.mainLock:
        fee_required = list()
        fee = create_transaction(script_pubkey, value, wtx_new, fee_required)
        if fee is None:
            if value + fee_required[0] > get_balance():
                str_error = "Error: This is an oversized transaction that requires a transaction fee of %s " \
                            % util.format_money(fee)
            else:
                str_error = "Error: Transaction creation failed "

            if not ignoreui:
                wx.MessageBox(str_error, "Sending...")
            print ("SendMoney() : %s" % str_error)
            return False

        if not commit_transaction_spend(wtx_new):
            if not ignoreui:
                wx.MessageBox("Error finalizing transaction", "Sending...")
            print ("SendMoney() : Error finalizing transaction")
            return False

        print ("SendMoney: %s\n" % serialize.hexser_uint256(wtx_new.get_hash())[:6])

        # Broadcast
        if not wtx_new.accept_transaction():  # TODO reject at this point
            # This must not fail. The transaction has already been signed and recorded.
            if not ignoreui:
                wx.MessageBox("Error: Transaction not valid", "Sending...")
            print ("SendMoney() : Error: Transaction not valid")
            return False
        wtx_new.relay_wallet_transaction()

    if not ignoreui:
        ui.mainframe_repaint()
    return True
Пример #6
0
 def get_uint256(self, out_type=None):
     b = bn2mpi(self)
     size = len(b)
     if size < 4:
         return 0
     else:
         b[4] &= 0x7F  # modify num negative
     n = bytearray(32)  # uint256
     i = 0  # 0 -> 28 for n,  empty for last 4 B
     for j in range(size - 1, 3, -1):  # 32 -> 4 for b
         if i >= 32:
             break
         n[i] = b[j]
         i += 1
     if out_type == "str":
         return bytes(n)
     if out_type == "hex":
         return serialize.hexser_uint256(bytes(n), in_type="str")
     return serialize.deser_uint256(bytes(n))
Пример #7
0
    def OnPaintListCtrl(self, event):

        # Update listctrl contents
        if ctx.listWalletUpdated:
            if ctx.dictWalletLock._RLock__count == 0:
                with ctx.dictWalletLock:
                    for tx_hash, f_new in ctx.listWalletUpdated:
                        wtx = ctx.dictWallet.get(tx_hash, None)
                        if wtx is not None:
                            print("listWalletUpdated: %s %s" %
                                  (serialize.hexser_uint256(tx_hash)[:6],
                                   "new" if f_new else ""))
                            self.InsertTransaction(wtx, f_new)
                    self.m_listCtrl_txs.ScrollList(0, 0xFFFF)
                    del ctx.listWalletUpdated[:]
                    pass  # end block
                pass  # end try block
        # Update status column of visible items only
        self.RefreshStatus()

        # Update status bar
        str_gen = ''
        if ctx.fGenerateCoins:
            str_gen = "    Generating"
        if ctx.fGenerateCoins and len(ctx.listNodes) == 0:
            str_gen = "(not connected)"

        self.m_statusBar.SetStatusText(unicode(str_gen), 1)

        str_status = "     %d connections     %d blocks     %d transactions" % \
                     (len(ctx.listNodes), ctx.bestHeight + 1, self.m_listCtrl_txs.GetItemCount())
        self.m_statusBar.SetStatusText(unicode(str_status), 2)

        # Balance total
        if ctx.dictWalletLock._RLock__count == 0:
            with ctx.dictWalletLock:
                self.m_statictext_balance.SetLabel(
                    util.format_money(txaction.get_balance()) + '  ')
                # print 'set label'
        self.m_listCtrl_txs.OnPaint(event)
        pass  # end func
Пример #8
0
def process_message(node_from, command, recv):
    """

    :param node_from:
    :type node_from: net.PyNode
    :param command:
    :param recv:
    :type recv: serialize.PyDataStream
    :return:
    :rtype bool
    """
    global dictReuseKey
    print("received: %-12s (%d bytes)  " % (command, len(recv)))
    buf = list()
    for i in range(min(len(recv), 25)):
        buf.append("%02x " % (bytearray(recv[i])[0] & 0xff))
    print "".join(buf)
    print("")
    if ctx.dropMessagesTest > 0 and baseutil.get_rand(
            ctx.dropMessagesTest) == 0:  # 这难吧··
        print("dropmessages DROPPING RECV MESSAGE\n")  # 应该是模拟随机丢弃消息
        return True

    if command == base.COMMAND_VERSION:
        # Can only do this once
        if node_from.nVersion != 0:
            return False
        node_from.nVersion = recv.stream_out(out_type="int")  # int
        node_from.services = recv.stream_out(out_type="uint64")  # uint64
        time = recv.stream_out(out_type="int64")  # int64
        addr_me = recv.stream_out(cls=net.PyAddress)
        if node_from.nVersion == 0:
            return False

        node_from.send.nVersion = min(node_from.nVersion, cfg.VERSION)
        node_from.recv.nVersion = min(node_from.nVersion, cfg.VERSION)

        node_from.f_client = not (node_from.services & cfg.NODE_NETWORK)
        if node_from.f_client:
            node_from.send.nType |= serialize.SerType.SER_BLOCKHEADERONLY
            node_from.recv.nType |= serialize.SerType.SER_BLOCKHEADERONLY

        timeutil.add_time_data(node_from.addr.ip, time)

        # Ask the first connected node for block updates
        global fAskedForBlocks
        if not fAskedForBlocks and not node_from.f_client:
            fAskedForBlocks = True
            node_from.push_message(base.COMMAND_GETBLOCKS,
                                   Block.PyBlockLocator(ctx.indexBest),
                                   (0, "uint256"))
        print("version addrMe = %s\n" % str(addr_me))
    elif node_from.nVersion == 0:
        # Must have a version message before anything else
        return False
    elif command == base.COMMAND_ADDR:
        list_addr = recv.stream_out(out_type="list",
                                    cls=net.PyAddress)  # list<PyAddress>
        # Store the new addresses
        addrdb = net.PyAddrDB()
        for addr in list_addr:
            if ctx.fShutdown:
                return True
            if net.add_address(addrdb, addr):
                # Put on lists to send to other nodes
                node_from.set_addr_known.add(addr)
                with ctx.listNodesLock:
                    if addr not in node_from.set_addr_known:
                        node_from.list_addr_to_send.append(addr)
        addrdb.close()
    elif command == base.COMMAND_INV:
        list_inv = recv.stream_out("list", net.PyInv)
        txdb = Tx.PyTxDB("r")
        for inv in list_inv:
            if ctx.fShutdown:
                return True
            node_from.add_inventory_known(inv)

            f_already_have = already_have(txdb, inv)
            print("  got inventory: %s  %s\n" %
                  (str(inv), "have" if f_already_have else "new"))

            if not f_already_have:
                node_from.ask_for(inv)
            elif inv.msg_type == net.MsgType.MSG_BLOCK and inv.msg_hash in ctx.dictOrphanBlocks:
                node_from.push_message(
                    base.COMMAND_GETBLOCKS,
                    Block.PyBlockLocator(ctx.indexBest),
                    (Block.get_orphan_root(
                        ctx.dictOrphanBlocks[inv.msg_hash]), "uint256"))
        txdb.close()
    elif command == base.COMMAND_GETDATA:
        list_inv = recv.stream_out("list", net.PyInv)
        for inv in list_inv:
            if ctx.fShutdown:
                return True
            print("received getdata for: %s\n" % str(inv))

            if inv.msg_type == net.MsgType.MSG_BLOCK:
                # Send block from disk
                block_index = ctx.dictBlockIndex.get(inv.msg_hash, None)
                if block_index is not None:
                    ## could optimize this to send header straight from blockindex for client
                    block = Block.PyBlock()
                    block.read_from_disk(
                        block_index, read_txs=(
                            not node_from.f_client))  # index, block_pos=0
                    node_from.push_message(base.COMMAND_BLOCK, block)
            elif inv.is_known_type():
                #  Send stream from relay memory
                with ctx.dictRelayLock:
                    data = ctx.dictRelay.get(inv, None)  # data:PyDataStream
                    if data is not None:
                        node_from.push_message(inv.get_command(), data)
    elif command == base.COMMAND_GETBLOCKS:
        locator = recv.stream_out(cls=Block.PyBlockLocator)
        hash_stop = recv.stream_out(out_type="uint256")

        # Find the first block the caller has in the main chain
        index = locator.get_block_index()

        # Send the rest of the chain
        if index:
            index = index.next_index

        print("getblocks %d to %s\n" %
              (index.height if index else -1,
               serialize.hexser_uint256(hash_stop)[:14]))

        while index:
            if index.get_block_hash() == hash_stop:
                print("  getblocks stopping at %d %s" %
                      (index.height,
                       index.get_block_hash(output_type='hex')[:14]))
                break

            # Bypass setInventoryKnown in case an inventory message got lost
            with node_from.inventory_lock:
                inv = net.PyInv(net.MsgType.MSG_BLOCK, index.get_block_hash())

                if inv not in node_from.set_inventory_know2:
                    node_from.set_inventory_know2.add(inv)
                    node_from.set_inventory_know.discard(
                        inv)  # not throw exception
                    node_from.list_inventory_to_send.append(inv)

            index = index.next_index
            pass  # end loop
    elif command == base.COMMAND_TX:
        list_work_queue = list()  # hash256 list
        msg = recv.copy()
        tx = recv.stream_out(cls=Tx.PyTransaction)

        inv = net.PyInv(net.MsgType.MSG_TX, tx.get_hash())
        node_from.add_inventory_known(inv)

        f_missing_inputs = [False]
        if tx.accept_transaction(check_inputs=True,
                                 missing_inputs=f_missing_inputs):
            Block.add_to_wallet_if_mine(tx, None)
            netaction.relay_message(inv, msg)
            ctx.dictAlreadyAskedFor.pop(inv, None)  # delete from dict
            list_work_queue.append(inv.msg_hash)

            # Recursively process any orphan transactions that depended on this one
            for hash_prev in iter(list_work_queue):
                for msg in ctx.dictOrphanBlocksByPrev[
                        hash_prev]:  # list<PyDataStrem>
                    tx = msg.stream_out(cls=Tx.PyTransaction)
                    inv = net.PyInv(net.MsgType.MSG_TX, tx.get_hash())

                    if tx.accept_transaction(check_inputs=True):
                        print("   accepted orphan tx %s" %
                              serialize.hexser_uint256(inv.msg_hash))
                        Block.add_to_wallet_if_mine(tx, None)
                        netaction.relay_message(inv, msg)
                        ctx.dictAlreadyAskedFor.pop(inv,
                                                    None)  # delete from dict
                        list_work_queue.append(inv.msg_hash)
                pass  # end for list_work_queue loop
            for tx_hash in list_work_queue:
                txaction.erase_orphan_tx(tx_hash)
        elif f_missing_inputs[
                0]:  # f_missing_inputs will chang in accept_transaction()
            print("storing orphan tx %s" %
                  serialize.hexser_uint256(inv.msg_hash)[:6])
            txaction.add_orphan_tx(msg)
    elif command == base.COMMAND_REVIEW:
        msg = recv.copy()
        review = recv.stream_out(cls=market.PyReview)

        inv = net.PyInv(net.MsgType.MSG_REVIEW, review.get_hash())
        node_from.add_inventory_known(inv)

        if review.accept_review():
            # Relay the original message as-is in case it's a higher version than we know how to parse
            netaction.relay_message(inv, msg)
            ctx.dictAlreadyAskedFor.pop(inv, None)  # del from dict
    elif command == base.COMMAND_BLOCK:
        block = recv.stream_out(cls=Block.PyBlock)
        ## debug print
        print("received block: \n%s" % str(block))

        inv = net.PyInv(net.MsgType.MSG_BLOCK, block.get_hash())
        node_from.add_inventory_known(inv)

        if blockaction.process_block(node_from, block):
            ctx.dictAlreadyAskedFor.pop(inv, None)
    elif command == base.COMMAND_GETADDR:
        node_from.list_addr_to_send = list()
        ## need to expand the time range if not enough found
        since = timeutil.get_adjusted_time(
        ) - cfg.COMMAND_GETADDR_SPAN_TIME  # in the last hour
        with ctx.dictAddressesLock:
            for addr in iter(ctx.dictAddresses.itervalues()):
                if ctx.fShutdown:
                    return
                if addr.time > since:
                    node_from.list_addr_to_send.append(addr)
    elif command == base.COMMAND_CHECKORDER:
        hash_reply = recv.stream_out(out_type="uint256")
        order = recv.stream_out(cls=Block.PyWalletTx)
        # todo: we have a chance to check the order here
        #
        # Keep giving the same key to the same ip until they use it
        if node_from.addr.ip is not dictReuseKey:
            dictReuseKey[node_from.addr.ip] = keyaction.generate_new_key(
            )  # generate pubkey : str

        # Send back approval of order and pubkey to use
        script_pubkey = script.PyScript()
        script_pubkey.extend(dictReuseKey[node_from.addr.ip]).append(
            script.OpCodeType.OP_CHECKSIG)
        node_from.push_message(base.COMMAND_REPLY, (hash_reply, "uint256"),
                               (0, "int"), (script_pubkey.get_str(), "str"))
    elif command == base.COMMAND_SUBMITORDER:
        hash_reply = recv.stream_out(out_type="uint256")
        wtx_new = recv.stream_out(cls=Block.PyWalletTx)

        # Broadcast
        if not wtx_new.accept_wallet_transaction():
            node_from.push_message(base.COMMAND_REPLY, (hash_reply, "uint256"),
                                   (1, "int"))
            print(
                "submitorder AcceptWalletTransaction() failed, returning error 1"
            )
            return False
        wtx_new.time_received_is_tx_time = 1
        Block.add_to_wallet(wtx_new)
        wtx_new.relay_wallet_transaction()
        dictReuseKey.pop(node_from.addr.ip, None)

        # Send back confirmation
        node_from.push_message(base.COMMAND_REPLY, (hash_reply, "uint256"),
                               (0, "int"))
    elif command == base.COMMAND_REPLY:
        hash_reply = recv.stream_out(out_type="uint256")
        # code_reply = recv.stream_out(out_type="int")
        with node_from.dict_requests_lock:
            tracker = node_from.dict_requests.get(hash_reply, None)
            if tracker is not None:
                tracker.func(tracker.param,
                             recv)  # recv contain code_reply(0 or 1)
    else:
        #  Ignore unknown commands for extensibility
        print("ProcessMessage(%s) : Ignored unknown message" % command)

    if len(recv) != 0:
        print("ProcessMessage(%s) : %d extra bytes" % (command, len(recv)))
    return True
Пример #9
0
def bitcoin_miner(t):
    """

    :param t:
    :type t: ExitedThread
    :return:
    """
    print "Miner started"
    # TODO add thread priority  THREAD_PRIORITY_LOWEST
    key = Key.PyKey()
    key.make_new_key()

    extra_nonce = 0
    while ctx.fGenerateCoins:
        timeutil.sleep_msec(50)  # 50 ms
        t.check_self_shutdown()
        if t.exit:
            break
        # while len(ctx.listNodes) == 0:
        #     timeutil.sleep_msec(1000)
        #     t.check_self_shutdown()
        #     if t.exit:
        #         return True

        transactions_updated_last = ctx.transactionsUpdated
        index_prev = ctx.indexBest
        bits = Block.get_next_work_required(index_prev)

        # create coinbase tx
        tx_new = Tx.PyTransaction()
        tx_in = Tx.PyTxIn()
        tx_in.prev_out.set_null()
        extra_nonce += 1
        tx_in.script_sig.append(bits).append(extra_nonce)
        tx_new.l_in.append(tx_in)
        tx_out = Tx.PyTxOut()
        tx_out.script_pubkey.extend(key.get_pubkey()).append(
            Script.OpCodeType.OP_CHECKSIG)
        tx_new.l_out.append(tx_out)

        # create new block
        block = Block.PyBlock()

        # Add our coinbase tx as first transaction
        block.l_tx.append(tx_new)

        # Collect the latest transactions into the block
        fees = 0
        with ctx.mainLock:
            with ctx.dictTransactionsLock:
                txdb = Tx.PyTxDB("r")
                test_pool = dict()  # map<uint256, PyTxIndex>
                flag_already_added = [False] * len(ctx.dictTransactions)
                found_something = True
                block_size = 0
                while found_something and block_size < cfg.MAX_SIZE / 2:  # block_size < 2MB/2 = 1MB
                    found_something = False
                    n = 0
                    for tx_hash, tx in ctx.dictTransactions.iteritems():
                        if flag_already_added[n]:
                            continue
                        if tx.is_coinbase() or not tx.is_final():
                            continue
                        # Transaction fee requirements, mainly only needed for flood control
                        # Under 10K (about 80 inputs) is free for first 100 transactions
                        # Base rate is 0.01 per KB
                        min_fee = tx.get_min_fee(
                            len(block.l_tx) < 100)  # 100 个交易内的打折,之后的不打折
                        tmp_test_pool = copy.deepcopy(
                            test_pool)  # 防止下面执行出错对test_pool产生干扰
                        ret = tx.connect_inputs(txdb, tmp_test_pool,
                                                Tx.PyDiskTxPos(1, 1, 1), 0,
                                                False, True, min_fee)
                        if ret is None:
                            continue
                        fees += ret  # 累积交易费
                        test_pool = tmp_test_pool

                        block.l_tx.append(tx)
                        block_size += tx.serialize_size(
                            serialize.SerType.SER_NETWORK)
                        flag_already_added[n] = True
                        found_something = True  # 这是为了跳出外层 while
                        n += 1
                        # end for
                        pass
                    pass  # end while
                txdb.close()
                pass
        # end critical_block
        pass
        block.bits = bits
        block.l_tx[0].l_out[0].value = block.get_block_value(fees)
        print("\n\nRunning Miner with %d transactions in block" %
              len(block.l_tx))

        # Prebuild hash buffer
        class Unnamed1(serialize.Serializable):
            class Unnamed2(serialize.Serializable):
                def __init__(self):
                    self.version = 0
                    self.hash_prev_block = 0
                    self.hash_merkle_root = 0
                    self.time = 0
                    self.bits = 0
                    self.nonce = 0

                def serialize(self, nType=0, nVersion=cfg.VERSION):
                    s = b''
                    s += serialize.ser_int(self.version)
                    s += serialize.ser_uint256(self.hash_prev_block)
                    s += serialize.ser_uint256(self.hash_merkle_root)
                    s += serialize.ser_uint(self.time)
                    s += serialize.ser_uint(self.bits)
                    s += serialize.ser_uint(self.nonce)
                    return s

            def __init__(self):
                self.block = Unnamed1.Unnamed2()
                self.padding0 = ['\x00'] * 64
                self.hash1 = 0
                self.padding1 = ['\x00'] * 64

        tmp = Unnamed1()
        tmp.block.version = block.version
        tmp.block.hash_prev_block = block.hash_prev_block = (
            index_prev.get_block_hash() if index_prev else 0)
        tmp.block.hash_merkle_root = block.hash_merkle_root = block.build_merkle_tree(
        )
        tmp.block.time = block.time = max(
            (index_prev.get_median_time_past() + 1 if index_prev else 0),
            timeutil.get_adjusted_time())
        tmp.block.bits = block.bits = bits  # difficulty
        tmp.block.nonce = block.nonce = 1  # 从1 开始计算

        # blocks0 = format_hash_blocks(tmp.block.serialize(), tmp.padding0)
        # blocks1 = format_hash_blocks(serialize.ser_uint256(tmp.hash1), tmp.padding1)

        # search
        start = timeutil.get_time()
        block_hash = 0
        hash_target = BN.PyBigNum.set_compact(block.bits).get_uint256()

        while True:
            if t.exit:
                break
            # use local sha256
            block_hash = cryptoutil.Hash(tmp.block.serialize())

            if block_hash <= hash_target:
                block.nonce = tmp.block.nonce
                assert block_hash == block.get_hash()
                # debug print
                print("Miner:")
                print("proof-of-work found  \n  hash: %s  \ntarget: %s\n" %
                      (serialize.hexser_uint256(block_hash),
                       serialize.hexser_uint256(hash_target)))
                print str(block)

                # TODO  setthreadpriority  THREAD_PRIORITY_NORMAL
                with ctx.mainLock:
                    # save key
                    kaction.add_key(key)

                    key.make_new_key()
                    # Process this block the same as if we had received it from another node
                    if not blkaction.process_block(None, block):
                        print(
                            "ERROR in CoinMiner, ProcessBlock, block not accepted"
                        )
                    else:
                        print("miner a block, waiting for relay")

                # TODO ADD THREAD_PRIORITY_LOWEST
                timeutil.sleep_msec(500)
                break

            # Update nTime every few seconds
            tmp.block.nonce += 1
            if tmp.block.nonce & 0x3FFFF == 0:
                # checkforshutdown
                if tmp.block.nonce == 0:
                    break
                if id(index_prev) != id(ctx.indexBest):
                    break
                if ctx.transactionsUpdated != transactions_updated_last and (
                        timeutil.get_time() - start > 60):
                    break
                if not ctx.fGenerateCoins:
                    break
                tmp.block.time = block.time = max(
                    (index_prev.get_median_time_past() + 1),
                    timeutil.get_adjusted_time())
            pass  # end nonce loop
        pass  # end whole loop
    return True