github.com/Finschia/finschia-sdk@v0.48.1/crypto/types/multisig/multisignature.go (about) 1 package multisig 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/Finschia/finschia-sdk/crypto/types" 8 "github.com/Finschia/finschia-sdk/types/tx/signing" 9 ) 10 11 // AminoMultisignature is used to represent amino multi-signatures for StdTx's. 12 // It is assumed that all signatures were made with SIGN_MODE_LEGACY_AMINO_JSON. 13 // Sigs is a list of signatures, sorted by corresponding index. 14 type AminoMultisignature struct { 15 BitArray *types.CompactBitArray 16 Sigs [][]byte 17 } 18 19 // NewMultisig returns a new MultiSignatureData 20 func NewMultisig(n int) *signing.MultiSignatureData { 21 return &signing.MultiSignatureData{ 22 BitArray: types.NewCompactBitArray(n), 23 Signatures: make([]signing.SignatureData, 0, n), 24 } 25 } 26 27 // GetIndex returns the index of pk in keys. Returns -1 if not found 28 func getIndex(pk types.PubKey, keys []types.PubKey) int { 29 for i := 0; i < len(keys); i++ { 30 if pk.Equals(keys[i]) { 31 return i 32 } 33 } 34 return -1 35 } 36 37 // AddSignature adds a signature to the multisig, at the corresponding index. The index must 38 // represent the pubkey index in the LegacyAmingPubKey structure, which verifies this signature. 39 // If the signature already exists, replace it. 40 func AddSignature(mSig *signing.MultiSignatureData, sig signing.SignatureData, index int) { 41 newSigIndex := mSig.BitArray.NumTrueBitsBefore(index) 42 // Signature already exists, just replace the value there 43 if mSig.BitArray.GetIndex(index) { 44 mSig.Signatures[newSigIndex] = sig 45 return 46 } 47 mSig.BitArray.SetIndex(index, true) 48 // Optimization if the index is the greatest index 49 if newSigIndex == len(mSig.Signatures) { 50 mSig.Signatures = append(mSig.Signatures, sig) 51 return 52 } 53 // Expand slice by one with a dummy element, move all elements after i 54 // over by one, then place the new signature in that gap. 55 mSig.Signatures = append(mSig.Signatures, &signing.SingleSignatureData{}) 56 copy(mSig.Signatures[newSigIndex+1:], mSig.Signatures[newSigIndex:]) 57 mSig.Signatures[newSigIndex] = sig 58 } 59 60 // AddSignatureFromPubKey adds a signature to the multisig, at the index in 61 // keys corresponding to the provided pubkey. 62 func AddSignatureFromPubKey(mSig *signing.MultiSignatureData, sig signing.SignatureData, pubkey types.PubKey, keys []types.PubKey) error { 63 if mSig == nil { 64 return fmt.Errorf("value of mSig is nil %v", mSig) 65 } 66 if sig == nil { 67 return fmt.Errorf("value of sig is nil %v", sig) 68 } 69 70 if pubkey == nil || keys == nil { 71 return fmt.Errorf("pubkey or keys can't be nil %v %v", pubkey, keys) 72 } 73 index := getIndex(pubkey, keys) 74 if index == -1 { 75 keysStr := make([]string, len(keys)) 76 for i, k := range keys { 77 keysStr[i] = fmt.Sprintf("%X", k.Bytes()) 78 } 79 80 return fmt.Errorf("provided key %X doesn't exist in pubkeys: \n%s", pubkey.Bytes(), strings.Join(keysStr, "\n")) 81 } 82 83 AddSignature(mSig, sig, index) 84 return nil 85 } 86 87 func AddSignatureV2(mSig *signing.MultiSignatureData, sig signing.SignatureV2, keys []types.PubKey) error { 88 return AddSignatureFromPubKey(mSig, sig.Data, sig.PubKey, keys) 89 }