This repository has been archived by the owner on Aug 1, 2024. It is now read-only.
forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(x/tx): add basic handler types + sign mode direct (cosmos#14787)
Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com>
- Loading branch information
Showing
23 changed files
with
345 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package direct | ||
|
||
import ( | ||
"context" | ||
|
||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" | ||
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" | ||
"google.golang.org/protobuf/proto" | ||
|
||
"cosmossdk.io/x/tx/signing" | ||
) | ||
|
||
// SignModeHandler is the SIGN_MODE_DIRECT implementation of signing.SignModeHandler. | ||
type SignModeHandler struct{} | ||
|
||
// Mode implements signing.SignModeHandler.Mode. | ||
func (h SignModeHandler) Mode() signingv1beta1.SignMode { | ||
return signingv1beta1.SignMode_SIGN_MODE_DIRECT | ||
} | ||
|
||
// GetSignBytes implements signing.SignModeHandler.GetSignBytes. | ||
func (SignModeHandler) GetSignBytes(_ context.Context, signerData signing.SignerData, txData signing.TxData) ([]byte, error) { | ||
return proto.Marshal(&txv1beta1.SignDoc{ | ||
BodyBytes: txData.BodyBytes, | ||
AuthInfoBytes: txData.AuthInfoBytes, | ||
ChainId: signerData.ChainId, | ||
AccountNumber: signerData.AccountNumber, | ||
}) | ||
} | ||
|
||
var _ signing.SignModeHandler = SignModeHandler{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package direct_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" | ||
basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" | ||
"cosmossdk.io/api/cosmos/crypto/secp256k1" | ||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" | ||
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" | ||
"github.com/cosmos/cosmos-proto/any" | ||
"github.com/stretchr/testify/require" | ||
"google.golang.org/protobuf/proto" | ||
"google.golang.org/protobuf/types/known/anypb" | ||
|
||
"cosmossdk.io/x/tx/signing" | ||
"cosmossdk.io/x/tx/signing/direct" | ||
) | ||
|
||
func TestDirectModeHandler(t *testing.T) { | ||
memo := "sometestmemo" | ||
|
||
msg, err := any.New(&bankv1beta1.MsgSend{}) | ||
require.NoError(t, err) | ||
|
||
pk, err := any.New(&secp256k1.PubKey{ | ||
Key: make([]byte, 256), | ||
}) | ||
require.NoError(t, err) | ||
|
||
accSeq := uint64(2) // Arbitrary account sequence | ||
|
||
signerInfo := []*txv1beta1.SignerInfo{ | ||
{ | ||
PublicKey: pk, | ||
ModeInfo: &txv1beta1.ModeInfo{ | ||
Sum: &txv1beta1.ModeInfo_Single_{ | ||
Single: &txv1beta1.ModeInfo_Single{ | ||
Mode: signingv1beta1.SignMode_SIGN_MODE_DIRECT, | ||
}, | ||
}, | ||
}, | ||
Sequence: accSeq, | ||
}, | ||
} | ||
|
||
fee := &txv1beta1.Fee{Amount: []*basev1beta1.Coin{{Denom: "uatom", Amount: "1000"}}, GasLimit: 20000} | ||
txBody := &txv1beta1.TxBody{ | ||
Messages: []*anypb.Any{msg}, | ||
Memo: memo, | ||
} | ||
|
||
authInfo := &txv1beta1.AuthInfo{ | ||
Fee: fee, | ||
SignerInfos: signerInfo, | ||
} | ||
|
||
directHandler := direct.SignModeHandler{} | ||
|
||
chainId := "test-chain" | ||
accNum := uint64(1) | ||
|
||
signingData := signing.SignerData{ | ||
Address: "", | ||
ChainId: chainId, | ||
AccountNumber: accNum, | ||
PubKey: pk, | ||
} | ||
|
||
bodyBz, err := proto.Marshal(txBody) | ||
require.NoError(t, err) | ||
|
||
authInfoBz, err := proto.Marshal(authInfo) | ||
require.NoError(t, err) | ||
|
||
txData := signing.TxData{ | ||
Body: txBody, | ||
AuthInfo: authInfo, | ||
BodyBytes: bodyBz, | ||
AuthInfoBytes: authInfoBz, | ||
BodyHasUnknownNonCriticals: false, | ||
} | ||
|
||
signBytes, err := directHandler.GetSignBytes(context.Background(), signingData, txData) | ||
require.NoError(t, err) | ||
require.NotNil(t, signBytes) | ||
|
||
signBytes2, err := proto.Marshal(&txv1beta1.SignDoc{ | ||
BodyBytes: txData.BodyBytes, | ||
AuthInfoBytes: txData.AuthInfoBytes, | ||
ChainId: chainId, | ||
AccountNumber: accNum, | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, signBytes2) | ||
|
||
require.Equal(t, signBytes2, signBytes) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package signing | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" | ||
) | ||
|
||
// HandlerMap aggregates several sign mode handlers together for convenient generation of sign bytes | ||
// based on sign mode. | ||
type HandlerMap struct { | ||
signModeHandlers map[signingv1beta1.SignMode]SignModeHandler | ||
modes []signingv1beta1.SignMode | ||
} | ||
|
||
// NewHandlerMap constructs a new sign mode handler map. | ||
func NewHandlerMap(handlers ...SignModeHandler) *HandlerMap { | ||
res := &HandlerMap{ | ||
signModeHandlers: map[signingv1beta1.SignMode]SignModeHandler{}, | ||
} | ||
|
||
for _, handler := range handlers { | ||
mode := handler.Mode() | ||
res.signModeHandlers[mode] = handler | ||
res.modes = append(res.modes, mode) | ||
} | ||
|
||
return res | ||
} | ||
|
||
// SupportedModes lists the modes supported by this handler map. | ||
func (h *HandlerMap) SupportedModes() []signingv1beta1.SignMode { | ||
return h.modes | ||
} | ||
|
||
// GetSignBytes returns the sign bytes for the transaction for the requested mode. | ||
func (h *HandlerMap) GetSignBytes(ctx context.Context, signMode signingv1beta1.SignMode, signerData SignerData, txData TxData) ([]byte, error) { | ||
handler, ok := h.signModeHandlers[signMode] | ||
if !ok { | ||
return nil, fmt.Errorf("unsuppored sign mode %s", signMode) | ||
} | ||
|
||
return handler.GetSignBytes(ctx, signerData, txData) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,16 @@ | ||
package signing | ||
|
||
import "google.golang.org/protobuf/types/known/anypb" | ||
import ( | ||
"context" | ||
|
||
// SignerData is the specific information needed to sign a transaction that generally | ||
// isn't included in the transaction body itself | ||
type SignerData struct { | ||
// The address of the signer. | ||
// | ||
// In case of multisigs, this should be the multisig's address. | ||
Address string | ||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" | ||
) | ||
|
||
// ChainId is the chain that this transaction is targeted | ||
ChainId string | ||
// SignModeHandler is the interface that handlers for each sign mode should implement to generate sign bytes. | ||
type SignModeHandler interface { | ||
// Mode is the sign mode supported by this handler | ||
Mode() signingv1beta1.SignMode | ||
|
||
// AccountNumber is the account number of the signer. | ||
// | ||
// In case of multisigs, this should be the multisig account number. | ||
AccountNumber uint64 | ||
|
||
// Sequence is the account sequence number of the signer that is used | ||
// for replay protection. This field is only useful for Legacy Amino signing, | ||
// since in SIGN_MODE_DIRECT the account sequence is already in the signer | ||
// info. | ||
// | ||
// In case of multisigs, this should be the multisig sequence. | ||
Sequence uint64 | ||
|
||
// PubKey is the public key of the signer. | ||
// | ||
// In case of multisigs, this should be the pubkey of the member of the | ||
// multisig that is signing the current sign doc. | ||
PubKey *anypb.Any | ||
// GetSignBytes returns the sign bytes for the provided SignerData and TxData, or an error. | ||
GetSignBytes(ctx context.Context, signerData SignerData, txData TxData) ([]byte, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package signing | ||
|
||
import "google.golang.org/protobuf/types/known/anypb" | ||
|
||
// SignerData is the specific information needed to sign a transaction that generally | ||
// isn't included in the transaction body itself | ||
type SignerData struct { | ||
// The address of the signer. | ||
// | ||
// In case of multisigs, this should be the multisig's address. | ||
Address string | ||
|
||
// ChainId is the chain that this transaction is targeted | ||
ChainId string | ||
|
||
// AccountNumber is the account number of the signer. | ||
// | ||
// In case of multisigs, this should be the multisig account number. | ||
AccountNumber uint64 | ||
|
||
// Sequence is the account sequence number of the signer that is used | ||
// for replay protection. This field is only useful for Legacy Amino signing, | ||
// since in SIGN_MODE_DIRECT the account sequence is already in the signer | ||
// info. | ||
// | ||
// In case of multisigs, this should be the multisig sequence. | ||
Sequence uint64 | ||
|
||
// PubKey is the public key of the signer. | ||
// | ||
// In case of multisigs, this should be the pubkey of the member of the | ||
// multisig that is signing the current sign doc. | ||
PubKey *anypb.Any | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package std | ||
|
||
import ( | ||
"fmt" | ||
|
||
"cosmossdk.io/x/tx/signing" | ||
"cosmossdk.io/x/tx/signing/direct" | ||
"cosmossdk.io/x/tx/textual" | ||
) | ||
|
||
// SignModeOptions are options for configuring the standard sign mode handler map. | ||
type SignModeOptions struct { | ||
// CoinMetadataQueryFn is the CoinMetadataQueryFn required for SIGN_MODE_TEXTUAL. | ||
CoinMetadataQueryFn textual.CoinMetadataQueryFn | ||
} | ||
|
||
// HandlerMap returns a sign mode handler map that Cosmos SDK apps can use out | ||
// of the box to support all "standard" sign modes. | ||
func (s SignModeOptions) HandlerMap() (*signing.HandlerMap, error) { | ||
if s.CoinMetadataQueryFn == nil { | ||
return nil, fmt.Errorf("missing %T needed for SIGN_MODE_TEXTUAL", s.CoinMetadataQueryFn) | ||
} | ||
|
||
return signing.NewHandlerMap( | ||
direct.SignModeHandler{}, | ||
textual.NewSignModeHandler(s.CoinMetadataQueryFn), | ||
), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package signing | ||
|
||
import txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" | ||
|
||
// TxData is the data about a transaction that is necessary to generate sign bytes. | ||
type TxData struct { | ||
// Body is the TxBody that will be part of the transaction. | ||
Body *txv1beta1.TxBody | ||
|
||
// AuthInfo is the AuthInfo that will be part of the transaction. | ||
AuthInfo *txv1beta1.AuthInfo | ||
|
||
// BodyBytes is the marshaled body bytes that will be part of TxRaw. | ||
BodyBytes []byte | ||
|
||
// AuthInfoBytes is the marshaled AuthInfo bytes that will be part of TxRaw. | ||
AuthInfoBytes []byte | ||
|
||
// BodyHasUnknownNonCriticals should be set to true if the transaction has been | ||
// decoded and found to have unknown non-critical fields. This is only needed | ||
// for amino JSON signing. | ||
BodyHasUnknownNonCriticals bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.