github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/tx/sigs.go (about) 1 package tx 2 3 import ( 4 "fmt" 5 6 "github.com/cosmos/cosmos-sdk/codec" 7 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 8 cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 9 "github.com/cosmos/cosmos-sdk/types/tx" 10 "github.com/cosmos/cosmos-sdk/types/tx/signing" 11 ) 12 13 // SignatureDataToModeInfoAndSig converts a SignatureData to a ModeInfo and raw bytes signature 14 func SignatureDataToModeInfoAndSig(data signing.SignatureData) (*tx.ModeInfo, []byte) { 15 if data == nil { 16 return nil, nil 17 } 18 19 switch data := data.(type) { 20 case *signing.SingleSignatureData: 21 return &tx.ModeInfo{ 22 Sum: &tx.ModeInfo_Single_{ 23 Single: &tx.ModeInfo_Single{Mode: data.SignMode}, 24 }, 25 }, data.Signature 26 case *signing.MultiSignatureData: 27 n := len(data.Signatures) 28 modeInfos := make([]*tx.ModeInfo, n) 29 sigs := make([][]byte, n) 30 31 for i, d := range data.Signatures { 32 modeInfos[i], sigs[i] = SignatureDataToModeInfoAndSig(d) 33 } 34 35 multisig := cryptotypes.MultiSignature{ 36 Signatures: sigs, 37 } 38 sig, err := multisig.Marshal() 39 if err != nil { 40 panic(err) 41 } 42 43 return &tx.ModeInfo{ 44 Sum: &tx.ModeInfo_Multi_{ 45 Multi: &tx.ModeInfo_Multi{ 46 Bitarray: data.BitArray, 47 ModeInfos: modeInfos, 48 }, 49 }, 50 }, sig 51 default: 52 panic(fmt.Sprintf("unexpected signature data type %T", data)) 53 } 54 } 55 56 // ModeInfoAndSigToSignatureData converts a ModeInfo and raw bytes signature to a SignatureData or returns 57 // an error 58 func ModeInfoAndSigToSignatureData(modeInfo *tx.ModeInfo, sig []byte) (signing.SignatureData, error) { 59 switch modeInfo := modeInfo.Sum.(type) { 60 case *tx.ModeInfo_Single_: 61 return &signing.SingleSignatureData{ 62 SignMode: modeInfo.Single.Mode, 63 Signature: sig, 64 }, nil 65 66 case *tx.ModeInfo_Multi_: 67 multi := modeInfo.Multi 68 69 sigs, err := decodeMultisignatures(sig) 70 if err != nil { 71 return nil, err 72 } 73 74 sigv2s := make([]signing.SignatureData, len(sigs)) 75 for i, mi := range multi.ModeInfos { 76 sigv2s[i], err = ModeInfoAndSigToSignatureData(mi, sigs[i]) 77 if err != nil { 78 return nil, err 79 } 80 } 81 82 return &signing.MultiSignatureData{ 83 BitArray: multi.Bitarray, 84 Signatures: sigv2s, 85 }, nil 86 87 default: 88 panic(fmt.Errorf("unexpected ModeInfo data type %T", modeInfo)) 89 } 90 } 91 92 // decodeMultisignatures safely decodes the raw bytes as a MultiSignature protobuf message 93 func decodeMultisignatures(bz []byte) ([][]byte, error) { 94 multisig := cryptotypes.MultiSignature{} 95 err := multisig.Unmarshal(bz) 96 if err != nil { 97 return nil, err 98 } 99 // NOTE: it is import to reject multi-signatures that contain unrecognized fields because this is an exploitable 100 // malleability in the protobuf message. Basically an attacker could bloat a MultiSignature message with unknown 101 // fields, thus bloating the transaction and causing it to fail. 102 if len(multisig.XXX_unrecognized) > 0 { 103 return nil, fmt.Errorf("rejecting unrecognized fields found in MultiSignature") 104 } 105 return multisig.Signatures, nil 106 } 107 108 func (g config) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error) { 109 descs := make([]*signing.SignatureDescriptor, len(sigs)) 110 111 for i, sig := range sigs { 112 descData := signing.SignatureDataToProto(sig.Data) 113 any, err := codectypes.NewAnyWithValue(sig.PubKey) 114 if err != nil { 115 return nil, err 116 } 117 118 descs[i] = &signing.SignatureDescriptor{ 119 PublicKey: any, 120 Data: descData, 121 Sequence: sig.Sequence, 122 } 123 } 124 125 toJSON := &signing.SignatureDescriptors{Signatures: descs} 126 127 return codec.ProtoMarshalJSON(toJSON, nil) 128 } 129 130 func (g config) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, error) { 131 var sigDescs signing.SignatureDescriptors 132 err := g.protoCodec.UnmarshalJSON(bz, &sigDescs) 133 if err != nil { 134 return nil, err 135 } 136 137 sigs := make([]signing.SignatureV2, len(sigDescs.Signatures)) 138 for i, desc := range sigDescs.Signatures { 139 pubKey, _ := desc.PublicKey.GetCachedValue().(cryptotypes.PubKey) 140 141 data := signing.SignatureDataFromProto(desc.Data) 142 143 sigs[i] = signing.SignatureV2{ 144 PubKey: pubKey, 145 Data: data, 146 Sequence: desc.Sequence, 147 } 148 } 149 150 return sigs, nil 151 }