Merge PR #5795: Proto Transaction Migration
This commit is contained in:
commit
f31b625bca
|
@ -14,6 +14,7 @@ import (
|
|||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clientx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -25,6 +26,8 @@ type CLIContext struct {
|
|||
FromAddress sdk.AccAddress
|
||||
Client rpcclient.Client
|
||||
ChainID string
|
||||
TxGenerator clientx.Generator
|
||||
Marshaler codec.Marshaler
|
||||
Keybase keys.Keybase
|
||||
Input io.Reader
|
||||
Output io.Writer
|
||||
|
@ -36,13 +39,15 @@ type CLIContext struct {
|
|||
BroadcastMode string
|
||||
Verifier tmlite.Verifier
|
||||
FromName string
|
||||
Codec *codec.Codec
|
||||
TrustNode bool
|
||||
UseLedger bool
|
||||
Simulate bool
|
||||
GenerateOnly bool
|
||||
Indent bool
|
||||
SkipConfirm bool
|
||||
|
||||
// TODO: Deprecated (remove).
|
||||
Codec *codec.Codec
|
||||
}
|
||||
|
||||
// NewCLIContextWithInputAndFrom returns a new initialized CLIContext with parameters from the
|
||||
|
@ -130,7 +135,20 @@ func (ctx CLIContext) WithInput(r io.Reader) CLIContext {
|
|||
return ctx
|
||||
}
|
||||
|
||||
// WithTxGenerator returns a copy of the CLIContext with an updated TxGenerator.
|
||||
func (ctx CLIContext) WithTxGenerator(txg clientx.Generator) CLIContext {
|
||||
ctx.TxGenerator = txg
|
||||
return ctx
|
||||
}
|
||||
|
||||
// WithMarshaler returns a copy of the CLIContext with an updated Marshaler.
|
||||
func (ctx CLIContext) WithMarshaler(m codec.Marshaler) CLIContext {
|
||||
ctx.Marshaler = m
|
||||
return ctx
|
||||
}
|
||||
|
||||
// WithCodec returns a copy of the context with an updated codec.
|
||||
// TODO: Deprecated (remove).
|
||||
func (ctx CLIContext) WithCodec(cdc *codec.Codec) CLIContext {
|
||||
ctx.Codec = cdc
|
||||
return ctx
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package tx
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type (
|
||||
// Generator defines an interface a client can utilize to generate an
|
||||
// application-defined concrete transaction type. The type returned must
|
||||
// implement ClientTx.
|
||||
Generator interface {
|
||||
NewTx() ClientTx
|
||||
}
|
||||
|
||||
// ClientTx defines an interface which an application-defined concrete transaction
|
||||
// type must implement. Namely, it must be able to set messages, generate
|
||||
// signatures, and provide canonical bytes to sign over. The transaction must
|
||||
// also know how to encode itself.
|
||||
ClientTx interface {
|
||||
sdk.Tx
|
||||
codec.ProtoMarshaler
|
||||
|
||||
SetMsgs(...sdk.Msg) error
|
||||
GetSignatures() []sdk.Signature
|
||||
SetSignatures(...sdk.Signature)
|
||||
GetFee() sdk.Fee
|
||||
SetFee(sdk.Fee)
|
||||
GetMemo() string
|
||||
SetMemo(string)
|
||||
|
||||
// CanonicalSignBytes returns the canonical JSON bytes to sign over, given a
|
||||
// chain ID, along with an account and sequence number. The JSON encoding
|
||||
// ensures all field names adhere to their proto definition, default values
|
||||
// are omitted, and follows the JSON Canonical Form.
|
||||
CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error)
|
||||
}
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -5,12 +5,16 @@ import "third_party/proto/cosmos-proto/cosmos.proto";
|
|||
import "third_party/proto/gogoproto/gogo.proto";
|
||||
import "x/auth/types/types.proto";
|
||||
import "x/auth/vesting/types/types.proto";
|
||||
import "x/bank/types/types.proto";
|
||||
import "x/crisis/types/types.proto";
|
||||
import "x/distribution/types/types.proto";
|
||||
import "x/supply/types/types.proto";
|
||||
import "x/evidence/types/types.proto";
|
||||
import "x/gov/types/types.proto";
|
||||
import "x/slashing/types/types.proto";
|
||||
import "x/staking/types/types.proto";
|
||||
import "x/params/types/proposal/types.proto";
|
||||
import "x/upgrade/types/types.proto";
|
||||
import "x/distribution/types/types.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/codec/std";
|
||||
|
||||
|
@ -57,8 +61,8 @@ message MsgSubmitEvidence {
|
|||
option (gogoproto.equal) = true;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
Evidence evidence = 1;
|
||||
cosmos_sdk.x.evidence.v1.MsgSubmitEvidenceBase base = 2 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
|
||||
cosmos_sdk.x.evidence.v1.MsgSubmitEvidenceBase base = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
|
||||
Evidence evidence = 2;
|
||||
}
|
||||
|
||||
// MsgSubmitProposal defines the application-level message type for handling
|
||||
|
@ -95,3 +99,49 @@ message Content {
|
|||
cosmos_sdk.x.distribution.v1.CommunityPoolSpendProposal community_pool_spend = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Transaction defines the application-level transaction that can be signed and
|
||||
// processed by the state-machine. It contains a base of common fields and
|
||||
// repeated set of Message types.
|
||||
message Transaction {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
cosmos_sdk.x.auth.v1.StdTxBase base = 1
|
||||
[(gogoproto.jsontag) = "", (gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
repeated Message msgs = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
// Message defines the set of valid concrete message types that can be used to
|
||||
// construct a transaction.
|
||||
message Message {
|
||||
option (cosmos_proto.interface_type) = "github.com/cosmos/cosmos-sdk/types.Msg";
|
||||
|
||||
// sum defines the set of all allowed valid messages defined in modules.
|
||||
oneof sum {
|
||||
cosmos_sdk.x.bank.v1.MsgSend msg_send = 1;
|
||||
cosmos_sdk.x.bank.v1.MsgMultiSend msg_multi_send = 2;
|
||||
cosmos_sdk.x.crisis.v1.MsgVerifyInvariant msg_verify_invariant = 3;
|
||||
cosmos_sdk.x.distribution.v1.MsgSetWithdrawAddress msg_set_withdraw_address = 4;
|
||||
cosmos_sdk.x.distribution.v1.MsgWithdrawDelegatorReward msg_withdraw_delegator_reward = 5;
|
||||
cosmos_sdk.x.distribution.v1.MsgWithdrawValidatorCommission msg_withdraw_validator_commission = 6;
|
||||
cosmos_sdk.x.distribution.v1.MsgFundCommunityPool msg_fund_community_pool = 7;
|
||||
MsgSubmitEvidence msg_submit_evidence = 8;
|
||||
MsgSubmitProposal msg_submit_proposal = 9;
|
||||
cosmos_sdk.x.gov.v1.MsgVote msg_vote = 10;
|
||||
cosmos_sdk.x.gov.v1.MsgDeposit msg_deposit = 11;
|
||||
cosmos_sdk.x.slashing.v1.MsgUnjail msg_unjail = 12;
|
||||
cosmos_sdk.x.staking.v1.MsgCreateValidator msg_create_validator = 13;
|
||||
cosmos_sdk.x.staking.v1.MsgEditValidator msg_edit_validator = 14;
|
||||
cosmos_sdk.x.staking.v1.MsgDelegate msg_delegate = 15;
|
||||
cosmos_sdk.x.staking.v1.MsgBeginRedelegate msg_begin_redelegate = 16;
|
||||
cosmos_sdk.x.staking.v1.MsgUndelegate msg_undelegate = 17;
|
||||
}
|
||||
}
|
||||
|
||||
// SignDoc defines a standard application-level signing document to compose
|
||||
// signatures for a Transaction.
|
||||
message SignDoc {
|
||||
cosmos_sdk.x.auth.v1.StdSignDocBase base = 1
|
||||
[(gogoproto.jsontag) = "", (gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
repeated Message msgs = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package std_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/std"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/evidence"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
)
|
||||
|
||||
func TestNewMsgSubmitEvidence(t *testing.T) {
|
||||
s := sdk.AccAddress("foo")
|
||||
e := evidence.Equivocation{
|
||||
Height: 100,
|
||||
Time: time.Now().UTC(),
|
||||
Power: 40000000000,
|
||||
ConsensusAddress: sdk.ConsAddress("test"),
|
||||
}
|
||||
|
||||
msg, err := std.NewMsgSubmitEvidence(e, s)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, msg.GetEvidence(), &e)
|
||||
require.Equal(t, msg.GetSubmitter(), s)
|
||||
require.NoError(t, msg.ValidateBasic())
|
||||
}
|
||||
|
||||
func TestNewNewMsgSubmitProposal(t *testing.T) {
|
||||
p := sdk.AccAddress("foo")
|
||||
d := sdk.NewCoins(sdk.NewInt64Coin("stake", 1000))
|
||||
c := gov.TextProposal{Title: "title", Description: "description"}
|
||||
|
||||
msg, err := std.NewMsgSubmitProposal(c, d, p)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, msg.GetContent(), &c)
|
||||
require.Equal(t, msg.GetProposer(), p)
|
||||
require.Equal(t, msg.GetInitialDeposit(), d)
|
||||
require.NoError(t, msg.ValidateBasic())
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package std
|
||||
|
||||
import (
|
||||
clientx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
_ sdk.Tx = (*Transaction)(nil)
|
||||
_ clientx.ClientTx = (*Transaction)(nil)
|
||||
_ clientx.Generator = TxGenerator{}
|
||||
)
|
||||
|
||||
// TxGenerator defines a transaction generator that allows clients to construct
|
||||
// transactions.
|
||||
type TxGenerator struct{}
|
||||
|
||||
// NewTx returns a reference to an empty Transaction type.
|
||||
func (TxGenerator) NewTx() clientx.ClientTx {
|
||||
return &Transaction{}
|
||||
}
|
||||
|
||||
func NewTransaction(fee auth.StdFee, memo string, sdkMsgs []sdk.Msg) (*Transaction, error) {
|
||||
tx := &Transaction{
|
||||
StdTxBase: auth.NewStdTxBase(fee, nil, memo),
|
||||
}
|
||||
|
||||
if err := tx.SetMsgs(sdkMsgs...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// GetMsgs returns all the messages in a Transaction as a slice of sdk.Msg.
|
||||
func (tx Transaction) GetMsgs() []sdk.Msg {
|
||||
msgs := make([]sdk.Msg, len(tx.Msgs))
|
||||
|
||||
for i, m := range tx.Msgs {
|
||||
msgs[i] = m.GetMsg()
|
||||
}
|
||||
|
||||
return msgs
|
||||
}
|
||||
|
||||
// GetSigners returns the addresses that must sign the transaction. Addresses are
|
||||
// returned in a deterministic order. They are accumulated from the GetSigners
|
||||
// method for each Msg in the order they appear in tx.GetMsgs(). Duplicate addresses
|
||||
// will be omitted.
|
||||
func (tx Transaction) GetSigners() []sdk.AccAddress {
|
||||
var signers []sdk.AccAddress
|
||||
seen := map[string]bool{}
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
for _, addr := range msg.GetSigners() {
|
||||
if !seen[addr.String()] {
|
||||
signers = append(signers, addr)
|
||||
seen[addr.String()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signers
|
||||
}
|
||||
|
||||
// ValidateBasic does a simple and lightweight validation check that doesn't
|
||||
// require access to any other information.
|
||||
func (tx Transaction) ValidateBasic() error {
|
||||
stdSigs := tx.GetSignatures()
|
||||
|
||||
if tx.Fee.Gas > auth.MaxGasWanted {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidRequest, "invalid gas supplied; %d > %d", tx.Fee.Gas, auth.MaxGasWanted,
|
||||
)
|
||||
}
|
||||
if tx.Fee.Amount.IsAnyNegative() {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee, "invalid fee provided: %s", tx.Fee.Amount,
|
||||
)
|
||||
}
|
||||
if len(stdSigs) == 0 {
|
||||
return sdkerrors.ErrNoSignatures
|
||||
}
|
||||
if len(stdSigs) != len(tx.GetSigners()) {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnauthorized, "wrong number of signers; expected %d, got %d", tx.GetSigners(), len(stdSigs),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetMsgs sets the messages for a Transaction. It will overwrite any existing
|
||||
// messages set.
|
||||
func (tx *Transaction) SetMsgs(sdkMsgs ...sdk.Msg) error {
|
||||
msgs := make([]Message, len(sdkMsgs))
|
||||
for i, msg := range sdkMsgs {
|
||||
m := &Message{}
|
||||
if err := m.SetMsg(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msgs[i] = *m
|
||||
}
|
||||
|
||||
tx.Msgs = msgs
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSignatures returns all the transaction's signatures.
|
||||
func (tx Transaction) GetSignatures() []sdk.Signature {
|
||||
sdkSigs := make([]sdk.Signature, len(tx.Signatures))
|
||||
for i, sig := range tx.Signatures {
|
||||
sdkSigs[i] = sig
|
||||
}
|
||||
|
||||
return sdkSigs
|
||||
}
|
||||
|
||||
// SetSignatures sets the transaction's signatures. It will overwrite any
|
||||
// existing signatures set.
|
||||
func (tx *Transaction) SetSignatures(sdkSigs ...sdk.Signature) {
|
||||
sigs := make([]auth.StdSignature, len(tx.Signatures))
|
||||
for i, sig := range sdkSigs {
|
||||
sigs[i] = auth.NewStdSignature(sig.GetPubKey(), sig.GetSignature())
|
||||
}
|
||||
|
||||
tx.Signatures = sigs
|
||||
}
|
||||
|
||||
// GetFee returns the transaction's fee.
|
||||
func (tx Transaction) GetFee() sdk.Fee {
|
||||
return tx.Fee
|
||||
}
|
||||
|
||||
// SetFee sets the transaction's fee. It will overwrite any existing fee set.
|
||||
func (tx *Transaction) SetFee(fee sdk.Fee) {
|
||||
tx.Fee = auth.NewStdFee(fee.GetGas(), fee.GetAmount())
|
||||
}
|
||||
|
||||
// GetMemo returns the transaction's memo.
|
||||
func (tx Transaction) GetMemo() string {
|
||||
return tx.Memo
|
||||
}
|
||||
|
||||
// SetMemo sets the transaction's memo. It will overwrite any existing memo set.
|
||||
func (tx *Transaction) SetMemo(memo string) {
|
||||
tx.Memo = memo
|
||||
}
|
||||
|
||||
// CanonicalSignBytes returns the canonical JSON bytes to sign over for the
|
||||
// Transaction given a chain ID, account sequence and account number. The JSON
|
||||
// encoding ensures all field names adhere to their proto definition, default
|
||||
// values are omitted, and follows the JSON Canonical Form.
|
||||
func (tx Transaction) CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error) {
|
||||
return NewSignDoc(num, seq, cid, tx.Memo, tx.Fee, tx.Msgs...).CanonicalSignBytes()
|
||||
}
|
||||
|
||||
func NewSignDoc(num, seq uint64, cid, memo string, fee auth.StdFee, msgs ...Message) *SignDoc {
|
||||
return &SignDoc{
|
||||
StdSignDocBase: auth.NewStdSignDocBase(num, seq, cid, memo, fee),
|
||||
Msgs: msgs,
|
||||
}
|
||||
}
|
||||
|
||||
// CanonicalSignBytes returns the canonical JSON bytes to sign over, where the
|
||||
// SignDoc is derived from a Transaction. The JSON encoding ensures all field
|
||||
// names adhere to their proto definition, default values are omitted, and follows
|
||||
// the JSON Canonical Form.
|
||||
func (sd *SignDoc) CanonicalSignBytes() ([]byte, error) {
|
||||
return sdk.CanonicalSignBytes(sd)
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package std_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/std"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
func TestTransaction(t *testing.T) {
|
||||
f := auth.NewStdFee(100, sdk.NewCoins(sdk.NewInt64Coin("stake", 50)))
|
||||
m := "hello world"
|
||||
acc1 := sdk.AccAddress("from")
|
||||
acc2 := sdk.AccAddress("to")
|
||||
msg1 := bank.NewMsgSend(acc1, acc2, sdk.NewCoins(sdk.NewInt64Coin("stake", 100000)))
|
||||
sdkMsgs := []sdk.Msg{&msg1}
|
||||
|
||||
tx, err := std.NewTransaction(f, m, sdkMsgs)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tx)
|
||||
require.Equal(t, tx.GetMsgs(), sdkMsgs)
|
||||
require.Equal(t, tx.GetSigners(), []sdk.AccAddress{acc1})
|
||||
require.Equal(t, tx.GetFee(), f)
|
||||
require.Equal(t, tx.GetMemo(), m)
|
||||
|
||||
// no signatures; validation should fail
|
||||
require.Empty(t, tx.GetSignatures())
|
||||
require.Error(t, tx.ValidateBasic())
|
||||
|
||||
signDocJSON := `{"base":{"accountNumber":"1","chainId":"chain-test","fee":{"amount":[{"amount":"50","denom":"stake"}],"gas":"100"},"memo":"hello world","sequence":"21"},"msgs":[{"msgSend":{"amount":[{"amount":"100000","denom":"stake"}],"fromAddress":"cosmos1veex7mgzt83cu","toAddress":"cosmos1w3hsjttrfq"}}]}`
|
||||
bz, err := tx.CanonicalSignBytes("chain-test", 1, 21)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, signDocJSON, string(bz))
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
## Changelog
|
||||
|
||||
- 2020 March 06: Initial Draft
|
||||
- 2020 March 12: API Updates
|
||||
|
||||
## Status
|
||||
|
||||
|
@ -43,9 +44,9 @@ message Message {
|
|||
option (cosmos_proto.interface_type) = "github.com/cosmos/cosmos-sdk/types.Msg";
|
||||
|
||||
oneof sum {
|
||||
bank.MsgSend = 1;
|
||||
staking.MsgCreateValidator = 2;
|
||||
staking.MsgDelegate = 3;
|
||||
cosmos_sdk.x.bank.v1.MsgSend msg_send = 1;
|
||||
cosmos_sdk.x.bank.v1.MsgMultiSend msg_multi_send = 2;
|
||||
cosmos_sdk.x.crisis.v1.MsgVerifyInvariant msg_verify_invariant = 3;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
@ -61,10 +62,8 @@ Example:
|
|||
// app/codec/codec.proto
|
||||
|
||||
message Transaction {
|
||||
option (cosmos_proto.interface_type) = "github.com/cosmos/cosmos-sdk/types.Tx";
|
||||
|
||||
StdTxBase base = 1;
|
||||
repeated Message msgs = 2;
|
||||
cosmos_sdk.x.auth.v1.StdTxBase base = 1;
|
||||
repeated Message msgs = 2;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -80,7 +79,8 @@ to provide canonical representation of a `Transaction` to sign over, clients mus
|
|||
obey the following rules:
|
||||
|
||||
- Encode `SignDoc` (see below) via [Protobuf's canonical JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json).
|
||||
- Default and zero values must be stripped from the output (`0`, `“”`, `null`, `false`, `[]`, and `{}`).
|
||||
- Default must be stripped from the output!
|
||||
- JSON keys adhere to their Proto-defined field names.
|
||||
- Generate canonical JSON to sign via the [JSON Canonical Form Spec](https://gibson042.github.io/canonicaljson-spec/).
|
||||
- This spec should be trivial to interpret and implement in any language.
|
||||
|
||||
|
@ -103,9 +103,8 @@ to handle all the types, but also knows how to generate transactions, signatures
|
|||
and messages.
|
||||
|
||||
```go
|
||||
type TxGenerator interface {
|
||||
type Generator interface {
|
||||
NewTx() ClientTx
|
||||
SignBytes func(chainID string, num, seq uint64, fee StdFee, msgs []sdk.Msg, memo string) ([]byte, error)
|
||||
}
|
||||
|
||||
type ClientTx interface {
|
||||
|
@ -113,27 +112,22 @@ type ClientTx interface {
|
|||
codec.ProtoMarshaler
|
||||
|
||||
SetMsgs(...sdk.Msg) error
|
||||
GetSignatures() []StdSignature
|
||||
SetSignatures(...StdSignature) error
|
||||
GetFee() StdFee
|
||||
SetFee(StdFee)
|
||||
GetSignatures() []sdk.Signature
|
||||
SetSignatures(...sdk.Signature)
|
||||
GetFee() sdk.Fee
|
||||
SetFee(sdk.Fee)
|
||||
GetMemo() string
|
||||
SetMemo(string)
|
||||
|
||||
CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error)
|
||||
}
|
||||
```
|
||||
|
||||
We then extend `codec.Marshaler` to also require fulfillment of `TxGenerator`.
|
||||
We then update `CLIContext` to have two new fields: `Generator` and `Marshler`.
|
||||
|
||||
```go
|
||||
type ClientMarshaler interface {
|
||||
TxGenerator
|
||||
codec.Marshaler
|
||||
}
|
||||
```
|
||||
|
||||
Then, each module will at the minimum accept a `ClientMarshaler` instead of a concrete
|
||||
Then, each module will at the minimum accept a `Marshaler` instead of a concrete
|
||||
Amino codec. If the module needs to work with any interface types, it will use
|
||||
the `Codec` interface defined by the module which also extends `ClientMarshaler`.
|
||||
the `Codec` interface defined by the module which also extends `Marshaler`.
|
||||
|
||||
## Future Improvements
|
||||
|
||||
|
|
4
go.mod
4
go.mod
|
@ -7,9 +7,10 @@ require (
|
|||
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1
|
||||
github.com/gibson042/canonicaljson-go v1.0.3
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/golang/mock v1.4.3
|
||||
github.com/golang/protobuf v1.3.5
|
||||
github.com/golang/protobuf v1.4.0-rc.4
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
|
@ -30,6 +31,7 @@ require (
|
|||
github.com/tendermint/iavl v0.13.1
|
||||
github.com/tendermint/tendermint v0.33.2
|
||||
github.com/tendermint/tm-db v0.5.0
|
||||
google.golang.org/protobuf v1.20.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
)
|
||||
|
||||
|
|
19
go.sum
19
go.sum
|
@ -111,6 +111,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
|
|||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gibson042/canonicaljson-go v1.0.3 h1:EAyF8L74AWabkyUmrvEFHEt/AGFQeD6RfwbAuf0j1bI=
|
||||
github.com/gibson042/canonicaljson-go v1.0.3/go.mod h1:DsLpJTThXyGNO+KZlI85C1/KDcImpP67k/RKVjcaEqo=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
|
||||
|
@ -130,8 +132,6 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
|
|||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.4.2 h1:fXIkPzOBCwDUPvYmOPzETABgbqpYlYNigQ2o64eMr5c=
|
||||
github.com/golang/mock v1.4.2/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -140,8 +140,11 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
|||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4 h1:+EOh4OY6tjM6ZueeUKinl1f0U2820HzQOuf1iqMnsks=
|
||||
github.com/golang/protobuf v1.4.0-rc.4/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
|
@ -558,6 +561,12 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.20.1 h1:ESRXHgpUBG5D2I5mmsQIyYxB/tQIZfSZ8wLyFDf/N/U=
|
||||
google.golang.org/protobuf v1.20.1/go.mod h1:KqelGeouBkcbcuB3HCk4/YH2tmNLk6YSWA5LIWeI/lY=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -585,9 +594,7 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
|
|
|
@ -39,7 +39,7 @@ func GenTx(msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accnums
|
|||
}
|
||||
|
||||
sigs[i] = auth.StdSignature{
|
||||
PubKey: p.PubKey(),
|
||||
PubKey: p.PubKey().Bytes(),
|
||||
Signature: sig,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
jsonc "github.com/gibson042/canonicaljson-go"
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
)
|
||||
|
||||
|
@ -9,3 +14,27 @@ func RegisterCodec(cdc *codec.Codec) {
|
|||
cdc.RegisterInterface((*Msg)(nil), nil)
|
||||
cdc.RegisterInterface((*Tx)(nil), nil)
|
||||
}
|
||||
|
||||
// CanonicalSignBytes returns a canonical JSON encoding of a Proto message that
|
||||
// can be signed over. The JSON encoding ensures all field names adhere to their
|
||||
// Proto definition, default values are omitted, and follows the JSON Canonical
|
||||
// Form.
|
||||
func CanonicalSignBytes(m codec.ProtoMarshaler) ([]byte, error) {
|
||||
jm := &jsonpb.Marshaler{EmitDefaults: false, OrigName: false}
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// first, encode via canonical Protocol Buffer JSON
|
||||
if err := jm.Marshal(buf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
genericJSON := make(map[string]interface{})
|
||||
|
||||
// decode canonical proto encoding into a generic map
|
||||
if err := jsonc.Unmarshal(buf.Bytes(), &genericJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// finally, return the canonical JSON encoding via JSON Canonical Form
|
||||
return jsonc.Marshal(genericJSON)
|
||||
}
|
||||
|
|
|
@ -2,45 +2,59 @@ package types
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
// Transactions messages must fulfill the Msg
|
||||
type Msg interface {
|
||||
type (
|
||||
// Msg defines the interface a transaction message must fulfill.
|
||||
Msg interface {
|
||||
|
||||
// Return the message type.
|
||||
// Must be alphanumeric or empty.
|
||||
Route() string
|
||||
// Return the message type.
|
||||
// Must be alphanumeric or empty.
|
||||
Route() string
|
||||
|
||||
// Returns a human-readable string for the message, intended for utilization
|
||||
// within tags
|
||||
Type() string
|
||||
// Returns a human-readable string for the message, intended for utilization
|
||||
// within tags
|
||||
Type() string
|
||||
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
|
||||
// Get the canonical byte representation of the Msg.
|
||||
GetSignBytes() []byte
|
||||
// Get the canonical byte representation of the Msg.
|
||||
GetSignBytes() []byte
|
||||
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
GetSigners() []AccAddress
|
||||
}
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
GetSigners() []AccAddress
|
||||
}
|
||||
|
||||
//__________________________________________________________
|
||||
// Fee defines an interface for an application application-defined concrete
|
||||
// transaction type to be able to set and return the transaction fee.
|
||||
Fee interface {
|
||||
GetGas() uint64
|
||||
GetAmount() Coins
|
||||
}
|
||||
|
||||
// Transactions objects must fulfill the Tx
|
||||
type Tx interface {
|
||||
// Gets the all the transaction's messages.
|
||||
GetMsgs() []Msg
|
||||
// Signature defines an interface for an application application-defined
|
||||
// concrete transaction type to be able to set and return transaction signatures.
|
||||
Signature interface {
|
||||
GetPubKey() crypto.PubKey
|
||||
GetSignature() []byte
|
||||
}
|
||||
|
||||
// ValidateBasic does a simple and lightweight validation check that doesn't
|
||||
// require access to any other information.
|
||||
ValidateBasic() error
|
||||
}
|
||||
// Tx defines the interface a transaction must fulfill.
|
||||
Tx interface {
|
||||
// Gets the all the transaction's messages.
|
||||
GetMsgs() []Msg
|
||||
|
||||
//__________________________________________________________
|
||||
// ValidateBasic does a simple and lightweight validation check that doesn't
|
||||
// require access to any other information.
|
||||
ValidateBasic() error
|
||||
}
|
||||
)
|
||||
|
||||
// TxDecoder unmarshals transaction bytes
|
||||
type TxDecoder func(txBytes []byte) (Tx, error)
|
||||
|
|
|
@ -22,6 +22,7 @@ const (
|
|||
DefaultSigVerifyCostSecp256k1 = types.DefaultSigVerifyCostSecp256k1
|
||||
QueryAccount = types.QueryAccount
|
||||
QueryParams = types.QueryParams
|
||||
MaxGasWanted = types.MaxGasWanted
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -58,6 +59,9 @@ var (
|
|||
MakeSignature = types.MakeSignature
|
||||
ValidateGenAccounts = types.ValidateGenAccounts
|
||||
GetGenesisStateFromAppState = types.GetGenesisStateFromAppState
|
||||
NewStdSignature = types.NewStdSignature
|
||||
NewStdTxBase = types.NewStdTxBase
|
||||
NewStdSignDocBase = types.NewStdSignDocBase
|
||||
|
||||
// variable aliases
|
||||
ModuleCdc = types.ModuleCdc
|
||||
|
@ -87,4 +91,6 @@ type (
|
|||
TxBuilder = types.TxBuilder
|
||||
GenesisAccountIterator = types.GenesisAccountIterator
|
||||
Codec = types.Codec
|
||||
StdSignDocBase = types.StdSignDocBase
|
||||
StdTxBase = types.StdTxBase
|
||||
)
|
||||
|
|
|
@ -127,7 +127,7 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim
|
|||
// use stdsignature to mock the size of a full signature
|
||||
simSig := types.StdSignature{
|
||||
Signature: simSecp256k1Sig[:],
|
||||
PubKey: pubkey,
|
||||
PubKey: pubkey.Bytes(),
|
||||
}
|
||||
|
||||
sigBz := codec.Cdc.MustMarshalBinaryBare(simSig)
|
||||
|
|
|
@ -106,15 +106,15 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
|
|||
txBldr.ChainID(), txBldr.AccountNumber(), txBldr.Sequence(),
|
||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
if ok := stdSig.PubKey.VerifyBytes(sigBytes, stdSig.Signature); !ok {
|
||||
if ok := stdSig.GetPubKey().VerifyBytes(sigBytes, stdSig.Signature); !ok {
|
||||
return fmt.Errorf("couldn't verify signature")
|
||||
}
|
||||
if err := multisigSig.AddSignatureFromPubKey(stdSig.Signature, stdSig.PubKey, multisigPub.PubKeys); err != nil {
|
||||
if err := multisigSig.AddSignatureFromPubKey(stdSig.Signature, stdSig.GetPubKey(), multisigPub.PubKeys); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
newStdSig := types.StdSignature{Signature: cdc.MustMarshalBinaryBare(multisigSig), PubKey: multisigPub}
|
||||
newStdSig := types.StdSignature{Signature: cdc.MustMarshalBinaryBare(multisigSig), PubKey: multisigPub.Bytes()}
|
||||
newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo())
|
||||
|
||||
sigOnly := viper.GetBool(flagSigOnly)
|
||||
|
|
|
@ -208,7 +208,7 @@ func printAndValidateSigs(
|
|||
}
|
||||
|
||||
for i, sig := range sigs {
|
||||
sigAddr := sdk.AccAddress(sig.Address())
|
||||
sigAddr := sdk.AccAddress(sig.GetPubKey().Address())
|
||||
sigSanity := "OK"
|
||||
|
||||
var (
|
||||
|
@ -235,13 +235,13 @@ func printAndValidateSigs(
|
|||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
|
||||
if ok := sig.VerifyBytes(sigBytes, sig.Signature); !ok {
|
||||
if ok := sig.GetPubKey().VerifyBytes(sigBytes, sig.Signature); !ok {
|
||||
sigSanity = "ERROR: signature invalid"
|
||||
success = false
|
||||
}
|
||||
}
|
||||
|
||||
multiPK, ok := sig.PubKey.(multisig.PubKeyMultisigThreshold)
|
||||
multiPK, ok := sig.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||
if ok {
|
||||
var multiSig multisig.Multisignature
|
||||
cliCtx.Codec.MustUnmarshalBinaryBare(sig.Signature, &multiSig)
|
||||
|
|
|
@ -14,11 +14,137 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
)
|
||||
|
||||
var (
|
||||
_ sdk.Tx = (*StdTx)(nil)
|
||||
// MaxGasWanted defines the max gas allowed.
|
||||
const MaxGasWanted = uint64((1 << 63) - 1)
|
||||
|
||||
maxGasWanted = uint64((1 << 63) - 1)
|
||||
)
|
||||
// NewStdFee returns a new instance of StdFee
|
||||
func NewStdFee(gas uint64, amount sdk.Coins) StdFee {
|
||||
return StdFee{
|
||||
Amount: amount,
|
||||
Gas: gas,
|
||||
}
|
||||
}
|
||||
|
||||
// GetGas returns the fee's (wanted) gas.
|
||||
func (fee StdFee) GetGas() uint64 {
|
||||
return fee.Gas
|
||||
}
|
||||
|
||||
// GetAmount returns the fee's amount.
|
||||
func (fee StdFee) GetAmount() sdk.Coins {
|
||||
return fee.Amount
|
||||
}
|
||||
|
||||
// Bytes returns the encoded bytes of a StdFee.
|
||||
func (fee StdFee) Bytes() []byte {
|
||||
if len(fee.Amount) == 0 {
|
||||
fee.Amount = sdk.NewCoins()
|
||||
}
|
||||
|
||||
bz, err := codec.Cdc.MarshalJSON(fee)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
||||
// GasPrices returns the gas prices for a StdFee.
|
||||
//
|
||||
// NOTE: The gas prices returned are not the true gas prices that were
|
||||
// originally part of the submitted transaction because the fee is computed
|
||||
// as fee = ceil(gasWanted * gasPrices).
|
||||
func (fee StdFee) GasPrices() sdk.DecCoins {
|
||||
return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas)))
|
||||
}
|
||||
|
||||
func NewStdSignature(pk crypto.PubKey, sig []byte) StdSignature {
|
||||
return StdSignature{PubKey: pk.Bytes(), Signature: sig}
|
||||
}
|
||||
|
||||
// GetSignature returns the raw signature bytes.
|
||||
func (ss StdSignature) GetSignature() []byte {
|
||||
return ss.Signature
|
||||
}
|
||||
|
||||
// GetPubKey returns the public key of a signature as a crypto.PubKey using the
|
||||
// Amino codec.
|
||||
func (ss StdSignature) GetPubKey() (pk crypto.PubKey) {
|
||||
if len(ss.PubKey) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
codec.Cdc.MustUnmarshalBinaryBare(ss.PubKey, &pk)
|
||||
return pk
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML representation of the signature.
|
||||
func (ss StdSignature) MarshalYAML() (interface{}, error) {
|
||||
var (
|
||||
bz []byte
|
||||
pubkey string
|
||||
err error
|
||||
)
|
||||
|
||||
if ss.PubKey != nil {
|
||||
pubkey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, ss.GetPubKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bz, err = yaml.Marshal(struct {
|
||||
PubKey string
|
||||
Signature string
|
||||
}{
|
||||
PubKey: pubkey,
|
||||
Signature: fmt.Sprintf("%X", ss.Signature),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return string(bz), err
|
||||
}
|
||||
|
||||
func NewStdTxBase(fee StdFee, sigs []StdSignature, memo string) StdTxBase {
|
||||
return StdTxBase{
|
||||
Fee: fee,
|
||||
Signatures: sigs,
|
||||
Memo: memo,
|
||||
}
|
||||
}
|
||||
|
||||
func NewStdSignDocBase(num, seq uint64, cid, memo string, fee StdFee) StdSignDocBase {
|
||||
return StdSignDocBase{
|
||||
ChainID: cid,
|
||||
AccountNumber: num,
|
||||
Sequence: seq,
|
||||
Memo: memo,
|
||||
Fee: fee,
|
||||
}
|
||||
}
|
||||
|
||||
// CountSubKeys counts the total number of keys for a multi-sig public key.
|
||||
func CountSubKeys(pub crypto.PubKey) int {
|
||||
v, ok := pub.(multisig.PubKeyMultisigThreshold)
|
||||
if !ok {
|
||||
return 1
|
||||
}
|
||||
|
||||
numKeys := 0
|
||||
for _, subkey := range v.PubKeys {
|
||||
numKeys += CountSubKeys(subkey)
|
||||
}
|
||||
|
||||
return numKeys
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DEPRECATED
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var _ sdk.Tx = (*StdTx)(nil)
|
||||
|
||||
// StdTx is a standard way to wrap a Msg with Fee and Signatures.
|
||||
// NOTE: the first signature is the fee payer (Signatures must not be nil).
|
||||
|
@ -46,10 +172,10 @@ func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs }
|
|||
func (tx StdTx) ValidateBasic() error {
|
||||
stdSigs := tx.GetSignatures()
|
||||
|
||||
if tx.Fee.Gas > maxGasWanted {
|
||||
if tx.Fee.Gas > MaxGasWanted {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted,
|
||||
"invalid gas supplied; %d > %d", tx.Fee.Gas, MaxGasWanted,
|
||||
)
|
||||
}
|
||||
if tx.Fee.Amount.IsAnyNegative() {
|
||||
|
@ -71,29 +197,15 @@ func (tx StdTx) ValidateBasic() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CountSubKeys counts the total number of keys for a multi-sig public key.
|
||||
func CountSubKeys(pub crypto.PubKey) int {
|
||||
v, ok := pub.(multisig.PubKeyMultisigThreshold)
|
||||
if !ok {
|
||||
return 1
|
||||
}
|
||||
|
||||
numKeys := 0
|
||||
for _, subkey := range v.PubKeys {
|
||||
numKeys += CountSubKeys(subkey)
|
||||
}
|
||||
|
||||
return numKeys
|
||||
}
|
||||
|
||||
// GetSigners returns the addresses that must sign the transaction.
|
||||
// Addresses are returned in a deterministic order.
|
||||
// They are accumulated from the GetSigners method for each Msg
|
||||
// in the order they appear in tx.GetMsgs().
|
||||
// Duplicate addresses will be omitted.
|
||||
func (tx StdTx) GetSigners() []sdk.AccAddress {
|
||||
seen := map[string]bool{}
|
||||
var signers []sdk.AccAddress
|
||||
seen := map[string]bool{}
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
for _, addr := range msg.GetSigners() {
|
||||
if !seen[addr.String()] {
|
||||
|
@ -102,6 +214,7 @@ func (tx StdTx) GetSigners() []sdk.AccAddress {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signers
|
||||
}
|
||||
|
||||
|
@ -127,9 +240,11 @@ func (tx StdTx) GetSignatures() [][]byte {
|
|||
// If pubkey is not included in the signature, then nil is in the slice instead
|
||||
func (tx StdTx) GetPubKeys() []crypto.PubKey {
|
||||
pks := make([]crypto.PubKey, len(tx.Signatures))
|
||||
|
||||
for i, stdSig := range tx.Signatures {
|
||||
pks[i] = stdSig.PubKey
|
||||
pks[i] = stdSig.GetPubKey()
|
||||
}
|
||||
|
||||
return pks
|
||||
}
|
||||
|
||||
|
@ -163,43 +278,6 @@ func (tx StdTx) FeePayer() sdk.AccAddress {
|
|||
return sdk.AccAddress{}
|
||||
}
|
||||
|
||||
// NewStdFee returns a new instance of StdFee
|
||||
func NewStdFee(gas uint64, amount sdk.Coins) StdFee {
|
||||
return StdFee{
|
||||
Amount: amount,
|
||||
Gas: gas,
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes for signing later
|
||||
func (fee StdFee) Bytes() []byte {
|
||||
// normalize. XXX
|
||||
// this is a sign of something ugly
|
||||
// (in the lcd_test, client side its null,
|
||||
// server side its [])
|
||||
if len(fee.Amount) == 0 {
|
||||
fee.Amount = sdk.NewCoins()
|
||||
}
|
||||
|
||||
bz, err := codec.Cdc.MarshalJSON(fee) // TODO
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
||||
// GasPrices returns the gas prices for a StdFee.
|
||||
//
|
||||
// NOTE: The gas prices returned are not the true gas prices that were
|
||||
// originally part of the submitted transaction because the fee is computed
|
||||
// as fee = ceil(gasWanted * gasPrices).
|
||||
func (fee StdFee) GasPrices() sdk.DecCoins {
|
||||
return sdk.NewDecCoinsFromCoins(fee.Amount...).QuoDec(sdk.NewDec(int64(fee.Gas)))
|
||||
}
|
||||
|
||||
//__________________________________________________________
|
||||
|
||||
// StdSignDoc is replay-prevention structure.
|
||||
// It includes the result of msg.GetSignBytes(),
|
||||
// as well as the ChainID (prevent cross chain replay)
|
||||
|
@ -237,12 +315,6 @@ func StdSignBytes(chainID string, accnum uint64, sequence uint64, fee StdFee, ms
|
|||
return sdk.MustSortJSON(bz)
|
||||
}
|
||||
|
||||
// StdSignature represents a sig
|
||||
type StdSignature struct {
|
||||
crypto.PubKey `json:"pub_key" yaml:"pub_key"` // optional
|
||||
Signature []byte `json:"signature" yaml:"signature"`
|
||||
}
|
||||
|
||||
// DefaultTxDecoder logic for standard transaction decoding
|
||||
func DefaultTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
|
||||
return func(txBytes []byte) (sdk.Tx, error) {
|
||||
|
@ -269,32 +341,3 @@ func DefaultTxEncoder(cdc *codec.Codec) sdk.TxEncoder {
|
|||
return cdc.MarshalBinaryBare(tx)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML representation of the signature.
|
||||
func (ss StdSignature) MarshalYAML() (interface{}, error) {
|
||||
var (
|
||||
bz []byte
|
||||
pubkey string
|
||||
err error
|
||||
)
|
||||
|
||||
if ss.PubKey != nil {
|
||||
pubkey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, ss.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bz, err = yaml.Marshal(struct {
|
||||
PubKey string
|
||||
Signature string
|
||||
}{
|
||||
PubKey: pubkey,
|
||||
Signature: fmt.Sprintf("%s", ss.Signature),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return string(bz), err
|
||||
}
|
||||
|
|
|
@ -152,11 +152,11 @@ func TestStdSignatureMarshalYAML(t *testing.T) {
|
|||
"|\n pubkey: \"\"\n signature: \"\"\n",
|
||||
},
|
||||
{
|
||||
StdSignature{PubKey: pubKey, Signature: []byte("dummySig")},
|
||||
fmt.Sprintf("|\n pubkey: %s\n signature: dummySig\n", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)),
|
||||
StdSignature{PubKey: pubKey.Bytes(), Signature: []byte("dummySig")},
|
||||
fmt.Sprintf("|\n pubkey: %s\n signature: 64756D6D79536967\n", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)),
|
||||
},
|
||||
{
|
||||
StdSignature{PubKey: pubKey, Signature: nil},
|
||||
StdSignature{PubKey: pubKey.Bytes(), Signature: nil},
|
||||
fmt.Sprintf("|\n pubkey: %s\n signature: \"\"\n", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums
|
|||
panic(err)
|
||||
}
|
||||
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey().Bytes(), Signature: sig}
|
||||
}
|
||||
|
||||
tx := NewStdTx(msgs, fee, sigs, "")
|
||||
|
@ -59,7 +59,7 @@ func NewTestTxWithMemo(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey,
|
|||
panic(err)
|
||||
}
|
||||
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey().Bytes(), Signature: sig}
|
||||
}
|
||||
|
||||
tx := NewStdTx(msgs, fee, sigs, memo)
|
||||
|
@ -74,7 +74,7 @@ func NewTestTxWithSignBytes(msgs []sdk.Msg, privs []crypto.PrivKey, accNums []ui
|
|||
panic(err)
|
||||
}
|
||||
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: sig}
|
||||
sigs[i] = StdSignature{PubKey: priv.PubKey().Bytes(), Signature: sig}
|
||||
}
|
||||
|
||||
tx := NewStdTx(msgs, fee, sigs, memo)
|
||||
|
|
|
@ -286,8 +286,9 @@ func MakeSignature(keybase keys.Keybase, name, passphrase string,
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return StdSignature{
|
||||
PubKey: pubkey,
|
||||
PubKey: pubkey.Bytes(),
|
||||
Signature: sigBytes,
|
||||
}, nil
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,13 +23,23 @@ message BaseAccount {
|
|||
// gas to be used by the transaction. The ratio yields an effective "gasprice",
|
||||
// which must be above some miminum to be accepted into the mempool.
|
||||
message StdFee {
|
||||
option (gogoproto.equal) = true;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (gogoproto.equal) = true;
|
||||
|
||||
repeated cosmos_sdk.v1.Coin amount = 1
|
||||
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
|
||||
uint64 gas = 2;
|
||||
}
|
||||
|
||||
// StdSignature defines a signature structure that contains the signature of a
|
||||
// transaction and an optional public key.
|
||||
message StdSignature {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
bytes pub_key = 1 [(gogoproto.jsontag) = "public_key,omitempty", (gogoproto.moretags) = "yaml:\"public_key\""];
|
||||
bytes signature = 2;
|
||||
}
|
||||
|
||||
// Params defines the parameters for the auth module.
|
||||
message Params {
|
||||
option (gogoproto.equal) = true;
|
||||
|
@ -43,3 +53,21 @@ message Params {
|
|||
uint64 sig_verify_cost_secp256k1 = 5
|
||||
[(gogoproto.customname) = "SigVerifyCostSecp256k1", (gogoproto.moretags) = "yaml:\"sig_verify_cost_secp256k1\""];
|
||||
}
|
||||
|
||||
// StdTxBase defines a transaction base which application-level concrete transaction
|
||||
// types can extend.
|
||||
message StdTxBase {
|
||||
StdFee fee = 1 [(gogoproto.nullable) = false];
|
||||
repeated StdSignature signatures = 2 [(gogoproto.nullable) = false];
|
||||
string memo = 3;
|
||||
}
|
||||
|
||||
// StdSignDocBase defines the base structure for which applications can extend
|
||||
// to define the concrete structure that signers sign over.
|
||||
message StdSignDocBase {
|
||||
string chain_id = 1 [(gogoproto.customname) = "ChainID", (gogoproto.moretags) = "yaml:\"chain_id\""];
|
||||
uint64 account_number = 2 [(gogoproto.moretags) = "yaml:\"account_number\""];
|
||||
uint64 sequence = 3;
|
||||
string memo = 4;
|
||||
StdFee fee = 5 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue