You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

77 lines
2.4 KiB

package multisig
import (
"fmt"
"strings"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/multisig/bitarray"
)
// Multisignature is used to represent the signature object used in the multisigs.
// Sigs is a list of signatures, sorted by corresponding index.
type Multisignature struct {
BitArray *bitarray.CompactBitArray
Sigs [][]byte
}
// NewMultisig returns a new Multisignature of size n.
func NewMultisig(n int) *Multisignature {
// Default the signature list to have a capacity of two, since we can
// expect that most multisigs will require multiple signers.
return &Multisignature{bitarray.NewCompactBitArray(n), make([][]byte, 0, 2)}
}
// GetIndex returns the index of pk in keys. Returns -1 if not found
func getIndex(pk crypto.PubKey, keys []crypto.PubKey) int {
for i := 0; i < len(keys); i++ {
if pk.Equals(keys[i]) {
return i
}
}
return -1
}
// 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.NumTrueBitsBefore(index)
// Signature already exists, just replace the value there
if mSig.BitArray.GetIndex(index) {
mSig.Sigs[newSigIndex] = sig
return
}
mSig.BitArray.SetIndex(index, true)
// Optimization if the index is the greatest index
if newSigIndex == len(mSig.Sigs) {
mSig.Sigs = append(mSig.Sigs, sig)
return
}
// Expand slice by one with a dummy element, move all elements after i
// over by one, then place the new signature in that gap.
mSig.Sigs = append(mSig.Sigs, make([]byte, 0))
copy(mSig.Sigs[newSigIndex+1:], mSig.Sigs[newSigIndex:])
mSig.Sigs[newSigIndex] = sig
}
// AddSignatureFromPubKey adds a signature to the multisig, at the index in
// keys corresponding to the provided pubkey.
func (mSig *Multisignature) AddSignatureFromPubKey(sig []byte, pubkey crypto.PubKey, keys []crypto.PubKey) error {
index := getIndex(pubkey, keys)
if index == -1 {
keysStr := make([]string, len(keys))
for i, k := range keys {
keysStr[i] = fmt.Sprintf("%X", k.Bytes())
}
return fmt.Errorf("provided key %X doesn't exist in pubkeys: \n%s", pubkey.Bytes(), strings.Join(keysStr, "\n"))
}
mSig.AddSignature(sig, index)
return nil
}
// Marshal the multisignature with amino
func (mSig *Multisignature) Marshal() []byte {
return cdc.MustMarshalBinaryBare(mSig)
}