126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
package offchain
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
gogogrpc "github.com/cosmos/gogoproto/grpc"
|
|
|
|
apisigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
|
clientcontext "cosmossdk.io/client/v2/context"
|
|
"cosmossdk.io/client/v2/internal/account"
|
|
"cosmossdk.io/client/v2/internal/offchain"
|
|
clitx "cosmossdk.io/client/v2/tx"
|
|
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
)
|
|
|
|
const (
|
|
// ExpectedChainID defines the chain id an off-chain message must have
|
|
ExpectedChainID = ""
|
|
// ExpectedAccountNumber defines the account number an off-chain message must have
|
|
ExpectedAccountNumber = 0
|
|
// ExpectedSequence defines the sequence number an off-chain message must have
|
|
ExpectedSequence = 0
|
|
)
|
|
|
|
var enabledSignModes = []apisigning.SignMode{
|
|
apisigning.SignMode_SIGN_MODE_DIRECT,
|
|
apisigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
|
}
|
|
|
|
// Sign signs given bytes using the specified encoder and SignMode.
|
|
func Sign(
|
|
ctx clientcontext.Context,
|
|
rawBytes []byte,
|
|
conn gogogrpc.ClientConn,
|
|
fromName, encoding, signMode, output string,
|
|
) (string, error) {
|
|
digest, err := encodeDigest(encoding, rawBytes)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
txConfig, err := clitx.NewTxConfig(clitx.ConfigOptions{
|
|
AddressCodec: ctx.AddressCodec,
|
|
Cdc: ctx.Cdc,
|
|
ValidatorAddressCodec: ctx.ValidatorAddressCodec,
|
|
EnabledSignModes: enabledSignModes,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
accRetriever := account.NewAccountRetriever(ctx.AddressCodec, conn, ctx.Cdc.InterfaceRegistry())
|
|
|
|
sm, err := getSignMode(signMode)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
params := clitx.TxParameters{
|
|
ChainID: ExpectedChainID,
|
|
SignMode: sm,
|
|
AccountConfig: clitx.AccountConfig{
|
|
AccountNumber: ExpectedAccountNumber,
|
|
Sequence: ExpectedSequence,
|
|
FromName: fromName,
|
|
},
|
|
}
|
|
|
|
txf, err := clitx.NewFactory(ctx.Keyring, ctx.Cdc, accRetriever, txConfig, ctx.AddressCodec, conn, params)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
pubKey, err := ctx.Keyring.GetPubKey(fromName)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
addr, err := ctx.AddressCodec.BytesToString(pubKey.Address())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
msg := &offchain.MsgSignArbitraryData{
|
|
AppDomain: version.AppName,
|
|
Signer: addr,
|
|
Data: digest,
|
|
}
|
|
|
|
signedTx, err := txf.BuildsSignedTx(context.Background(), msg)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
bz, err := encode(output, signedTx, txConfig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(bz), nil
|
|
}
|
|
|
|
func encode(output string, tx clitx.Tx, config clitx.TxConfig) ([]byte, error) {
|
|
switch output {
|
|
case "json":
|
|
return config.TxJSONEncoder()(tx)
|
|
case "text":
|
|
return config.TxTextEncoder()(tx)
|
|
default:
|
|
return nil, fmt.Errorf("unsupported output type: %s", output)
|
|
}
|
|
}
|
|
|
|
// getSignMode returns the corresponding apisigning.SignMode based on the provided mode string.
|
|
func getSignMode(mode string) (apisigning.SignMode, error) {
|
|
switch mode {
|
|
case "direct":
|
|
return apisigning.SignMode_SIGN_MODE_DIRECT, nil
|
|
case "amino-json":
|
|
return apisigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, nil
|
|
}
|
|
|
|
return apisigning.SignMode_SIGN_MODE_UNSPECIFIED, fmt.Errorf("unsupported sign mode: %s", mode)
|
|
}
|