让我们定义一个名为 verify_signatures()
的辅助函数,它检查提供的每个签名的有效性,并拒绝任何无效的签名,确保所有签名都是唯一的。
将签名验证辅助函数复制到您的 main.sw 中:
fn verify_signature(i: u64) -> u64 {
// Discard any out of bounds signatures
if (i >= tx_witnesses_count()) {
return 0;
}
let tx_hash = tx_id();
let mut j = 0;
while j < 3 {
let current_signature = tx_witness_data::<B512>(j);
let current_address = ec_recover_address(current_signature, tx_hash).unwrap();
if current_address == SIGNERS[i] {
return 1;
}
j += 1;
}
return 0;
}
如前所述,我们将利用交易见证和交易哈希来验证每个签名,将它们与之前配置的钱包进行匹配。
参数 i
:此参数表示预定义的签名者列表中的一个签名者的索引,该列表在可配置项中定义。它用于识别函数当前正在尝试验证的签名者的签名。
签名验证循环:然后,函数进入一个循环,迭代至多三次。此循环表示尝试根据附加到交易的最多三个见证数据(签名)来验证签名。
签名恢复:在循环内,对于由 j
定义的每次迭代,它使用 tx_witness_data::<B512>(j)
从交易的见证数据中检索当前签名(current_signature
)。然后,它尝试使用 ec_recover_address
函数从当前签名和交易哈希作为输入来恢复生成此签名的地址(current_address
)。
地址匹配:在恢复地址后,函数检查此地址是否与 SIGNERS
列表中第 i
个签名者的地址匹配。如果找到匹配项,则意味着成功验证了一个签名者的签名,并且函数返回 1
。
while j < 3 {
let current_signature = tx_witness_data::<B512>(j);
let current_address = ec_recover_address(current_signature, tx_hash).unwrap();
if current_address == SIGNERS[i] {
return 1;
}
j += 1;
}
return 0;
i
个签名者的匹配签名,则函数返回 1
,表示验证成功。如果在检查最多三个签名后找不到匹配的签名,则函数返回 0
,表示无法验证第 i
个签名者的签名。 这样可以灵活地进行签名验证,适应了签名者可以以任何顺序呈现所需签名的情况,并确保每个签名都被唯一地记录,而不允许来自同一钱包的重复签名。