예제 #1
0
    def parse_block(self, block_num):
        """
        解析区块的交易详情
        :return: 返回待推送信息列表
        """
        push_list = []
        block = self.rpc.get_block(block_num)
        timestamp = block["Header"]["Timestamp"]
        txs = self.rpc.get_smart_code_event(block_num)
        for tx in txs:
            # 不成功的不推送
            if tx["State"] != 1:
                continue

            for n in tx["Notify"]:
                # 只支持ont和ong的推送, 且只推送类型为transfer的交易
                if n["ContractAddress"] not in ["0100000000000000000000000000000000000000",
                                                "0200000000000000000000000000000000000000"] or \
                        n["States"][0] != "transfer":
                    continue
                mq_tx = G_PUSH_TEMPLATE.copy()
                mq_tx["BlockNumber"] = block_num
                mq_tx["Time"] = timestamp
                mq_tx["Txid"] = tx["TxHash"]
                mq_tx["Type"] = "ONT"
                mq_tx["From"] = n["States"][1]
                mq_tx["To"] = n["States"][2]
                mq_tx["Amount"] = n["States"][3]
                mq_tx["Contract"] = n["ContractAddress"]
                mq_tx["status"] = "true"
                push_list.append(mq_tx)
        return push_list
예제 #2
0
 def parse_block(self, block_num):
     """
     解析区块的交易详情
     :return: 返回待推送信息列表
     """
     while True:
         try:
             if isinstance(block_num, int):
                 block_num = hex(block_num)
             if isinstance(block_num,
                           str) and not block_num.startswith('0x'):
                 block_num = hex(int(block_num))
             block = self.rpc.get_block(block_num)
             txs = block.get("transactions", [])
             push_list = []
             for tx in txs:
                 tx_receipt = self.rpc.get_tx_receipt(tx.get("hash"))
                 mq_tx = G_PUSH_TEMPLATE.copy()
                 mq_tx["Txid"] = tx.get("hash")
                 mq_tx["Type"] = "TOMO"
                 mq_tx["From"] = tx.get("from")
                 mq_tx["To"] = tx.get("to")
                 mq_tx["Amount"] = int(tx.get("value"), 16)
                 mq_tx["Fee"] = int(tx["gasPrice"], 16) * int(
                     tx_receipt["gasUsed"], 16)
                 status = int(tx_receipt["status"], 16)
                 mq_tx["Valid"] = True if status else False
                 mq_tx["status"] = "true" if status else "false"
                 mq_tx["Time"] = int(block.get("timestamp"), 16)
                 mq_tx["BlockNumber"] = int(tx.get("blockNumber"), 16)
                 push_list.append(mq_tx)
             return push_list
         except Exception as e:
             G_LOGGER.info(f"出现异常,尝试重新获取。异常原因:{str(e)}")
             time.sleep(1)
예제 #3
0
 def parse_block(self, block_num):
     """
     解析区块的交易详情
     :return: 返回待推送信息列表
     """
     block_num -= 1
     block = self.http.get_block(block_num)
     current_block = block["data"][0] if "data" in block.keys() and len(block["data"]) > 0 else None
     push_list = []
     if current_block:
         txs = current_block["txes"]
         block_num = current_block["block"]["height"]
         for tx in txs:
             tx_type = tx["tx"]["type"]
             if tx_type == 257:
                 mq_tx = G_PUSH_TEMPLATE.copy()
                 mq_tx["Txid"] = tx["hash"]
                 mq_tx["Type"] = "NEM"
                 # 根据公钥得到地址
                 signer = tx["tx"]["signer"]
                 result = self.http.get_from_public_key(signer)
                 mq_tx["From"] = result["account"]["address"]
                 mq_tx["To"] = tx["tx"]["recipient"]
                 mq_tx["Amount"] = tx["tx"]["amount"]
                 mq_tx["Time"] = tx["tx"]["timeStamp"]
                 mq_tx["BlockNumber"] = block_num
                 mq_tx["status"] = "true"
                 push_list.append(mq_tx)
     return push_list
예제 #4
0
    def parse_block(self, block_num):
        """
        解析区块的交易列表
        :return: 返回待推送信息列表
        """
        block = self.rpc.get_block(block_num)
        txs = block["result"]["transactions"] if block else []

        tx_index = 0
        push_list = []
        for tx in txs:
            if tx.get("type") != "binary" or tx.get("status") != 1:
                continue
            mq_tx = G_PUSH_TEMPLATE.copy()
            mq_tx["BlockNumber"] = tx["block_height"]
            mq_tx["Time"] = tx["timestamp"]
            mq_tx["Txid"] = tx["hash"]
            mq_tx["Type"] = "NAS"
            mq_tx["From"] = tx["from"]
            mq_tx["To"] = tx["to"]
            mq_tx["Amount"] = tx["value"]
            mq_tx["TxIndex"] = tx_index
            push_list.append(mq_tx)
            tx_index += 1
        return push_list
예제 #5
0
 def parse_block(self, block_num):
     """
     解析区块的交易详情
     :return: 返回待推送信息列表
     """
     while True:
         try:
             block = self.rpc.get_block(block_num)
             txs = block.get("tx", [])
             push_list = []
             for tx in txs:
                 G_LOGGER.info("tx={}".format(tx))
                 mq_tx = G_PUSH_TEMPLATE.copy()
                 mq_tx["Txid"] = tx.get("txHash")
                 mq_tx["Type"] = "BNB"
                 mq_tx["From"] = tx.get("fromAddr")
                 mq_tx["To"] = tx.get("toAddr")
                 mq_tx["Amount"] = int(
                     float(tx.get("value") if tx.get("value") else 0) *
                     100000000)
                 mq_tx["Fee"] = int(
                     float(tx.get("txFee") if tx.get("txFee") else 0) *
                     100000000)
                 mq_tx["Valid"] = True
                 mq_tx["Time"] = utcstr_to_timestamp(
                     tx.get("timeStamp")) if tx.get("timeStamp") else 0
                 mq_tx["BlockNumber"] = tx.get("blockHeight")
                 mq_tx["TxIndex"] = 0
                 mq_tx["Memo"] = tx.get("memo") if tx.get("memo") else ""
                 G_LOGGER.info("mq_tx={}".format(mq_tx))
                 push_list.append(mq_tx)
             return push_list
         except Exception as e:
             G_LOGGER.info(f"出现异常,尝试重新获取。异常原因:{str(e)}")
             time.sleep(1)
