问题描述
问题根源分析
两个不同的验证者获取路径
- 获取指定区块头
- 创建该区块的快照
- 从快照中提取验证者列表
- 返回的验证者信息来自于区块头的 Extra 字段
验证者信息的更新机制
- 更新发生在每个 epoch 区块(通常是每 200 个区块)
- 调用 getCurrentValidators 从 BscValidatorSet 合约获取当前验证者
- 将验证者信息写入区块头的 Extra 字段
- 通过 updateValidatorSetV2 函数更新
- 更新发生在每个呼吸区块(每 24 小时一次)
- 从 StakeHub 合约获取最新的验证者选举信息并更新到 BscValidatorSet 合约
时间差导致的问题
- updateValidatorSetV2 每 24 小时执行一次,更新 BscValidatorSet 合约中的验证者列表为 1 个
- 区块头中的验证者信息只有在 epoch 区块(每 200 个区块)才会更新
- 如果最近的 epoch 区块发生在 updateValidatorSetV2 更新之前,区块头中仍然包含旧的 3 个验证者信息
- parlia.getValidators() 读取的是区块头中的信息,所以仍然返回 3 个验证者
时间线分析
验证者信息在区块头中的存储
解决方案
短期解决方案
- 直接调用合约方法:使用 BscValidatorSet.getValidators() 获取最新的验证者信息
- 等待下一个 epoch 区块:等待下一个 epoch 区块生成,区块头中的验证者信息会自动更新
长期解决方案
- 修改 API 接口:在 parlia.getValidators() API 中添加一个参数,允许直接从合约获取最新信息
- 调整更新频率:考虑修改 epoch 长度,使其与呼吸区块同步
- 添加缓存机制:在 API 层面添加缓存,优先返回最新的验证者信息