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  }