예제 #6
0
 def parse_block(self, block_num):
     """
     解析区块的交易列表
     :return: 返回待推送信息列表
     """
     txs = self.rpc.get_block(block_num)
     push_list = []
     for tx in txs:
         mq_tx = G_PUSH_TEMPLATE.copy()
         tx_type = tx.get('type', '')
         if tx_type not in ('payment', 'create_account'):
             continue
         mq_tx["BlockNumber"] = block_num
         mq_tx["Time"] = date_z_to_timestamp(tx.get('created_at'))
         mq_tx["Txid"] = tx.get('transaction_hash')
         mq_tx["Type"] = "XLM"
         mq_tx["status"] = "true"
         if tx_type == 'payment':
             mq_tx['From'] = tx.get('from')
             mq_tx['To'] = tx.get('to')
             mq_tx['Amount'] = tx.get('amount')
         elif tx_type == 'create_account':
             mq_tx['From'] = tx.get('funder')
             mq_tx['To'] = tx.get('account')
             mq_tx['Amount'] = tx.get('starting_balance')
         push_list.append(mq_tx)
     return push_list
예제 #7
0
    def parse_block(self, block_num):
        """
        解析区块的交易列表
        :return: 返回待推送信息列表
        """
        block = self.rpc.get_block(block_num)
        block = block.get("block", {})
        txs = block.get("transactions", []) if block else []

        push_list = []
        for tx in txs:
            tx_receipt = tx.get("tx_receipt", {})
            actions = tx.get("actions", [])
            for i, act in enumerate(actions):
                contract, action_name, data = act.get("contract", ""), act.get(
                    "action_name", ""), act.get("data", "")
                if action_name in self.supported:
                    data = loads(data)
                    d_len = len(data)
                    _from, _to, _amount, _memo = "", "", 0, ""
                    if action_name == "transfer" and contract == "token.iost":
                        _token = data[0] if d_len > 0 else ""
                        if _token and _token == "iost":
                            contract = "iost"
                        else:
                            contract = _token
                        _from = data[1] if d_len > 1 else ""
                        _to = data[2] if d_len > 2 else ""
                        _amount = data[3] if d_len > 3 else ""
                        _memo = data[4] if d_len > 4 else ""
                    elif action_name in ["buy", "sell", "pledge", "unpledge"]:
                        if d_len < 4:
                            continue
                        contract = "iost"
                        _from = data[0] if d_len > 0 else ""
                        _to = data[1] if d_len > 1 else ""
                        _amount = data[2] if d_len > 2 else ""
                    else:
                        continue
                    mq_tx = G_PUSH_TEMPLATE.copy()
                    mq_tx["BlockNumber"] = block.get("number", "-1")
                    mq_tx["Time"] = block.get("time", "0")[:10]
                    mq_tx["Txid"] = tx.get("hash", "")
                    mq_tx["Type"] = "IOST"
                    mq_tx["From"] = _from
                    mq_tx["To"] = _to
                    mq_tx["Amount"] = _amount
                    mq_tx["Contract"] = contract
                    mq_tx["Memo"] = _memo
                    mq_tx["Fee"] = 0
                    mq_tx["Action"] = self.action_map.get(action_name, "")
                    mq_tx["VoutsIndex"] = i
                    status = tx_receipt.get("status_code", True)
                    mq_tx["Valid"] = True if status == "SUCCESS" else False
                    mq_tx[
                        "status"] = "true" if status == "SUCCESS" else "false"
                    push_list.append(mq_tx)
        return push_list
예제 #8
0
 def parse_block(self, block_num):
     """
     解析区块的交易列表
     :return: 返回待推送信息列表
     """
     block = self.rpc.get_block(block_num)
     txs = block["tx"] if block else []
     push_list = []
     for tx in txs:
         tx_type = tx.get("tx_type")
         if tx_type in ["BCOIN_TRANSFER_TX", "UCOIN_TRANSFER_TX"]:
             transfers = tx.get("transfers", [])
             for i, tran in enumerate(transfers):
                 if tran.get("coin_symbol") != "WICC":
                     continue
                 mq_tx = G_PUSH_TEMPLATE.copy()
                 mq_tx["BlockNumber"] = tx["confirmed_height"]
                 mq_tx["Time"] = block["time"]
                 mq_tx["Txid"] = tx["txid"]
                 mq_tx["Type"] = "WICC"
                 mq_tx["From"] = tx["from_addr"]
                 mq_tx["To"] = tran["to_addr"]
                 mq_tx["Amount"] = tran["coin_amount"]
                 mq_tx["Fee"] = tx.get("fees", "")
                 mq_tx["Memo"] = tx.get("memo", "")
                 mq_tx["Action"] = tx_type
                 mq_tx["VoutsIndex"] = i
                 mq_tx["status"] = "true"
                 push_list.append(mq_tx)
         else:
             mq_tx = G_PUSH_TEMPLATE.copy()
             mq_tx["BlockNumber"] = tx["confirmed_height"]
             mq_tx["Time"] = block["time"]
             mq_tx["Txid"] = tx["txid"]
             mq_tx["Type"] = "WICC"
             mq_tx["From"] = tx.get("from_addr", "")
             mq_tx["To"] = tx.get("to_addr", "")
             mq_tx["Amount"] = tx.get("coin_amount", "")
             mq_tx["Fee"] = tx.get("fees", "")
             mq_tx["Memo"] = tx.get("memo", "")
             mq_tx["Action"] = tx_type
             mq_tx["status"] = "true"
             push_list.append(mq_tx)
     return push_list
예제 #9
0
    def parse_normal_tx(self, tx_ids, mempool_tx=False, push_cache=None):
        """
        解析交易通过USDT节点
        """
        push_list = []
        tx_details = self.rpc.omni_get_transactions(tx_ids)

        for idx, tx_detail in enumerate(tx_details):
            if tx_detail is None:
                # 不过USDT交易
                continue
            mq_tx = G_PUSH_TEMPLATE.copy()
            mq_tx["Txid"] = tx_ids[idx]
            if self.rollback and push_cache and (mq_tx["Txid"] in push_cache):
                continue
            mq_tx["Type"] = self.coin_type
            mq_tx['Valid'] = tx_detail.get('valid', False)
            mq_tx['status'] = str(tx_detail.get('valid', "false")).lower()
            mq_tx['Fee'] = self.real_number(tx_detail.get("fee", "0"), self.wei, eng_string=True)

            if mempool_tx:
                mq_tx["Time"] = int(time.time())
                mq_tx["BlockNumber"] = 0
            else:
                mq_tx["Time"] = int(tx_detail.get("blocktime", time.time()))
                mq_tx["BlockNumber"] = self.current_height

            mq_tx['From'] = send_addr = tx_detail.get('sendingaddress')
            mq_tx['To'] = to_addr = tx_detail.get('referenceaddress')
            if send_addr is None or to_addr is None:
                continue

            subsends = tx_detail.get('subsends')
            if not subsends:
                mq_tx['Amount'] = self.real_number(tx_detail.get('amount', "0"), self.wei, eng_string=True)
                op_id = tx_detail.get('propertyid')
                if self.verify_op_id(op_id):
                    mq_tx['Contract'] = str(op_id)
                else:
                    continue
                push_list.append(mq_tx)
            else:
                for out_idx, sub in enumerate(subsends):
                    if not isinstance(sub, dict):
                        continue
                    mq_tx['Amount'] = sub.get('amount', "0")
                    op_id = sub.get('propertyid')
                    if self.verify_op_id(op_id):
                        mq_tx['Contract'] = str(op_id)
                    else:
                        continue
                    push_list.append(mq_tx)

        return push_list
