github.com/Finschia/finschia-sdk@v0.49.1/x/auth/legacy/legacytx/stdsign.go (about) 1 package legacytx 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "gopkg.in/yaml.v2" 8 9 "github.com/Finschia/finschia-sdk/codec" 10 "github.com/Finschia/finschia-sdk/codec/legacy" 11 codectypes "github.com/Finschia/finschia-sdk/codec/types" 12 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 13 "github.com/Finschia/finschia-sdk/crypto/types/multisig" 14 sdk "github.com/Finschia/finschia-sdk/types" 15 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 16 "github.com/Finschia/finschia-sdk/types/tx/signing" 17 ) 18 19 // LegacyMsg defines the old interface a message must fulfill, containing 20 // Amino signing method and legacy router info. 21 // Deprecated: Please use `Msg` instead. 22 type LegacyMsg interface { 23 sdk.Msg 24 25 // Get the canonical byte representation of the Msg. 26 GetSignBytes() []byte 27 28 // Return the message type. 29 // Must be alphanumeric or empty. 30 Route() string 31 32 // Returns a human-readable string for the message, intended for utilization 33 // within tags 34 Type() string 35 } 36 37 // StdSignDoc is replay-prevention structure. 38 // It includes the result of msg.GetSignBytes(), 39 // as well as the ChainID (prevent cross chain replay) 40 // and the Sequence numbers for each signature (prevent 41 // inchain replay and enforce tx ordering per account). 42 type StdSignDoc struct { 43 AccountNumber uint64 `json:"account_number" yaml:"account_number"` 44 Sequence uint64 `json:"sequence" yaml:"sequence"` 45 TimeoutHeight uint64 `json:"timeout_height,omitempty" yaml:"timeout_height"` 46 ChainID string `json:"chain_id" yaml:"chain_id"` 47 Memo string `json:"memo" yaml:"memo"` 48 Fee json.RawMessage `json:"fee" yaml:"fee"` 49 Msgs []json.RawMessage `json:"msgs" yaml:"msgs"` 50 } 51 52 // StdSignBytes returns the bytes to sign for a transaction. 53 func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte { 54 msgsBytes := make([]json.RawMessage, 0, len(msgs)) 55 for _, msg := range msgs { 56 legacyMsg, ok := msg.(LegacyMsg) 57 if !ok { 58 panic(fmt.Errorf("expected %T when using amino JSON", (*LegacyMsg)(nil))) 59 } 60 61 msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes())) 62 } 63 64 bz, err := legacy.Cdc.MarshalJSON(StdSignDoc{ 65 AccountNumber: accnum, 66 ChainID: chainID, 67 Fee: json.RawMessage(fee.Bytes()), 68 Memo: memo, 69 Msgs: msgsBytes, 70 Sequence: sequence, 71 TimeoutHeight: timeout, 72 }) 73 if err != nil { 74 panic(err) 75 } 76 77 return sdk.MustSortJSON(bz) 78 } 79 80 // Deprecated: StdSignature represents a sig 81 type StdSignature struct { 82 cryptotypes.PubKey `json:"pub_key" yaml:"pub_key"` // optional 83 Signature []byte `json:"signature" yaml:"signature"` 84 } 85 86 // Deprecated 87 func NewStdSignature(pk cryptotypes.PubKey, sig []byte) StdSignature { 88 return StdSignature{PubKey: pk, Signature: sig} 89 } 90 91 // GetSignature returns the raw signature bytes. 92 func (ss StdSignature) GetSignature() []byte { 93 return ss.Signature 94 } 95 96 // GetPubKey returns the public key of a signature as a cryptotypes.PubKey using the 97 // Amino codec. 98 func (ss StdSignature) GetPubKey() cryptotypes.PubKey { 99 return ss.PubKey 100 } 101 102 // MarshalYAML returns the YAML representation of the signature. 103 func (ss StdSignature) MarshalYAML() (interface{}, error) { 104 pk := "" 105 if ss.PubKey != nil { 106 pk = ss.PubKey.String() 107 } 108 109 bz, err := yaml.Marshal(struct { 110 PubKey string 111 Signature string 112 }{ 113 pk, 114 fmt.Sprintf("%X", ss.Signature), 115 }) 116 if err != nil { 117 return nil, err 118 } 119 120 return string(bz), err 121 } 122 123 func (ss StdSignature) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 124 return codectypes.UnpackInterfaces(ss.PubKey, unpacker) 125 } 126 127 // StdSignatureToSignatureV2 converts a StdSignature to a SignatureV2 128 func StdSignatureToSignatureV2(cdc *codec.LegacyAmino, sig StdSignature) (signing.SignatureV2, error) { 129 pk := sig.GetPubKey() 130 data, err := pubKeySigToSigData(cdc, pk, sig.Signature) 131 if err != nil { 132 return signing.SignatureV2{}, err 133 } 134 135 return signing.SignatureV2{ 136 PubKey: pk, 137 Data: data, 138 }, nil 139 } 140 141 func pubKeySigToSigData(cdc *codec.LegacyAmino, key cryptotypes.PubKey, sig []byte) (signing.SignatureData, error) { 142 multiPK, ok := key.(multisig.PubKey) 143 if !ok { 144 return &signing.SingleSignatureData{ 145 SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, 146 Signature: sig, 147 }, nil 148 } 149 var multiSig multisig.AminoMultisignature 150 err := cdc.Unmarshal(sig, &multiSig) 151 if err != nil { 152 return nil, err 153 } 154 155 sigs := multiSig.Sigs 156 sigDatas := make([]signing.SignatureData, len(sigs)) 157 pubKeys := multiPK.GetPubKeys() 158 bitArray := multiSig.BitArray 159 n := multiSig.BitArray.Count() 160 signatures := multisig.NewMultisig(n) 161 sigIdx := 0 162 for i := 0; i < n; i++ { 163 if bitArray.GetIndex(i) { 164 data, err := pubKeySigToSigData(cdc, pubKeys[i], multiSig.Sigs[sigIdx]) 165 if err != nil { 166 return nil, sdkerrors.Wrapf(err, "Unable to convert Signature to SigData %d", sigIdx) 167 } 168 169 sigDatas[sigIdx] = data 170 multisig.AddSignature(signatures, data, sigIdx) 171 sigIdx++ 172 } 173 } 174 175 return signatures, nil 176 }