You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Algorand TransactionPool的no pending block evaluator错误?

修复Algorand自托管网络的「no pending block evaluator」错误

我正在尝试使用Algorand,计划通过单条命令自托管一个全新的网络,执行步骤如下:

$ git clone https://github.com/hermesloom/algorand-node-fly
$ cd algorand-node-fly
$ ./setup.sh 100 EUR

部署脚本最后会运行仓库中test.py的单元测试,其中test_04_transfer_funds测试用例代码如下:

def test_04_transfer_funds(self):
    """测试从创世账户向新测试账户转账"""
    try:
        # 创建接收测试资金的账户
        test_account = self.create_test_account()

        # 从创世账户转账到测试账户
        result = self.api_client.transfer(
            self.genesis_address,
            self.genesis_mnemonic,
            test_account["address"],
            self.test_transfer_amount,
            "Test transfer",
        )

        # 检查返回结果
        self.assertIn("tx_id", result)
        self.assertIn("status", result)
        tx_id = result["tx_id"]

        print(f"转账已发起,交易ID: {tx_id}")

        # 如果状态为pending,等待确认
        if result["status"] == "pending":
            print("交易处于pending状态,等待5秒确认...")
            time.sleep(5)

        # 查询测试账户余额,验证资金到账
        account_info = self.api_client.get_balance(
            test_account["address"], test_account["mnemonic"]
        )

        self.assertIn("balance", account_info)
        balance = account_info["balance"]

        # 测试账户余额应大于等于转账金额(可能更多)
        self.assertGreaterEqual(
            balance,
            self.test_transfer_amount,
            f"测试账户余额 {balance} 小于转账金额 {self.test_transfer_amount}"
        )

        print(f"测试账户收到 {balance} picoXDRs")

    except Exception as e:
        self.fail(f"转账及验证失败: {e}")

转账接口基于algosdk实现的代码如下:

@app.route("/api/transfer", methods=["POST"])
def transfer_funds():
    """通过助记词认证实现账户间转账"""
    # 基础限流
    client_ip = request.remote_addr
    if rate_limit(client_ip):
        return jsonify({"error": "Rate limit exceeded"}), 429

    try:
        data = request.get_json()
        sender_address = data.get("from")
        sender_mnemonic = data.get("mnemonic")
        receiver_address = data.get("to")
        amount = data.get("amount")
        note = data.get("note", "")

        # 验证输入字段
        if not all([sender_address, sender_mnemonic, receiver_address, amount]):
            return jsonify({"error": "缺少必填字段"}), 400

        try:
            amount = int(amount)
            if amount <= 0:
                raise ValueError("金额必须为正数")
        except ValueError:
            return jsonify({"error": "无效金额"}), 400

        # 验证助记词与发送方地址匹配
        if not validate_mnemonic(sender_mnemonic, sender_address):
            return jsonify({"error": "发送方地址对应的助记词无效"}), 403

        # 将助记词转换为私钥
        sender_private_key = mnemonic.to_private_key(sender_mnemonic)

        # 获取交易参数
        params = algod_client.suggested_params()

        # 创建并签名交易
        unsigned_txn = PaymentTxn(
            sender=sender_address,
            sp=params,
            receiver=receiver_address,
            amt=amount,
            note=note.encode() if note else None,
        )

        signed_txn = unsigned_txn.sign(sender_private_key)

        # 提交交易
        tx_id = algod_client.send_transaction(signed_txn)

        # 等待交易确认
        try:
            wait_for_confirmation(algod_client, tx_id)
            return jsonify({"tx_id": tx_id, "status": "confirmed"})
        except Exception as e:
            return jsonify({"tx_id": tx_id, "status": "pending", "error": str(e)}), 202

    except Exception as e:
        app.logger.error(f"转账错误: {e}")
        return jsonify({"error": f"转账失败: {str(e)}"}), 500

运行测试时出现以下错误:

FAIL: test_04_transfer_funds (__main__.AlgorandAPITest.test_04_transfer_funds)
Test transferring funds from genesis to a new test account.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/nalenz/Programmierung/algorand-node-fly/local/test.py", line 222, in test_04_transfer_funds
    result = self.api_client.transfer(
        self.genesis_address,
    ...<3 lines>...
        "Test transfer",
    )
  File "/Users/nalenz/Programmierung/algorand-node-fly/local/api_client.py", line 70, in transfer
    raise Exception(f"Error transferring funds: {response.text}")