예제 #10
0
 def parse_block(self, block_number):
     """
     解析区块的交易列表
     :return: 返回待推送信息列表
     """
     txs = self.rpc.get_block_transactions(block_number)
     push_list = []
     for tx in txs:
         mq_tx = G_PUSH_TEMPLATE.copy()
         tx_details = self.rpc.get_transactions(tx)
         mq_tx["BlockNumber"] = block_number
         mq_tx["Time"] = tx_details.get('meta', {}).get('blockTimestamp')
         mq_tx["Txid"] = tx
         mq_tx["Type"] = "VET"
         mq_tx['From'] = tx_details.get('origin')
         mq_tx['To'] = tx_details.get('clauses', [])[0].get('to')
         mq_tx['Amount'] = int(
             tx_details.get('clauses', [])[0].get('value'), 16)
         push_list.append(mq_tx)
예제 #11
0
 def parse_block(self, block_num):
     """
     解析区块的交易列表
     :return: 返回待推送信息列表
     """
     block = self.rpc.get_block(block_num)
     txs = block["data"]["transactions"]
     push_list = []
     for tx in txs:
         mq_tx = G_PUSH_TEMPLATE.copy()
         mq_tx["BlockNumber"] = block["data"]["height"]
         mq_tx["Time"] = block["data"]["timestamp"]
         mq_tx["Txid"] = tx["id"]
         mq_tx["Type"] = "BTM"
         vins = tx["inputs"]
         is_coinbase = False  # 是否挖矿交易
         input_amount = 0
         for i, vin in enumerate(vins):
             input_amount += vin.get("amount", 0)
             if vin["type"] == "coinbase":
                 is_coinbase = True
                 break
             if i == 0:
                 # 取第一个input中的address作为from地址
                 mq_tx["From"] = vin["address"] if "address" in vin.keys() else ""
         vouts = tx["outputs"]
         output_amount = 0
         for i, vout in enumerate(vouts):
             output_amount += vout.get("amount", 0)
             # 如果是挖矿交易,且交易类型不为control则不推送
             if is_coinbase or vout['type'] != 'control' or "address" not in vout.keys():
                 continue
             mq_tx = mq_tx.copy()
             mq_tx["To"] = vout["address"]
             mq_tx["Amount"] = vout["amount"]
             mq_tx["Contract"] = vout["asset_id"]
             mq_tx["VoutsIndex"] = i
             mq_tx["status"] = "true"
             push_list.append(mq_tx)
         for _push in push_list:
             _push["Fee"] = input_amount - output_amount
     return push_list
예제 #12
0
 def parse_block(self, block_num):
     """
     解析区块的交易详情
     :return: 返回待推送信息列表
     """
     block = None
     while True:
         try:
             block = self.rpc.get_block(block_num)
             ledger = block.get("ledger", []) if block else []
             txs = ledger.get("transactions", []) if ledger else []
             push_list = []
             for tx in txs:
                 if tx["TransactionType"] == "Payment" and isinstance(
                         tx['Amount'], str):
                     # 交易类型为Payment且状态为成功
                     mq_tx = G_PUSH_TEMPLATE.copy()
                     mq_tx["Txid"] = tx.get("hash", "")
                     mq_tx["Type"] = "XRP"
                     mq_tx["From"] = tx.get("Account", "")
                     mq_tx["To"] = tx.get("Destination", "")
                     mq_tx["Fee"] = tx.get("Fee", "")
                     mq_tx["Memo"] = tx.get("DestinationTag", "")
                     meta_data = tx.get("metaData", {})
                     status = meta_data.get("TransactionResult")
                     mq_tx["Valid"] = True if (
                         status and status == "tesSUCCESS") else False
                     mq_tx["status"] = "true" if (
                         status and status == "tesSUCCESS") else "false"
                     mq_tx["Amount"] = meta_data.get(
                         "delivered_amount", "0")
                     mq_tx["Time"] = ledger.get("close_time",
                                                0) + self.time_diff
                     mq_tx["BlockNumber"] = ledger.get("ledger_index", 0)
                     push_list.append(mq_tx)
             return push_list
         except Exception as e:
             G_LOGGER.info(
                 f"区块{block_num}出现异常,区块内容:{block},尝试重新获取。异常原因:{str(e)}")
             time.sleep(1)
예제 #13
0
    def parse_coinbase_tx(self, tx_id, mempool_tx=False, push_cache=None):
        """
        解析封装币基交易
        """
        if self.rollback and push_cache and (tx_id in push_cache):
            return []

        coinbase_list = []
        tx_detail = self.rpc.get_transaction(tx_id)

        mq_tx = G_PUSH_TEMPLATE.copy()
        mq_tx["Txid"] = tx_id
        mq_tx["Type"] = self.coin_type
        mq_tx["From"] = None
        mq_tx["Time"] = int(tx_detail["time"])
        mq_tx["BlockNumber"] = self.current_height

        total_out_value = 0
        coinbase_v_outs = tx_detail['vout']
        for v_out in coinbase_v_outs:
            tx_type = self.get_transaction_type(v_out)
            if not tx_type:
                continue
            v_out_address = self.get_vout_address(tx_type, v_out)
            if not v_out_address:
                continue
            v_out_value = self.get_handle_value(v_out)
            total_out_value += v_out_value
            tmp = mq_tx.copy()
            tmp["To"] = v_out_address
            tmp["Amount"] = str(v_out_value)
            tmp["VoutsIndex"] = v_out['n']
            tmp["status"] = "true"
            coinbase_list.append(tmp)

        return coinbase_list
