bridge: correctly calculate 2/3+ majority

Adds test vectors.

ghstack-source-id: 1f7e0d783f
Pull Request resolved: https://github.com/certusone/wormhole/pull/58
This commit is contained in:
Leo 2020-10-28 22:41:33 +01:00
parent 6c5b9875cf
commit 55fd671228
3 changed files with 47 additions and 3 deletions

View File

@ -5,7 +5,6 @@ import (
"crypto/ecdsa"
"encoding/hex"
"fmt"
"math"
"strings"
"time"
@ -218,7 +217,7 @@ func vaaConsensusProcessor(lockC chan *common.ChainLock, setC chan *common.Guard
}
// 2/3+ majority required for VAA to be valid - wait until we have quorum to submit VAA.
quorum := int(math.Ceil((float64(len(gs.Keys)) / 3) * 2))
quorum := CalculateQuorum(len(gs.Keys))
logger.Info("aggregation state for VAA",
zap.String("digest", hash),
@ -303,7 +302,7 @@ func checkDevModeGuardianSetUpdate(ctx context.Context, vaaC chan *vaa.VAA, gs *
defer cancel()
tx, err := devnet.SubmitVAA(timeout, *ethRPC, v)
if err != nil {
return fmt.Errorf("failed to submit devnet guardian set change: %v")
return fmt.Errorf("failed to submit devnet guardian set change: %v", err)
}
logger.Info("devnet guardian set change submitted to Ethereum", zap.Any("tx", tx), zap.Any("vaa", v))

View File

@ -0,0 +1,9 @@
package main
// CalculateQuorum returns the minimum number of have that needs to sign a VAA for a given guardian set.
//
// The canonical source is the calculation in the contracts (solana/bridge/src/processor.rs and
// ethereum/contracts/Wormhole.sol), and this needs to match the implementation in the contracts.
func CalculateQuorum(numGuardians int) int {
return ((numGuardians*10/3)*2)/10 + 1
}

View File

@ -0,0 +1,36 @@
package main
import (
"fmt"
"testing"
)
func TestCalculateQuorum(t *testing.T) {
tests := []struct {
have int
want int
}{
{have: 1, want: 1},
{have: 2, want: 2},
{have: 3, want: 3},
{have: 4, want: 3},
{have: 5, want: 4},
{have: 6, want: 5},
{have: 7, want: 5},
{have: 8, want: 6},
{have: 9, want: 7},
{have: 10, want: 7},
{have: 11, want: 8},
{have: 12, want: 9},
{have: 20, want: 14},
{have: 25, want: 17},
{have: 100, want: 67},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%d have", tt.have), func(t *testing.T) {
if got := CalculateQuorum(tt.have); got != tt.want {
t.Errorf("CalculateQuorum(%d) = %v, want %v", tt.have, got, tt.want)
}
})
}
}