From 8d7a35683e636e5d8728ec901a421322d6fa9b95 Mon Sep 17 00:00:00 2001 From: Hendrik Hofstadt Date: Sun, 25 Oct 2020 08:57:04 +0100 Subject: [PATCH] bridge: fix quorum (#56) --- ethereum/contracts/Wormhole.sol | 4 +++- solana/bridge/src/processor.rs | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ethereum/contracts/Wormhole.sol b/ethereum/contracts/Wormhole.sol index 78738996..61a20503 100644 --- a/ethereum/contracts/Wormhole.sol +++ b/ethereum/contracts/Wormhole.sol @@ -99,7 +99,9 @@ contract Wormhole is ReentrancyGuard { GuardianSet memory guardian_set = guardian_sets[vaa_guardian_set_index]; 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.keys.length / 4) * 3) + 1 <= len_signers, "no quorum"); + // For guardian sets < 3, the division by 3 evaluates to 0 and the quorum would not be calculated correctly + // 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 < 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; for (uint i = 0; i < len_signers; i++) { diff --git a/solana/bridge/src/processor.rs b/solana/bridge/src/processor.rs index 527975cc..db26f914 100644 --- a/solana/bridge/src/processor.rs +++ b/solana/bridge/src/processor.rs @@ -621,13 +621,17 @@ impl Bridge { return Err(ProgramError::InvalidAccountData); } - // Check quorum - if (sig_state + let signature_count = (sig_state .signatures .iter() .filter(|v| v.iter().filter(|v| **v != 0).count() != 0) - .count() as u8) - < (((guardian_set.len_keys / 4) * 3) + 1) + .count() as u8); + // Check quorum + // For guardian sets < 3, the division by 3 evaluates to 0 and the quorum would not be calculated correctly + // We fall back to the guardian set size as quorum for < 3, because 2/3+ for <3 is always the set size + if (guardian_set.len_keys < 3 && signature_count != guardian_set.len_keys) + || (guardian_set.len_keys >= 3 + && signature_count < (((guardian_set.len_keys / 3) * 2) + 1)) { return Err(ProgramError::InvalidArgument); }