예제 #14
0
    def parse_block(self, block_num):
        """
        解析区块的交易列表(支持多发送)
        :return: 返回待推送信息列表
        """
        while True:
            try:
                block = self.rpc.eth_get_block_by_number(block_num)
                if block is None:
                    raise Exception(f"获取到最新高度{block_num}区块详情为None,触发异常,尝试重新获取")
                G_LOGGER.info(
                    f"当前推送的区块:高度{int(block.get('number', '0x0'), 16)},哈希{block.get('hash', '')}"
                )
                self._check_uncle(block)
                # 遍历交易
                push_list = []
                if block.get("transactions") is None:
                    time.sleep(3)
                    continue
                tx_hashes = [tx["hash"] for tx in block["transactions"]]
                receipts = self.rpc.eth_get_transaction_receipt(
                    tx_hashes) if tx_hashes else []
                assert len(receipts) == len(block["transactions"])
                for i, tx in enumerate(block["transactions"]):
                    _input = tx.get('input', '')
                    _to = tx.get('to', '')
                    _from = tx.get('from', '')
                    multi_send_token = self.is_multi_send_token(_input)
                    mq_tx = G_PUSH_TEMPLATE.copy()
                    mq_tx["BlockNumber"] = hex_to_int(tx["blockNumber"])
                    mq_tx["Txid"] = tx["hash"]
                    mq_tx["Type"] = self.coin_type
                    mq_tx["From"] = tx["from"]
                    mq_tx["Time"] = block["timestamp"]
                    is_token_transfer = self._is_token(_input)
                    # 交易状态
                    mq_tx["Valid"] = self.get_status(receipts[i],
                                                     is_token_transfer)
                    mq_tx["status"] = self.get_tx_status(
                        receipts[i], is_token_transfer)
                    # 手续费
                    gas_price = tx.get("gasPrice", "0x0")
                    gas_used = receipts[i].get("gasUsed",
                                               "0x0") if receipts[i] else "0x0"
                    mq_tx["Fee"] = hex(int(gas_price, 16) * int(gas_used, 16))

                    if is_token_transfer:
                        if _from != _to:
                            tx['contract'] = _to
                        _to = self._get_token_to_address(_input)
                        _value = self._get_token_to_value(_input)
                        tx["to"] = _to if _to != "0x" else f"0x{'0'*40}"
                        tx["value"] = _value if _value != "0x" else "0x0"
                    elif multi_send_token:
                        continue
                        _len = self.multi_abi_len
                        _del_0x_input = del_0x(_input)
                        if multi_send_token == 'create':
                            # 多发送合约创建的交易,保存到数据库存起来
                            data = dict()
                            data['contract'] = tx['contract'] = tx['creates']
                            data['blockNumber'] = hex_to_int(tx["blockNumber"])
                            data['timestamp'] = block["timestamp"]
                            data['hash'] = tx["hash"]
                            # 保存合约
                            self.db.mysql.contract.insert_contract(data)
                            G_LOGGER.info(f"发现新的多发送合约{data['contract']}并保存")
                            continue
                        else:
                            token = ''
                            address_list = amount_list = []
                            # 不是我们自己的多发送合约则不处理
                            contract = self.db.mysql.contract.get_by_contract(
                                tx["to"])
                            if not contract:
                                continue
                            if multi_send_token == 'multisend':
                                _multisend_abi = del_0x(
                                    self.multi_abi_deal['multisend'])
                                result = self.parse_multi_data(
                                    _del_0x_input[len(_multisend_abi):])
                                address_count = hex_to_int(result[2])
                                address_list = result[3:3 + address_count]
                                amount_count = hex_to_int(
                                    result[3 + address_count])
                                amount_list = result[4 + address_count:4 +
                                                     address_count +
                                                     amount_count]
                            elif multi_send_token == 'multisendToken':
                                _multisend_token_abi = del_0x(
                                    self.multi_abi_deal['multisendToken'])
                                token = add_0x(
                                    self.parse_multi_data_pos(
                                        _del_0x_input, _multisend_token_abi,
                                        0))
                                result = self.parse_multi_data(
                                    _del_0x_input[len(_multisend_token_abi):])
                                address_count = hex_to_int(result[3])
                                address_list = result[4:4 + address_count]
                                amount_count = hex_to_int(
                                    result[4 + address_count])
                                amount_list = result[5 + address_count:5 +
                                                     address_count +
                                                     amount_count]
                            for k, v in enumerate(address_list):
                                mq_tx = mq_tx.copy()
                                mq_tx["To"] = v
                                mq_tx["Amount"] = int_to_hex(
                                    hex_to_int(amount_list[k]))
                                mq_tx["Contract"] = token
                                push_list.append(mq_tx)
                            return push_list
                    if tx["to"]:
                        mq_tx["To"] = tx["to"]
                        mq_tx["Amount"] = tx["value"]
                        if 'contract' in tx.keys():
                            mq_tx["Contract"] = tx["contract"]
                        push_list.append(mq_tx)
                return push_list
            except ForkError as ex:
                raise ForkError(ex.height, ex.msg)
            except Exception as ex:
                traceback.print_exc()
                G_LOGGER.info(f"获取块出现异常,尝试重新获取。异常原因:{str(ex)}")
            time.sleep(10)
