import asyncio import inspect from datetime import datetime from public.times import Times from init import Init class Report(Init): def __init__(self, coin): super().__init__(coin, "report") async def query_mysql_last_height(self): sql = f"SELECT MAX(height) AS max_height FROM {self.coin}_blkreportprofitv2;" data = await self.distribution.exec(sql) if not data or data[0]["max_height"] is None: raise ValueError(f"{self.coin}当前无报块记录") return data[0]["max_height"] async def query_redis_last_height(self): data = await self.redis.get(f"{self.coin}:last_check") if not data: result = await self.query_mysql_last_height() await self.redis.set(f"{self.coin}:last_check", result) print(f"redis中无{self.coin} last_check数据,采用最后一个报块高度!") return result return int(data) async def query_chain_last_height(self): return int(await self.node.getblockcount()) async def insert_blkreportprofit(self, data): sql = f""" INSERT INTO {self.coin}_blkreportprofitv2 (date, height, hash, reward, fees, state) VALUES """ values = [] for item in data: sql += "(?,?,?,?,?,?)," values.extend([ item["date"], item["height"], item["hash"], item["reward"], item["fees"], 0 ]) sql = sql.rstrip(",") await self.distribution.exec_transaction(sql, values) async def main(self): redis_height, chain_height = await asyncio.gather( self.query_redis_last_height(), self.query_chain_last_height() ) if chain_height < redis_height: print(f"{self.coin}节点同步出错,节点高度{chain_height},last_check{redis_height}") return if chain_height == redis_height: print(f"{self.coin}当前节点和last_check高度一致,无需校验") return suc_data = [] for height in range(redis_height + 1, chain_height + 1): check_result = await self.node.verify_block(height, self.REPORT_ADDRESS) if not check_result: continue block_ret = self.node.block(check_result) if inspect.isawaitable(block_ret): block = await block_ret else: block = block_ret suc_data.append({ "date": Times.utcTime(block["time"] * 1000), "height": block["height"], "hash": block["hash"], "reward": str(block["block_reward"]), "fees": block["block_fees"] }) if not suc_data: print(f"{redis_height} - {chain_height} 无报块") await self.redis.set(f"{self.coin}:last_check", chain_height) return await self.insert_blkreportprofit(suc_data) await self.redis.set(f"{self.coin}:last_check", chain_height) class ReportEnx(Report): async def query_blkstats(self, height): yesterday = Times.utcTime( int(datetime.now().timestamp() * 1000) - 86400000 ).split(" ")[0].replace("-", "") table1 = "enx_pool_blkstats" table2 = f"enx_pool_blkstats_{yesterday}" exist_sql = "SHOW TABLES LIKE %s;" exist = await self.pooldb.exec(exist_sql, [table2]) if not exist: sql = f"SELECT date, height, hash FROM {table1} WHERE height > %s;" return await self.pooldb.exec(sql, [height]) sql = f""" SELECT date, height, hash FROM {table1} WHERE height > %s UNION ALL SELECT date, height, hash FROM {table2} WHERE height > %s; """ return await self.pooldb.exec(sql, [height, height]) async def query_blkreportprofit(self): sql = f"SELECT MAX(height) AS max_height FROM {self.coin}_blkreportprofitv2;" data = await self.distribution.exec(sql) if not data or data[0]["max_height"] is None: return 0 return data[0]["max_height"] async def insertinto_blkreportprofit(self, data): sql = f""" INSERT INTO {self.coin}_blkreportprofitv2 (date, height, hash, reward, fees, state) VALUES """ values = [] for item in data: sql += "(?,?,?,?,?,?)," values.extend([ item["date"], item["height"], item["hash"], item["reward"], 0, 1 ]) sql = sql.rstrip(",") await self.distribution.exec_transaction(sql, values) async def main(self): last_height = await self.query_blkreportprofit() data = await self.query_blkstats(last_height) if not data: print(f"{self.coin} 无报块") return block_data = [ { "date": item["date"], "height": item["height"], "hash": item["hash"], "reward": 333 } for item in data ] await self.insertinto_blkreportprofit(block_data) __all__ = ["Report", "ReportEnx"]