Example #1
0
    def block_check(self):
        # set current scanned block
        last_block = Block.last_block(db_session)
        if last_block:
            current_scanned_block = last_block.num
        else:
            current_scanned_block = cfg.startblock
            # check if no accounts created so we can skip to the most recent block
            with self.account_lock:
                acct_count = Account.count(db_session)
                if acct_count == 0:
                    current_scanned_block = get_current_block_number() - 1

        # check for reorgs and invalidate any blocks (and associated txs)
        block_num = current_scanned_block
        block = Block.from_number(db_session, current_scanned_block)
        if block:
            any_reorgs = False
            block_hash = get_block_hash(block_num)
            if not block_hash:
                self.logger.error("unable to get hash for block %d" %
                                  block_num)
                return
            while block_hash != block.hash:
                self.logger.info(
                    "block %d hash does not match current blockchain, must have been reorged"
                    % block_num)
                block.set_reorged(db_session)
                any_reorgs = True
                # decrement block_num, set new current_scanned_block
                block_num -= 1
                current_scanned_block = block_num
                # now do the previous block
                block = Block.from_number(db_session, block_num)
                if not block:
                    break
                block_hash = get_block_hash(block_num)
            if any_reorgs:
                db_session.commit()

        # get address list from db
        with self.account_lock:
            addresses = Account.all_active_addresses(db_session)

        # scan for new blocks
        current_block = get_current_block_number()
        while current_scanned_block < current_block and self.keep_running:
            block_num = current_scanned_block + 1
            start = time.time()
            block_hash, txs, tx_count = get_block_hash_and_txs(
                block_num, addresses)
            # check for reorged blocks now reorged *back* into the main chain
            block = Block.from_hash(db_session, block_hash)
            if block:
                self.logger.info("block %s (was #%d) now un-reorged" %
                                 (block_hash.hex(), block.num))
                block.num = block_num
                block.reorged = False
            else:
                block = Block(block_num, block_hash)
                db_session.add(block)
                db_session.flush()
            for key in txs.keys():
                self.logger.info("adding txs for " + key)
                for tx in txs[key]:
                    self.logger.info(" - %s, %s" %
                                     (tx["hash"].hex(), tx["value"]))
                Account.add_txs(db_session, key, block.id, txs[key])
            db_session.commit()
            current_scanned_block = block_num
            self.logger.info(
                "#block# %d scan took %f seconds (%d addresses, %d txs)" %
                (block_num, time.time() - start, len(addresses), tx_count))

        # scan for pending transactions
        start = time.time()
        txs, tx_count = scan_pending_txs(addresses)
        for key in txs.keys():
            self.logger.info("adding txs for " + key)
            for tx in txs[key]:
                self.logger.info(" - %s, %s" % (tx["hash"].hex(), tx["value"]))
            Account.add_txs(db_session, key, None, txs[key])
        db_session.commit()
        self.logger.info(
            "!pending! tx scan took %f seconds (%d addresses, %d txs)" %
            (time.time() - start, len(addresses), tx_count))
Example #2
0
        def blockloop():
            logger.info("ZapWeb blockloop started")

            # get last block from the db
            last_block = Block.last_block(db.session)
            if last_block:
                scanned_block_num = last_block.num
            else:
                scanned_block_num = cfg.start_block

            while 1:
                gevent.sleep(5)

                # check for reorgs and invalidate any blocks (and associated txs)
                block = Block.from_number(db.session, scanned_block_num)
                if block:
                    any_reorgs = False
                    blk_hash = block_hash(scanned_block_num)
                    if not blk_hash:
                        msg = f"unable to get hash (from node) for block {scanned_block_num}"
                        logger.error(msg)
                        utils.email_death(logger, msg)
                        sys.exit(1)
                    while blk_hash != block.hash:
                        logger.info("block %d hash does not match current blockchain, must have been reorged" % scanned_block_num)
                        block.set_reorged(db.session)
                        any_reorgs = True
                        # decrement scanned_block_num
                        scanned_block_num -= 1
                        # now do the previous block
                        block = Block.from_number(db.session, scanned_block_num)
                        if not block:
                            msg = f"unable to get hash (from db) for block {scanned_block_num}"
                            logger.error(msg)
                            utils.email_death(logger, msg)
                            sys.exit(1)
                        blk_hash = block_hash(scanned_block_num)
                    if any_reorgs:
                        db.session.commit()
            
                # scan for new blocks
                # use "block_height() - 1" because with the WavesNG protocol the block can have new transactions
                # added until the next block is found
                while block_height() - 1 > scanned_block_num:
                    block = block_at(scanned_block_num + 1)
                    res, reason = block_chk(block)
                    if not res:
                        logger.error(f"failed to get block at {scanned_block_num + 1} ({reason})")
                        break
                    blk_hash = block_hash(block)
                    # check for reorged blocks now reorged *back* into the main chain
                    dbblk = Block.from_hash(db.session, blk_hash)
                    if dbblk:
                        logger.info("block %s (was #%d) now un-reorged" % (blk_hash, dbblk.num))
                        dbblk.num = scanned_block_num + 1
                        dbblk.reorged = False
                    else:
                        dbblk = Block(block["timestamp"], block["height"], blk_hash)
                        db.session.add(dbblk)
                        db.session.flush()
                    # add transactions to db
                    if "transactions" in block:
                        for tx in block["transactions"]:
                            if tx["type"] == 4:
                                recipient = tx["recipient"]
                                asset_id = tx["assetId"]
                                if recipient == cfg.address and asset_id == cfg.asset_id:
                                    txid = tx["id"]
                                    logger.info(f"new tx {txid}")
                                    attachment = tx["attachment"]
                                    if attachment:
                                        attachment = base58.b58decode(attachment)
                                        logger.info(f"    {attachment}")
                                    invoice_id = utils.extract_invoice_id(logger, attachment)
                                    if invoice_id:
                                        logger.info(f"    {invoice_id}")
                                    dbtx = Transaction(txid, tx["sender"], recipient, tx["amount"], attachment, invoice_id, dbblk.id)
                                    db.session.add(dbtx)
                    scanned_block_num = block["height"]
                    logger.debug(f"scanned block {scanned_block_num}")
                    if scanned_block_num % 100 == 0:
                        db.session.commit()
                    gevent.sleep(0)
                db.session.commit()