예제 #15
0
 def parse_block(self, block_num):
     """
     解析区块的交易列表
     :return: 返回待推送信息列表
     """
     block = self.rpc.get_block(block_num)
     blocknumber = block.get("block_header", {}).get("raw_data",
                                                     {}).get("number", -1)
     block_timestamp = block.get("block_header",
                                 {}).get("raw_data",
                                         {}).get("timestamp", "")
     txs = block.get("transactions", []) if block else []
     push_list = []
     for tx in txs:
         # ret = tx.get("ret", [])
         status = tx.get("ret", [])[0].get("contractRet", "")
         if status != "SUCCESS":
             continue
         txid = tx.get("txID", "")
         raw_data = tx.get("raw_data", {})
         # timestamp_update = raw_data.get("timestamp", "")
         timestamp = block_timestamp
         contract = raw_data.get("contract", [])
         if not contract:
             continue
         else:
             contract = contract[0]
         transaction_type = contract.get("type", "")
         if transaction_type not in self.supported:
             continue
         transaction_data = contract.get("parameter", {}).get("value", {})
         _from = b58encode_check(
             bytes.fromhex(transaction_data.get("owner_address",
                                                ""))).decode()
         # contract_type = self.contract.get(transaction_type)
         if transaction_type == "TransferContract":
             _to = b58encode_check(
                 bytes.fromhex(transaction_data.get("to_address",
                                                    ""))).decode()
             _amount = transaction_data.get("amount", 0)
             contract_type = 0
         elif transaction_type == "FreezeBalanceContract":
             receiver_address = transaction_data.get("receiver_address", "")
             _to = b58encode_check(bytes.fromhex(
                 receiver_address)).decode() if receiver_address else _from
             _amount = transaction_data.get("frozen_balance", 0)
             contract_type = ""
         elif transaction_type == "UnfreezeBalanceContract":
             receiver_address = transaction_data.get("receiver_address", "")
             _to = b58encode_check(bytes.fromhex(
                 receiver_address)).decode() if receiver_address else _from
             _amount = transaction_data.get("frozen_balance", 0)
             contract_type = ""
         elif transaction_type == "TransferAssetContract":
             _from = b58encode_check(
                 bytes.fromhex(
                     transaction_data.get("owner_address"))).decode()
             _to = b58encode_check(
                 bytes.fromhex(
                     transaction_data.get("to_address"))).decode()
             asset_name = transaction_data.get("asset_name")
             contract_type = bytes.fromhex(asset_name).decode("utf-8")
             _amount = transaction_data.get("amount", 0)
         else:
             data = transaction_data.get("data")
             if data and data[:8] == "a9059cbb":
                 _amount = int(data[72:], 16)
                 _to = b58encode_check(
                     bytes.fromhex(f"41{data[32:72]}")).decode()
                 # after b58encode_check the legal address start with 0x41(mainnet) or 0xa0(testnet)
                 contract_address = contract.get("parameter", {}).get(
                     "value", {}).get("contract_address")
                 contract_type = b58encode_check(
                     bytes.fromhex(contract_address)).decode()
             else:
                 continue
         mq_tx = G_PUSH_TEMPLATE.copy()
         mq_tx["BlockNumber"] = blocknumber
         mq_tx["Time"] = int(timestamp) // 1000
         mq_tx["Txid"] = txid
         mq_tx["Type"] = "TRX"
         mq_tx["From"] = _from
         mq_tx["To"] = _to
         mq_tx["Amount"] = int(_amount)
         mq_tx["Contract"] = str(contract_type)
         mq_tx["Fee"] = 0
         mq_tx["Action"] = self.action_map[transaction_type]
         mq_tx["Valid"] = True if status == "SUCCESS" else False
         mq_tx["status"] = "true" if status == "SUCCESS" else "false"
         push_list.append(mq_tx)
     return push_list
예제 #16
0
    def parse_block(self, block_height):
        """
        解析区块的交易详情
        :return: 返回待推送信息列表
        """
        accounts = self.get_xmr_accounts()
        block_detail = self.rpc.get_block(block_height)
        if not block_detail:
            return []
        tx_ids = block_detail.get("tx_hashes", [])
        if not tx_ids:
            return []
        tx_details = self.rpc.get_transactions(tx_ids)
        push_list = []
        for tx_detail in tx_details:
            tx_as_json = tx_detail.get("as_json")
            block_timestamp = tx_detail.get("block_timestamp")
            tx_global_indexes = tx_detail['output_indices']
            txid = tx_detail.get("tx_hash")
            if not txid:
                continue
            tx_json = json.loads(tx_as_json)
            extra_list = tx_json['extra']
            extra = ''.join('{:02x}'.format(x) for x in extra_list)

            extra_mem = ctypes.c_char_p()
            extra_mem.value = extra.encode()

            tx_pub_key_mem = ctypes.create_string_buffer(100)
            tx_pub_key_result = self.monero_lib.monero_from_extra_get_tx_pub_key(
                extra_mem, tx_pub_key_mem)
            if not tx_pub_key_result:
                continue
            # G_LOGGER.info(f"height:{block_height} txid:{txid}")
            tx_vin = tx_json.get("vin", [])
            v_in_keys = [i['key'] for i in tx_vin]
            key_images = [i.get("k_image") for i in v_in_keys]
            tx_vout = tx_json.get("vout", [])
            rct_signatures = tx_json.get("rct_signatures")
            if not rct_signatures:
                continue
            ecdhInfos = rct_signatures.get("ecdhInfo")
            if not ecdhInfos:
                continue
            outPks = rct_signatures.get("outPk")
            if not outPks:
                continue
            tx_fee = rct_signatures.get("txnFee", '0')

            mq_tx = G_PUSH_TEMPLATE.copy()
            mq_tx["Txid"] = txid
            mq_tx["Type"] = "XMR"
            mq_tx["From"] = ""
            mq_tx["To"] = ""
            mq_tx["Amount"] = ""
            mq_tx["Memo"] = ""
            mq_tx["Fee"] = str(tx_fee)
            mq_tx["Valid"] = True
            mq_tx["status"] = "true"
            mq_tx["Time"] = block_timestamp
            mq_tx["BlockNumber"] = block_height
            mq_tx["VoutsIndex"] = 0

            v_in_address = []
            for key in key_images:
                if not key:
                    continue
                redis_key = key[:6] + key[18:24] + key[-6:]
                addr_info = self.redis.get_and_delete(redis_key)
                if not addr_info:
                    continue
                addr_info = json.loads(addr_info.decode())
                G_LOGGER.info(
                    f"height:{block_height}, txid:{txid}, key_image: {key}, addr_info: {addr_info}"
                )
                v_in_address.append(addr_info)

            v_out_infos = []
            for v_out_index, vout in enumerate(tx_vout):
                rct = outPks[v_out_index]
                global_index = tx_global_indexes[v_out_index]
                target = vout.get("target")
                if not target:
                    continue
                v_out_address = target.get("key")
                if not v_out_address:
                    continue
                random_utxo = {
                    "global_index": str(global_index),
                    "public_key": v_out_address,
                    "rct": rct
                }
                self.redis.push_utxo_cache(self.random_utxo_redis_key,
                                           random_utxo)
                for account in accounts:
                    address = account.get("addr")
                    private_view_key = account.get("pr_vk")
                    public_spend_key = account.get("pb_sk")

                    private_view_key_mem = ctypes.c_char_p()
                    private_view_key_mem.value = private_view_key.encode()
                    public_spend_key_mem = ctypes.c_char_p()
                    public_spend_key_mem.value = public_spend_key.encode()
                    derivation_mem = ctypes.create_string_buffer(256)
                    one_time_address_mem = ctypes.create_string_buffer(128)

                    amount_echo_init = ecdhInfos[v_out_index]
                    if not amount_echo_init:
                        continue
                    amount_echo = amount_echo_init.get("amount")
                    if not amount_echo:
                        continue
                    if address and str(address).startswith("8"):
                        additional_tx_pub_key_mem = ctypes.create_string_buffer(
                            100)
                        additional_tx_pub_key_result = self.monero_lib.monero_from_extra_get_additional_tx_pub_key(
                            extra_mem, 0, v_out_index,
                            additional_tx_pub_key_mem)
                        if not additional_tx_pub_key_result:
                            der_result = self.monero_lib.monero_generate_derivation_byte32(
                                tx_pub_key_mem, private_view_key_mem,
                                derivation_mem)
                        else:
                            der_result = self.monero_lib.monero_generate_derivation_byte32(
                                additional_tx_pub_key_mem,
                                private_view_key_mem, derivation_mem)
                    else:
                        der_result = self.monero_lib.monero_generate_derivation_byte32(
                            tx_pub_key_mem, private_view_key_mem,
                            derivation_mem)
                    if not der_result:
                        continue
                    address_result = self.monero_lib.monero_generate_one_time_public_key(
                        derivation_mem, public_spend_key_mem, v_out_index,
                        one_time_address_mem)
                    if not address_result:
                        continue
                    one_time_addr = (one_time_address_mem.value).decode()
                    # 判断是否命中
                    if v_out_address.strip() != one_time_addr.strip():
                        # G_LOGGER.info(f"Addr:{address}, height:{block_height}, txid:{txid}, out:{v_out_index} No")
                        continue
                    G_LOGGER.info(
                        f"Addr:{address}, height:{block_height}, txid:{txid}, out:{v_out_index} Yes"
                    )
                    amount_echo_mem = ctypes.c_char_p()
                    amount_echo_mem.value = amount_echo.encode()
                    real_amount_mem = ctypes.create_string_buffer(128)
                    # payment_id_mem = ctypes.create_string_buffer(32)

                    amount_result = self.monero_lib.monero_decrypt_amount(
                        derivation_mem, v_out_index, amount_echo_mem, 0,
                        real_amount_mem)
                    amount = '0'
                    if amount_result:
                        amount = (real_amount_mem.value).decode()
                        amount = int("0x" + amount, 0)
                    mq_tx["Amount"] = amount
                    # 暂时不推送memo信息,子地址不需要memo
                    # pyamentid_result = self.monero_lib.monero_from_extra_get_payment_id(extra_mem, derivation_mem, payment_id_mem)
                    # payment_id = '0'
                    # if pyamentid_result:
                    #     payment_id = (payment_id_mem.value).decode()
                    # tmp_tx["Memo"] = payment_id
                    tmp_tx = mq_tx.copy()
                    tmp_tx["Memo"] = ""
                    tmp_tx["VoutsIndex"] = v_out_index
                    tmp_tx["To"] = address
                    v_out_infos.append(tmp_tx)
                    break
            # if (not v_in_address) or (not v_out_infos):
            #     continue
            v_in_length = len(v_in_address)
            v_out_length = len(v_out_infos)
            G_LOGGER.info(
                f"height:{block_height}, txid:{txid}, v_in_length:{v_in_length}, v_out_length:{v_out_length}"
            )
            G_LOGGER.info(f"v_in_address: {v_in_address}")
            G_LOGGER.info(f"v_out_infos: {v_out_infos}")

            v_out_sort_infos = sorted(v_out_infos,
                                      key=lambda x: x["VoutsIndex"])

            max_len = max(v_out_length, v_in_length)
            for num in range(max_len):
                v_in_idx = num if num < v_in_length else -1
                v_out_idx = num if num < v_out_length else -1
                tx_tp = v_out_sort_infos[
                    v_out_idx] if v_out_length - 1 >= v_out_idx else v_out_sort_infos[
                        -1]
                tmp = tx_tp.copy()
                tmp['From'] = v_in_address[v_in_idx] if v_in_address else ''
                push_list.append(tmp)

        return push_list
