如何修复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节点尚未完成初始化,区块评估器还未启动,无法处理交易池中的交易。自托管的新网络需要时间完成创世区块生成、节点初始化流程,测试脚本在节点完全就绪前就发起了交易,导致失败。
修复步骤
在测试前增加节点就绪等待逻辑
修改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()调整部署脚本的等待逻辑
修改setup.sh,在启动节点后增加等待时间,确保节点完全初始化后再运行测试:# 在启动节点的代码后添加 echo "等待节点初始化完成..." sleep 30 # 根据实际情况调整等待时间,比如30-60秒检查节点配置
确认节点配置文件(config.json)中EnableBlockEval参数为true(默认应为开启状态),如果被误设为false需要修改并重启节点:{ "EnableBlockEval": true }优化转账接口与测试的交易确认逻辑
当前接口在交易提交后立即等待确认,若节点未就绪会直接报错。可以调整为提交交易后返回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
相关产品推荐
相关产品推荐

