This commit is contained in:
Aleksandr Bezobchuk 2020-03-13 09:51:11 -04:00
parent 0b76411469
commit 0a79849d6e
No known key found for this signature in database
GPG Key ID: 7DAC30FBD99879B0
2 changed files with 123 additions and 17 deletions

View File

@ -6,12 +6,28 @@ import (
jsonc "github.com/gibson042/canonicaljson-go"
"github.com/gogo/protobuf/jsonpb"
"github.com/cosmos/cosmos-sdk/client"
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{}
var (
_ sdk.Tx = (*Transaction)(nil)
_ client.ClientTx = (*Transaction)(nil)
)
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 {
@ -47,16 +63,16 @@ func (tx Transaction) GetSigners() []sdk.AccAddress {
// ValidateBasic does a simple and lightweight validation check that doesn't
// require access to any other information.
func (tx Transaction) ValidateBasic() error {
stdSigs := tx.Base.GetSignatures()
stdSigs := tx.GetSignatures()
if tx.Base.Fee.Gas > auth.MaxGasWanted {
if tx.Fee.Gas > auth.MaxGasWanted {
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid gas supplied; %d > %d", tx.Base.Fee.Gas, auth.MaxGasWanted,
sdkerrors.ErrInvalidRequest, "invalid gas supplied; %d > %d", tx.Fee.Gas, auth.MaxGasWanted,
)
}
if tx.Base.Fee.Amount.IsAnyNegative() {
if tx.Fee.Amount.IsAnyNegative() {
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee, "invalid fee provided: %s", tx.Base.Fee.Amount,
sdkerrors.ErrInsufficientFee, "invalid fee provided: %s", tx.Fee.Amount,
)
}
if len(stdSigs) == 0 {
@ -71,23 +87,75 @@ func (tx Transaction) ValidateBasic() error {
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, a, s uint64) ([]byte, error) {
return NewSignDoc(a, s, cid, tx.Base.Memo, tx.Base.Fee, tx.Msgs...).CanonicalSignBytes()
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(a, s uint64, cid, m string, f auth.StdFee, msgs ...Message) *SignDoc {
func NewSignDoc(num, seq uint64, cid, memo string, fee auth.StdFee, msgs ...Message) *SignDoc {
return &SignDoc{
StdSignDocBase: auth.StdSignDocBase{
ChainID: cid,
AccountNumber: a,
Sequence: s,
Memo: m,
Fee: f,
},
StdSignDocBase: auth.NewStdSignDocBase(num, seq, cid, memo, fee),
Msgs: msgs,
}
}

38
codec/std/tx_test.go Normal file
View File

@ -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))
}