예제 #17
0
 def parse_block(self, block_num):
     """
     解析区块的交易详情
     :return: 返回待推送信息列表
     """
     t1 = time.time()
     push_list = []
     node, block = self.http.get_block(block_num)
     t2 = time.time()
     if isinstance(block, str):
         # 出现大块,比如110588067,api.eossweden.org超级节点偶发性返回部分数据,不能被json反序列化,需要多次重试才能获得结果,造成消息积压
         # eos.greymass.com超级节点可以正确拿到数据,但是访问频率受限,所以异常以后要重试获取数据
         G_LOGGER.info(
             "eos_pass, block_num={}, node={}, lenght={}, head={}, tail={}".
             format(block_num, node, len(block), block[:38], block[-30:]))
         # self.redis.client.rpush("eos_pass_block", block_num)
         # return push_list
     timestamp = str(date_to_timestamp(block['timestamp'].split(".")[0]))
     txs = block.get("transactions", [])
     for tx in txs:
         tx_status = tx.get("status")
         if (not tx_status) or (tx_status not in ("executed")):
             continue
         trx = tx.get("trx", "")
         if not isinstance(trx, dict):
             continue
         tx_id = trx['id']
         transaction = trx["transaction"]
         acts = transaction.get('actions', [])
         act_index = 0
         get_amount_and_symbol = self.get_amount_and_symbol
         for act in acts:
             account, name, Contract = act.get('account'), act['name'], ""
             # if name in self.SUPPORTED and self.action_account.get(name) == account:
             if name in self.SUPPORTED:
                 data = act['data']
                 if not isinstance(data, dict):
                     continue
                 mq_tx = G_PUSH_TEMPLATE.copy()
                 if name == "delegatebw" and self.action_account.get(
                         name) != account:
                     from_addr = account
                     to_addr = data.get("to")
                     amount, symbol = get_amount_and_symbol(
                         "other_delegatebw", data)
                 elif name == "undelegatebw" and self.action_account.get(
                         name) != account:
                     from_addr = data.get("from")
                     to_addr = account
                     amount, symbol = get_amount_and_symbol(
                         "other_undelegatebw", data)
                 else:
                     from_addr = data.get(self.action_convert[name]['from'])
                     to_addr = data.get(self.action_convert[name]['to'])
                     if not from_addr or not to_addr:
                         continue
                     amount, symbol = get_amount_and_symbol(name, data)
                 # 无金额或者金额小于0.0001, 略过
                 if (not amount) or (float(amount) <= 0.0001):
                     continue
                 if account and str(
                         account) == "eosio.token" and symbol in ["EOS"]:
                     Contract = "eosio.token"
                 else:
                     Contract = str(account) + "|" + str(symbol).upper()
                 memo_info = data.get("memo", "")
                 mq_tx["BlockNumber"] = block_num
                 mq_tx["Time"] = timestamp
                 mq_tx["Txid"] = tx_id
                 mq_tx["Type"] = "EOS"
                 mq_tx['From'] = from_addr
                 mq_tx['To'] = to_addr
                 mq_tx['Amount'] = amount
                 mq_tx["Action"] = name
                 mq_tx['Contract'] = Contract
                 mq_tx["VoutsIndex"] = act_index
                 mq_tx["Memo"] = memo_info
                 mq_tx["Valid"] = True
                 mq_tx["status"] = "true"
                 push_list.append(mq_tx)
                 act_index += 1
     t3 = time.time()
     http_time = int((t2 - t1) * 1000) / 1000
     parse_time = int((t3 - t2) * 1000) / 1000
     G_LOGGER.info(
         "eos_parse_block, block_num={}, length={}, node={}, 网络耗时={}, 处理耗时={}"
         .format(block_num, len(push_list), node, http_time, parse_time))
     return push_list
