- 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)
- }
|