bridge: fix quorum calculation (#69)

This commit is contained in:
Hendrik Hofstadt 2020-10-28 21:22:15 +01:00 committed by GitHub
parent cf90bbec0d
commit dadb287220
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 5 additions and 9 deletions

View File

@ -99,9 +99,8 @@ contract Wormhole is ReentrancyGuard {
GuardianSet memory guardian_set = guardian_sets[vaa_guardian_set_index]; GuardianSet memory guardian_set = guardian_sets[vaa_guardian_set_index];
require(guardian_set.keys.length > 0, "invalid guardian set"); require(guardian_set.keys.length > 0, "invalid guardian set");
require(guardian_set.expiration_time == 0 || guardian_set.expiration_time > block.timestamp, "guardian set has expired"); require(guardian_set.expiration_time == 0 || guardian_set.expiration_time > block.timestamp, "guardian set has expired");
// For guardian sets < 3, the division by 3 evaluates to 0 and the quorum would not be calculated correctly // We're using a fixed point number transformation with 1 decimal to deal with rounding.
// We fall back to the guardian set size as quorum for < 3, because 2/3+ for <3 is always the set size require(((guardian_set.keys.length * 10 / 3) * 2) / 10 + 1 <= len_signers, "no quorum");
require((guardian_set.keys.length < 3 && len_signers == guardian_set.keys.length) || (len_signers >= 3 && ((guardian_set.keys.length / 3) * 2) + 1 <= len_signers), "no quorum");
int16 last_index = - 1; int16 last_index = - 1;
for (uint i = 0; i < len_signers; i++) { for (uint i = 0; i < len_signers; i++) {

View File

@ -627,12 +627,9 @@ impl Bridge {
.filter(|v| v.iter().filter(|v| **v != 0).count() != 0) .filter(|v| v.iter().filter(|v| **v != 0).count() != 0)
.count() as u8); .count() as u8);
// Check quorum // Check quorum
// For guardian sets < 3, the division by 3 evaluates to 0 and the quorum would not be calculated correctly // We're using a fixed point number transformation with 1 decimal to deal with rounding.
// We fall back to the guardian set size as quorum for < 3, because 2/3+ for <3 is always the set size // The cast to u16 exists to prevent issues where len_keys * 10 might overflow.
if (guardian_set.len_keys < 3 && signature_count != guardian_set.len_keys) if (signature_count as u16) < ((((guardian_set.len_keys as u16) * 10 / 3) * 2) / 10 + 1) {
|| (guardian_set.len_keys >= 3
&& signature_count < (((guardian_set.len_keys / 3) * 2) + 1))
{
return Err(ProgramError::InvalidArgument); return Err(ProgramError::InvalidArgument);
} }