Exception: Error transferring funds: {"error":"Failed to transfer funds: TransactionPool.Remember: TransactionPool.ingest: no pending block evaluator"}


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/nalenz/Programmierung/algorand-node-fly/local/test.py", line 260, in test_04_transfer_funds
    self.fail(f"Failed to transfer funds and verify: {e}")
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Failed to transfer funds and verify: Error transferring funds: {"error":"Failed to transfer funds: TransactionPool.Remember: TransactionPool.ingest: no pending block evaluator"}

问题原因及修复方案

原因分析

「no pending block evaluator」错误说明Algorand节点尚未完成初始化,区块评估器还未启动,无法处理交易池中的交易。自托管的新网络需要时间完成创世区块生成、节点初始化流程,测试脚本在节点完全就绪前就发起了交易,导致失败。

修复步骤

  1. 在测试前增加节点就绪等待逻辑
    修改test.py的测试用例,在发起转账前先检查节点状态,确认区块评估器已启动:

    def test_04_transfer_funds(self):
        """测试从创世账户向新测试账户转账"""
        try:
            # 新增:等待节点就绪
            print("等待Algorand节点初始化完成...")
            max_wait_time = 60  # 最多等待60秒
            wait_interval = 5
            elapsed_time = 0
            while elapsed_time < max_wait_time:
                try:
                    # 查询节点状态,确认区块高度正常增长
                    status = self.api_client.get_node_status()
                    if status.get("last-round", 0) > 0:
                        print(f"节点已就绪,当前区块高度: {status['last-round']}")
                        break
                except Exception:
                    pass
                time.sleep(wait_interval)
                elapsed_time += wait_interval
            else:
                self.fail(f"节点在{max_wait_time}秒内未就绪")
    
            # 原有的测试代码...
    

    同时需要在api_client.py中添加获取节点状态的方法:

    def get_node_status(self):
        response = self.session.get(f"{self.base_url}/api/v2/status")
        response.raise_for_status()
        return response.json()
    
  2. 调整部署脚本的等待逻辑
    修改setup.sh,在启动节点后增加等待时间,确保节点完全初始化后再运行测试:

    # 在启动节点的代码后添加
    echo "等待节点初始化完成..."
    sleep 30  # 根据实际情况调整等待时间,比如30-60秒
    
  3. 检查节点配置
    确认节点配置文件(config.json)中EnableBlockEval参数为true(默认应为开启状态),如果被误设为false需要修改并重启节点:

    {
      "EnableBlockEval": true
    }
    
  4. 优化转账接口与测试的交易确认逻辑
    当前接口在交易提交后立即等待确认,若节点未就绪会直接报错。可以调整为提交交易后返回pending状态,由测试脚本轮询等待:

    • 修改转账接口代码:
      # 替换原等待确认代码
      # try:
      #     wait_for_confirmation(algod_client, tx_id)
      #     return jsonify({"tx_id": tx_id, "status": "confirmed"})
      # except Exception as e:
      #     return jsonify({"tx_id": tx_id, "status": "pending", "error": str(e)}), 202
      
      # 修改为:
      return jsonify({"tx_id": tx_id, "status": "pending"}), 202
      
    • 在测试脚本中增加轮询确认逻辑,替代固定5秒等待:
      # 替换原pending等待代码
      if result["status"] == "pending":
          print("交易处于pending状态,轮询等待确认...")
          max_wait_time = 30
          wait_interval = 2
          elapsed_time = 0
          while elapsed_time < max_wait_time:
              try:
                  tx_info = self.api_client.get_transaction_info(tx_id)
                  if tx_info.get("confirmed-round") is not None:
                      print(f"交易已确认,区块高度: {tx_info['confirmed-round']}")
                      break
              except Exception:
                  pass
              time.sleep(wait_interval)
              elapsed_time += wait_interval
          else:
              self.fail(f"交易在{max_wait_time}秒内未确认")
      
    • 在api_client.py中添加获取交易信息的方法:
      def get_transaction_info(self, tx_id):
          response = self.session.get(f"{self.base_url}/api/v2/transactions/{tx_id}")
          response.raise_for_status()
          return response.json()
      

内容的提问来源于stack exchange,提问作者sigalor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:24:52