mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-11 22:37:11 +00:00
(squash this) begin addressing PR comments
This commit is contained in:
parent
aab26c3ff7
commit
00db469fc0
@ -31,6 +31,7 @@ func getIndex(pk crypto.PubKey, keys []crypto.PubKey) int {
|
||||
}
|
||||
|
||||
// AddSignature adds a signature to the multisig, at the corresponding index.
|
||||
// If the signature already exists, replace it.
|
||||
func (mSig *Multisignature) AddSignature(sig []byte, index int) {
|
||||
newSigIndex := mSig.BitArray.NumOfTrueBitsBefore(index)
|
||||
// Signature already exists, just replace the value there
|
||||
@ -64,5 +65,5 @@ func (mSig *Multisignature) AddSignatureFromPubkey(sig []byte, pubkey crypto.Pub
|
||||
|
||||
// Marshal the multisignature with amino
|
||||
func (mSig *Multisignature) Marshal() []byte {
|
||||
return cdc.MustMarshalBinary(mSig)
|
||||
return cdc.MustMarshalBinaryBare(mSig)
|
||||
}
|
||||
|
@ -14,7 +14,11 @@ type ThresholdMultiSignaturePubKey struct {
|
||||
var _ crypto.PubKey = &ThresholdMultiSignaturePubKey{}
|
||||
|
||||
// NewThresholdMultiSignaturePubKey returns a new ThresholdMultiSignaturePubKey.
|
||||
// Panics if len(pubkeys) < k or 0 >= k.
|
||||
func NewThresholdMultiSignaturePubKey(k int, pubkeys []crypto.PubKey) crypto.PubKey {
|
||||
if k <= 0 {
|
||||
panic("threshold k of n multisignature: k <= 0")
|
||||
}
|
||||
if len(pubkeys) < k {
|
||||
panic("threshold k of n multisignature: len(pubkeys) < k")
|
||||
}
|
||||
@ -29,12 +33,21 @@ func NewThresholdMultiSignaturePubKey(k int, pubkeys []crypto.PubKey) crypto.Pub
|
||||
// a concern.
|
||||
func (pk *ThresholdMultiSignaturePubKey) VerifyBytes(msg []byte, marshalledSig []byte) bool {
|
||||
var sig *Multisignature
|
||||
err := cdc.UnmarshalBinary(marshalledSig, &sig)
|
||||
err := cdc.UnmarshalBinaryBare(marshalledSig, &sig)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
size := sig.BitArray.Size()
|
||||
if len(sig.Sigs) < int(pk.K) || len(pk.Pubkeys) != size || sig.BitArray.NumOfTrueBitsBefore(size) < int(pk.K) {
|
||||
// ensure bit array is the correct size
|
||||
if len(pk.Pubkeys) != size {
|
||||
return false
|
||||
}
|
||||
// ensure size of signature list
|
||||
if len(sig.Sigs) < int(pk.K) || len(sig.Sigs) > size {
|
||||
return false
|
||||
}
|
||||
// ensure at least k signatures are set
|
||||
if sig.BitArray.NumOfTrueBitsBefore(size) < int(pk.K) {
|
||||
return false
|
||||
}
|
||||
// index in the list of signatures which we are concerned with.
|
||||
@ -63,16 +76,17 @@ func (pk *ThresholdMultiSignaturePubKey) Address() crypto.Address {
|
||||
// Equals returns true iff pk and other both have the same number of keys, and
|
||||
// all constituent keys are the same, and in the same order.
|
||||
func (pk *ThresholdMultiSignaturePubKey) Equals(other crypto.PubKey) bool {
|
||||
if otherKey, ok := other.(*ThresholdMultiSignaturePubKey); ok {
|
||||
if pk.K != otherKey.K || len(pk.Pubkeys) != len(otherKey.Pubkeys) {
|
||||
otherKey, sameType := other.(*ThresholdMultiSignaturePubKey)
|
||||
if !sameType {
|
||||
return false
|
||||
}
|
||||
if pk.K != otherKey.K || len(pk.Pubkeys) != len(otherKey.Pubkeys) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(pk.Pubkeys); i++ {
|
||||
if !pk.Pubkeys[i].Equals(otherKey.Pubkeys[i]) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(pk.Pubkeys); i++ {
|
||||
if !pk.Pubkeys[i].Equals(otherKey.Pubkeys[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
@ -11,34 +11,60 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
)
|
||||
|
||||
func TestThresholdMultisig(t *testing.T) {
|
||||
msg := []byte{1, 2, 3, 4}
|
||||
pubkeys, sigs := generatePubKeysAndSignatures(5, msg)
|
||||
multisigKey := NewThresholdMultiSignaturePubKey(2, pubkeys)
|
||||
multisignature := NewMultisig(5)
|
||||
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
multisignature.AddSignatureFromPubkey(sigs[0], pubkeys[0], pubkeys)
|
||||
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
// Make sure adding the same signature twice doesn't increase number of signatures
|
||||
multisignature.AddSignatureFromPubkey(sigs[0], pubkeys[0], pubkeys)
|
||||
require.Equal(t, 1, len(multisignature.Sigs))
|
||||
// This tests multisig functionality, but it expects the first k signatures to be valid
|
||||
// TODO: Adapt it to give more flexibility about first k signatures being valid
|
||||
func TestThresholdMultisigValidCases(t *testing.T) {
|
||||
pkSet1, sigSet1 := generatePubKeysAndSignatures(5, []byte{1, 2, 3, 4})
|
||||
cases := []struct {
|
||||
msg []byte
|
||||
k int
|
||||
pubkeys []crypto.PubKey
|
||||
signingIndices []int
|
||||
// signatures should be the same size as signingIndices.
|
||||
signatures [][]byte
|
||||
passAfterKSignatures []bool
|
||||
}{
|
||||
{
|
||||
msg: []byte{1, 2, 3, 4},
|
||||
k: 2,
|
||||
pubkeys: pkSet1,
|
||||
signingIndices: []int{0, 3, 1},
|
||||
signatures: sigSet1,
|
||||
passAfterKSignatures: []bool{false},
|
||||
},
|
||||
}
|
||||
for tcIndex, tc := range cases {
|
||||
multisigKey := NewThresholdMultiSignaturePubKey(tc.k, tc.pubkeys)
|
||||
multisignature := NewMultisig(len(tc.pubkeys))
|
||||
for i := 0; i < tc.k-1; i++ {
|
||||
signingIndex := tc.signingIndices[i]
|
||||
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
|
||||
require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
|
||||
"multisig passed when i < k, tc %d, i %d", tcIndex, i)
|
||||
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
|
||||
require.Equal(t, i+1, len(multisignature.Sigs),
|
||||
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex)
|
||||
}
|
||||
require.False(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
|
||||
"multisig passed with k - 1 sigs, tc %d", tcIndex)
|
||||
multisignature.AddSignatureFromPubkey(tc.signatures[tc.signingIndices[tc.k]], tc.pubkeys[tc.signingIndices[tc.k]], tc.pubkeys)
|
||||
require.True(t, multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
|
||||
"multisig failed after k good signatures, tc %d", tcIndex)
|
||||
for i := tc.k + 1; i < len(tc.signingIndices); i++ {
|
||||
signingIndex := tc.signingIndices[i]
|
||||
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
|
||||
require.Equal(t, tc.passAfterKSignatures[i-tc.k-1],
|
||||
multisigKey.VerifyBytes(tc.msg, multisignature.Marshal()),
|
||||
"multisig didn't verify as expected after k sigs, tc %d, i %d", tcIndex, i)
|
||||
|
||||
// Adding two signatures should make it pass, as k = 2
|
||||
multisignature.AddSignatureFromPubkey(sigs[3], pubkeys[3], pubkeys)
|
||||
require.True(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
|
||||
// Adding a third invalid signature should make verification fail.
|
||||
multisignature.AddSignatureFromPubkey(sigs[0], pubkeys[4], pubkeys)
|
||||
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
|
||||
// try adding the invalid signature one signature before
|
||||
// first reset the multisig
|
||||
multisignature.BitArray.SetIndex(4, false)
|
||||
multisignature.Sigs = multisignature.Sigs[:2]
|
||||
multisignature.AddSignatureFromPubkey(sigs[0], pubkeys[2], pubkeys)
|
||||
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
multisignature.AddSignatureFromPubkey(tc.signatures[signingIndex], tc.pubkeys[signingIndex], tc.pubkeys)
|
||||
require.Equal(t, i+1, len(multisignature.Sigs),
|
||||
"adding a signature for the same pubkey twice increased signature count by 2, tc %d", tcIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fully replace this test with table driven tests
|
||||
func TestThresholdMultisigDuplicateSignatures(t *testing.T) {
|
||||
msg := []byte{1, 2, 3, 4, 5}
|
||||
pubkeys, sigs := generatePubKeysAndSignatures(5, msg)
|
||||
@ -51,6 +77,7 @@ func TestThresholdMultisigDuplicateSignatures(t *testing.T) {
|
||||
require.False(t, multisigKey.VerifyBytes(msg, multisignature.Marshal()))
|
||||
}
|
||||
|
||||
// TODO: Fully replace this test with table driven tests
|
||||
func TestMultiSigPubkeyEquality(t *testing.T) {
|
||||
msg := []byte{1, 2, 3, 4}
|
||||
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user