예제 #18
0
 def parse_tx(self, tx, push_cache=None):
     """
     解析交易详情
     :param tx: 交易详情
     :return:
     """
     if not isinstance(tx, dict):
         return []
     mq_tx = G_PUSH_TEMPLATE.copy()
     mq_tx["Txid"] = del_0x(tx["txid"])
     if self.rollback and push_cache and (mq_tx["Txid"] in push_cache):
         return []
     mq_tx["Type"] = "NEO"
     push_list = []  # 待推送交易列表
     vins = tx["vin"]
     vin_address = []
     tx_index = 0  # 同笔交易中待推送的交易索引
     for vin in vins:
         tx_id = vin["txid"]
         vout = vin["vout"]
         vin_transactions = self.rpc.get_transaction(tx_id)
         for tran in vin_transactions["vout"]:
             address = tran["address"]
             n = tran["n"]
             if vout == n:
                 vin_address.append(address)
                 break
     vouts = tx["vout"]
     for i, vout in enumerate(vouts):
         mq_tx = mq_tx.copy()
         mq_tx["From"] = vin_address[0] if len(vin_address) > 0 else ""
         mq_tx["To"] = vout["address"]
         mq_tx["status"] = "true"
         mq_tx["Amount"] = vout["value"]
         mq_tx["Contract"] = del_0x(vout["asset"])
         if vout["address"] not in vin_address:
             mq_tx["TxIndex"] = tx_index
             push_list.append(mq_tx)
             tx_index += 1
     # 如果是NEP5资产,还需要调用getapplicationlog查询交易详情
     if tx["type"] == "InvocationTransaction":
         result = self.rpc.get_application_log(tx["txid"])
         if result:
             result = result.get("executions")
             result = result[0] if result and len(result) > 0 else {}
             vmstate = result.get("vmstate")
             notifications = result.get("notifications", [])
             if vmstate and vmstate.find("FAULT") == -1:
                 for ns in notifications:
                     contract = ns.get("contract")
                     state_type = ns["state"]["type"]
                     state_value = ns["state"]["value"]
                     if state_type == "Array":
                         event_type = state_value[0]["type"]
                         event_value = state_value[0]["value"]
                         if event_type == "ByteArray":
                             event_value = bytes.fromhex(event_value).decode()
                         if event_value == "transfer":
                             from_type = state_value[1]['type']
                             from_value = state_value[1]['value']
                             to_type = state_value[2]["type"]
                             to_value = state_value[2]["value"]
                             amount_type = state_value[3]["type"]
                             amount_value = state_value[3]["value"]
                             if from_type == 'ByteArray':
                                 from_value = b58encode_check(b'\x17' + hex_to_bytes(from_value)).decode()
                             if to_type == "ByteArray":
                                 to_value = b58encode_check(b"\x17" + hex_to_bytes(to_value)).decode()
                             if amount_type == "ByteArray":
                                 amount_value = str(hex_to_int(size_convert(amount_value)))
                             mq_tx = mq_tx.copy()
                             mq_tx["From"] = from_value
                             mq_tx["To"] = to_value
                             mq_tx["status"] = "true"
                             mq_tx["Amount"] = amount_value
                             mq_tx["Contract"] = del_0x(contract)
                             if to_value not in vin_address:
                                 mq_tx["TxIndex"] = tx_index
                                 push_list.append(mq_tx)
                                 tx_index += 1
     return push_list
예제 #19
0
    def parse_normal_tx(self, tx_details, mempool_tx=False, push_cache=None):
        """
        解析封装普通交易
        """
        push_list = []
        total_fees = 0
        for tx_detail in tx_details:
            mq_tx = G_PUSH_TEMPLATE.copy()
            mq_tx["Txid"] = tx_detail['txid']
            if self.rollback and push_cache and (mq_tx["Txid"] in push_cache):
                continue
            mq_tx["Type"] = self.coin_type
            mq_tx["status"] = "true"
            if mempool_tx:
                mq_tx["Time"] = int(time.time())
                mq_tx["BlockNumber"] = 0
            else:
                mq_tx["Time"] = int(tx_detail["time"])
                mq_tx["BlockNumber"] = self.current_height

            v_in_list = tx_detail['vin']
            v_in_addresses = []
            v_in_infos = []
            for v_in in v_in_list:
                scriptSig = v_in.get('scriptSig')
                txid = v_in.get('txid')
                if txid:
                    v_in_infos.append(dict(txid=txid, index=v_in.get('vout', 0)))
                if not scriptSig:
                    continue
                v_in_address = self.get_address_from_scriptsig(scriptSig['hex'])
                if not v_in_address:
                    continue
                v_in_addresses.append(v_in_address)

            v_out_list = tx_detail['vout']
            out_infos = []
            total_out_value = 0
            for v_out in v_out_list:
                info = {}
                v_out_value = self.get_handle_value(v_out)
                total_out_value += v_out_value

                tx_type = self.get_transaction_type(v_out)
                if not tx_type:
                    continue
                v_out_address = self.get_vout_address(tx_type, v_out)
                if not v_out_address:
                    continue
                v_out_index = v_out['n']
                if v_out_address in v_in_addresses:
                    # 标记找零
                    info['Charge'] = True
                info['To'] = v_out_address
                info['Amount'] = str(v_out_value)
                info["VoutsIndex"] = v_out_index
                out_infos.append(info)
            # 计算交易手续费
            tx_fee = self.get_tx_fee(v_in_infos, total_out_value)
            total_fees += tx_fee
            # 到此只缺FROM
            if not out_infos:
                continue
            v_in_length = len(v_in_addresses)
            v_out_length = len(out_infos)

            v_out_infos = sorted(out_infos, key=lambda x: x["VoutsIndex"])

            max_len = max(v_out_length, v_in_length)
            for num in range(max_len):
                v_in_idx = num if num < v_in_length else -1
                v_out_idx = num if num < v_out_length else -1

                tx_tp = mq_tx.copy()
                tx_tp.update(v_out_infos[v_out_idx]) if v_out_length - 1 >= v_out_idx else tx_tp.update(v_out_infos[-1])
                tx_tp['From'] = v_in_addresses[v_in_idx] if v_in_addresses else ''
                tx_tp['Fee'] = str(tx_fee)
                push_list.append(tx_tp)

        return push_list, total_fees
예제 #20
0
    def parse_tx(self, tx_ids):
        """
        解析交易详情
        :param tx_ids: 交易ids
        :return:
        """
        push_list = []
        for tx_id in tx_ids:
            # 根据tx_id查询交易详情
            tx = self.rpc.get_transaction(tx_id)
            # 获取operations下的第一个type字段(交易类型)
            tx_type = tx[1]["trx"]["operations"][0]["type"]
            asset_id = tx[1]["trx"]["alp_inport_asset"]["asset_id"]
            if tx_type == "transaction_op_type":
                # 合约交易
                tx = self.rpc.get_pretty_contract_transaction(tx_id)
            elif asset_id == 0:
                """
                已知tx_type
                withdraw_op_type: ACT Transfer (1f279cf35e8ec5cc785642bf06c57b1ba33a645b)
                deposit_op_type: ACT Transfer
                define_slate_op_type: ACT Transfer (09749dbf3aba3a54a5a5ac6f1723869becaf2b32)
                withdraw_pay_op_type: Agent Gets Paid (d81726e747a4e7c14ef12839cfb0dbd68117757f)
                register_account_op_type: Account Registration (f2de809451b084e8d80758efa7949d7ec8e80036)
                """
                # ACT交易
                tx = self.rpc.get_pretty_transaction(tx_id)
            else:
                G_LOGGER.info(
                    f"unkown asset_id:{str(id)}, tx_type:{tx_type}, hash:{tx_id}"
                )
                continue
            tx["tx_type"] = tx_type

            mq_tx = G_PUSH_TEMPLATE.copy()
            mq_tx["Type"] = "ACT"
            mq_tx["BlockNumber"] = tx["block_num"]
            mq_tx["Time"] = date_to_timestamp(tx["timestamp"])
            mq_tx["TxIndex"] = 0
            # 只要转账的合约交易
            if tx["tx_type"] == "transaction_op_type":
                reserved = tx["reserved"]
                if reserved and tx["reserved"][0] == "transfer_to":
                    # 区块链浏览器普遍使用该交易ID
                    mq_tx["Txid"] = tx["orig_trx_id"]
                    # 发起转账的地址
                    mq_tx["From"] = tx['to_contract_ledger_entry'][
                        'from_account']
                    # 转账金额
                    mq_tx["Amount"] = tx["to_contract_ledger_entry"]["amount"][
                        "amount"]
                    # 合约地址
                    mq_tx["Contract"] = tx["to_contract_ledger_entry"][
                        "to_account"]
                    # 合约执行函数
                    if reserved[1].find("|") > -1:
                        # 合约转账金额
                        mq_tx["Amount"] = reserved[1].split("|")[1]
                        # 实际合约转账地址
                        mq_tx["To"] = reserved[1].split("|")[0]
                    else:
                        mq_tx["To"] = reserved[1]
            else:
                # 交易id
                mq_tx["Txid"] = tx["trx_id"]
                # 发起转账的地址
                mq_tx["From"] = tx['ledger_entries'][0]['from_account']
                # 接收转账的地址
                mq_tx["To"] = tx["ledger_entries"][0]["to_account"]
                # 转账金额
                mq_tx["Amount"] = tx["ledger_entries"][0]["amount"]["amount"]
            mq_tx["status"] = "true"
            push_list.append(mq_tx)
        return push_list
예제 #21
0
 def parse_block(self, block_num):
     """
     解析区块的交易列表
     """
     try:
         block = self.rpc.eth_get_block_by_number(block_num)
         if block is None:
             raise Exception(f"获取区块高度{block_num}区块详情为None,触发异常,尝试重新获取")
         G_LOGGER.info(
             f"当前推送的区块:高度{int(block.get('number', '0x0'), 16)},哈希{block.get('hash', '')}"
         )
         self._check_uncle(block)
         # 遍历交易
         push_list = []
         if block.get("transactions") is None:
             raise Exception(
                 f"获取区块高度{block_num}区块transactions为None,触发异常,尝试重新获取")
         tx_hashes = [tx["hash"] for tx in block["transactions"]]
         receipts = self.rpc.eth_get_transaction_receipt(
             tx_hashes) if tx_hashes else []
         assert len(receipts) == len(block["transactions"])
         for i, tx in enumerate(block["transactions"]):
             _input = tx.get('input', '')
             _to = tx.get('to', '')
             _from = tx.get('from', '')
             is_token_transfer = self._is_token(_input)
             if is_token_transfer:
                 if _from != _to:
                     tx['contract'] = _to
                 _to = self._get_token_to_address(_input)
                 _value = self._get_token_to_value(_input)
                 tx["to"] = _to if _to != "0x" else f"0x{'0'*40}"
                 tx["value"] = _value if _value != "0x" else "0x0"
             mq_tx = G_PUSH_TEMPLATE.copy()
             mq_tx["BlockNumber"] = int(tx["blockNumber"], 16)
             mq_tx["Txid"] = tx["hash"]
             mq_tx["Type"] = self.coin_type
             mq_tx["From"] = tx["from"]
             # 排除to为空的
             if not tx["to"]:
                 continue
             mq_tx["To"] = tx["to"]
             mq_tx["Time"] = block["timestamp"]
             mq_tx["Amount"] = tx["value"]
             # 手续费
             gas_price = tx.get("gasPrice", "0x0")
             gas_used = receipts[i].get("gasUsed",
                                        "0x0") if receipts[i] else "0x0"
             mq_tx["Fee"] = hex(int(gas_price, 16) * int(gas_used, 16))
             # 交易状态
             mq_tx["Valid"] = self.get_status(receipts[i],
                                              is_token_transfer)
             mq_tx["status"] = self.get_tx_status(receipts[i],
                                                  is_token_transfer)
             if 'contract' in tx.keys():
                 mq_tx["Contract"] = tx["contract"]
             push_list.append(mq_tx)
         # 缓存已推送的区块高度和hash
         self.db.redis.save_cache_block(hex_to_int(block["number"]),
                                        block["hash"])
         return push_list
     except ForkError as ex:
         raise ForkError(ex.height, ex.msg)
     except Exception as e:
         traceback.print_exc()
         G_LOGGER.info(f"获取块出现异常,尝试重新获取。异常原因:{str(e)}")