Update auth cli commands (#6717)
* add utils * update sign cmd * update multisign cmd * update sign batch cmd * update genutil cmd * add wrap tx builder * update gentx cli * update validate sigs cmd * fix lint * add flag reader to cli * update marshaler for batchscan * add register query server * update to master * remove depricated methods * fix keyring issue * update wraptx * Fix batch scan * fix register interfaces issue * update printOutput * Update Validate Sigs test * WIP on signature JSON * Cleanup * Cleanup * Test fixes * Test fixes * Fixes * WIP on tests * Fix gov tests * fix lint * fix MultiSign tests * fix tests * refactor tests * Cleanup * Address review comments * Update encode * Test fix * Rename SignData func * Fix lint * Fix lint * Revert ReadTxCommandFlags Co-authored-by: Aaron Craelius <aaron@regen.network> Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com>
This commit is contained in:
parent
cf078c0c88
commit
72ebafeeca
|
@ -195,6 +195,17 @@ func (ctx Context) WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceR
|
|||
return ctx
|
||||
}
|
||||
|
||||
// PrintString prints the raw string to ctx.Output or os.Stdout
|
||||
func (ctx Context) PrintString(str string) error {
|
||||
writer := ctx.Output
|
||||
if writer == nil {
|
||||
writer = os.Stdout
|
||||
}
|
||||
|
||||
_, err := writer.Write([]byte(str))
|
||||
return err
|
||||
}
|
||||
|
||||
// PrintOutput outputs toPrint to the ctx.Output based on ctx.OutputFormat which is
|
||||
// either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint
|
||||
// will be JSON encoded using ctx.JSONMarshaler. An error is returned upon failure.
|
||||
|
|
|
@ -172,3 +172,14 @@ func (f Factory) WithSimulateAndExecute(sim bool) Factory {
|
|||
f.simulateAndExecute = sim
|
||||
return f
|
||||
}
|
||||
|
||||
// SignMode returns the sign mode configured in the Factory
|
||||
func (f Factory) SignMode() signing.SignMode {
|
||||
return f.signMode
|
||||
}
|
||||
|
||||
// WithSignMode returns a copy of the Factory with an updated sign mode value.
|
||||
func (f Factory) WithSignMode(mode signing.SignMode) Factory {
|
||||
f.signMode = mode
|
||||
return f
|
||||
}
|
||||
|
|
|
@ -64,7 +64,12 @@ func GenerateTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintOutput(tx.GetTx())
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(tx.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
|
||||
// BroadcastTx attempts to generate, sign and broadcast a transaction with the
|
||||
|
|
|
@ -17,6 +17,8 @@ type (
|
|||
TxDecoder() sdk.TxDecoder
|
||||
TxJSONEncoder() sdk.TxEncoder
|
||||
TxJSONDecoder() sdk.TxDecoder
|
||||
MarshalSignatureJSON([]signingtypes.SignatureV2) ([]byte, error)
|
||||
UnmarshalSignatureJSON([]byte) ([]signingtypes.SignatureV2, error)
|
||||
}
|
||||
|
||||
// TxConfig defines an interface a client can utilize to generate an
|
||||
|
|
|
@ -16,7 +16,9 @@ type ProtoCodec struct {
|
|||
anyUnpacker types.AnyUnpacker
|
||||
}
|
||||
|
||||
func NewProtoCodec(anyUnpacker types.AnyUnpacker) Marshaler {
|
||||
var _ Marshaler = &ProtoCodec{}
|
||||
|
||||
func NewProtoCodec(anyUnpacker types.AnyUnpacker) *ProtoCodec {
|
||||
return &ProtoCodec{anyUnpacker: anyUnpacker}
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ func mustAny(msg proto.Message) *types.Any {
|
|||
}
|
||||
|
||||
func BenchmarkProtoCodecMarshalBinaryLengthPrefixed(b *testing.B) {
|
||||
var pCdc = codec.NewProtoCodec(types.NewInterfaceRegistry()).(*codec.ProtoCodec)
|
||||
var pCdc = codec.NewProtoCodec(types.NewInterfaceRegistry())
|
||||
var msg = &testdata.HasAnimal{
|
||||
X: 1000,
|
||||
Animal: mustAny(&testdata.HasAnimal{
|
||||
|
|
|
@ -17,6 +17,9 @@ type PubKey interface {
|
|||
|
||||
// GetPubKeys returns the crypto.PubKey's nested within the multi-sig PubKey
|
||||
GetPubKeys() []crypto.PubKey
|
||||
|
||||
// GetThreshold returns the threshold number of signatures that must be obtained to verify a signature.
|
||||
GetThreshold() uint
|
||||
}
|
||||
|
||||
// GetSignBytesFunc defines a function type which returns sign bytes for a given SignMode or an error.
|
||||
|
|
|
@ -154,3 +154,8 @@ func (pk PubKeyMultisigThreshold) Equals(other crypto.PubKey) bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// GetThreshold implements the PubKey.GetThreshold method
|
||||
func (pk PubKeyMultisigThreshold) GetThreshold() uint {
|
||||
return pk.K
|
||||
}
|
||||
|
|
5
go.sum
5
go.sum
|
@ -168,8 +168,6 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
|
|||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
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/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -646,7 +644,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
|
|||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
|
@ -772,7 +769,5 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
|||
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/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
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=
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
syntax = "proto3";
|
||||
package cosmos.tx.signing;
|
||||
|
||||
import "cosmos/crypto/crypto.proto";
|
||||
|
||||
option go_package = "github.com/cosmos/cosmos-sdk/types/tx/signing";
|
||||
|
||||
// SignMode represents a signing mode with its own security guarantees
|
||||
|
@ -20,3 +22,49 @@ enum SignMode {
|
|||
// Amino JSON and will be removed in the future
|
||||
SIGN_MODE_LEGACY_AMINO_JSON = 127;
|
||||
}
|
||||
|
||||
// SignatureDescriptors wraps multiple SignatureDescriptor's.
|
||||
message SignatureDescriptors {
|
||||
// signatures are the signature descriptors
|
||||
repeated SignatureDescriptor signatures = 1;
|
||||
}
|
||||
|
||||
// SignatureDescriptor is a convenience type which represents the full data for a
|
||||
// signature including the public key of the signer, signing modes and the signature
|
||||
// itself. It is primarily used for coordinating signatures between clients.
|
||||
message SignatureDescriptor {
|
||||
// public_key is the public key of the signer
|
||||
cosmos.crypto.PublicKey public_key = 1;
|
||||
|
||||
Data data = 2;
|
||||
|
||||
// Data represents signature data
|
||||
message Data {
|
||||
// sum is the oneof that specifies whether this represents single or multi-signature data
|
||||
oneof sum {
|
||||
// single represents a single signer
|
||||
Single single = 1;
|
||||
|
||||
// multi represents a multisig signer
|
||||
Multi multi = 2;
|
||||
}
|
||||
|
||||
// Single is the signature data for a single signer
|
||||
message Single {
|
||||
// mode is the signing mode of the single signer
|
||||
cosmos.tx.signing.SignMode mode = 1;
|
||||
|
||||
// signature is the raw signature bytes
|
||||
bytes signature = 2;
|
||||
}
|
||||
|
||||
// Multi is the signature data for a multisig public key
|
||||
message Multi {
|
||||
// bitarray specifies which keys within the multisig are signing
|
||||
cosmos.crypto.CompactBitArray bitarray = 1;
|
||||
|
||||
// signatures is the signatures of the multi-signature
|
||||
repeated Data signatures = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,15 @@ import (
|
|||
|
||||
// MakeEncodingConfig creates an EncodingConfig for an amino based test configuration.
|
||||
func MakeEncodingConfig() EncodingConfig {
|
||||
cdc := codec.New()
|
||||
amino := codec.New()
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
marshaler := codec.NewHybridCodec(cdc, interfaceRegistry)
|
||||
txGen := tx.NewTxConfig(interfaceRegistry, std.DefaultPublicKeyCodec{}, tx.DefaultSignModeHandler())
|
||||
marshaler := codec.NewHybridCodec(amino, interfaceRegistry)
|
||||
txGen := tx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), std.DefaultPublicKeyCodec{}, tx.DefaultSignModeHandler())
|
||||
|
||||
return EncodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Marshaler: marshaler,
|
||||
TxConfig: txGen,
|
||||
Amino: cdc,
|
||||
Amino: amino,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
tmcfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
@ -29,6 +27,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: cosmos/tx/sig_desc.proto
|
||||
|
||||
package tx
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
func init() { proto.RegisterFile("cosmos/tx/sig_desc.proto", fileDescriptor_d560eb6bd3d62ef7) }
|
||||
|
||||
var fileDescriptor_d560eb6bd3d62ef7 = []byte{
|
||||
// 129 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x48, 0xce, 0x2f, 0xce,
|
||||
0xcd, 0x2f, 0xd6, 0x2f, 0xa9, 0xd0, 0x2f, 0xce, 0x4c, 0x8f, 0x4f, 0x49, 0x2d, 0x4e, 0xd6, 0x2b,
|
||||
0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0xc8, 0xe8, 0x95, 0x54, 0x48, 0xc9, 0xa3, 0x28, 0xca,
|
||||
0xcb, 0xcc, 0x4b, 0x87, 0xd1, 0x10, 0xb5, 0x4e, 0xf6, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24,
|
||||
0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78,
|
||||
0x2c, 0xc7, 0x10, 0xa5, 0x9a, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f,
|
||||
0x35, 0x05, 0x42, 0xe9, 0x16, 0xa7, 0x64, 0xeb, 0x97, 0x54, 0x16, 0xa4, 0x82, 0x8c, 0x4d, 0x62,
|
||||
0x03, 0x9b, 0x63, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x86, 0x8a, 0xa4, 0x8a, 0x8f, 0x00, 0x00,
|
||||
0x00,
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package signing
|
||||
|
||||
import "github.com/tendermint/tendermint/crypto"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
// SignatureV2 is a convenience type that is easier to use in application logic
|
||||
// than the protobuf SignerInfo's and raw signature bytes. It goes beyond the
|
||||
|
@ -15,3 +19,64 @@ type SignatureV2 struct {
|
|||
// the signatures themselves for either single or multi-signatures.
|
||||
Data SignatureData
|
||||
}
|
||||
|
||||
// SignatureDataToProto converts a SignatureData to SignatureDescriptor_Data.
|
||||
// SignatureDescriptor_Data is considered an encoding type whereas SignatureData is used for
|
||||
// business logic.
|
||||
func SignatureDataToProto(data SignatureData) *SignatureDescriptor_Data {
|
||||
switch data := data.(type) {
|
||||
case *SingleSignatureData:
|
||||
return &SignatureDescriptor_Data{
|
||||
Sum: &SignatureDescriptor_Data_Single_{
|
||||
Single: &SignatureDescriptor_Data_Single{
|
||||
Mode: data.SignMode,
|
||||
Signature: data.Signature,
|
||||
},
|
||||
},
|
||||
}
|
||||
case *MultiSignatureData:
|
||||
descDatas := make([]*SignatureDescriptor_Data, len(data.Signatures))
|
||||
|
||||
for j, d := range data.Signatures {
|
||||
descDatas[j] = SignatureDataToProto(d)
|
||||
}
|
||||
|
||||
return &SignatureDescriptor_Data{
|
||||
Sum: &SignatureDescriptor_Data_Multi_{
|
||||
Multi: &SignatureDescriptor_Data_Multi{
|
||||
Bitarray: data.BitArray,
|
||||
Signatures: descDatas,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected case %+v", data))
|
||||
}
|
||||
}
|
||||
|
||||
// SignatureDataFromProto converts a SignatureDescriptor_Data to SignatureData.
|
||||
// SignatureDescriptor_Data is considered an encoding type whereas SignatureData is used for
|
||||
// business logic.
|
||||
func SignatureDataFromProto(descData *SignatureDescriptor_Data) SignatureData {
|
||||
switch descData := descData.Sum.(type) {
|
||||
case *SignatureDescriptor_Data_Single_:
|
||||
return &SingleSignatureData{
|
||||
SignMode: descData.Single.Mode,
|
||||
Signature: descData.Single.Signature,
|
||||
}
|
||||
case *SignatureDescriptor_Data_Multi_:
|
||||
multi := descData.Multi
|
||||
datas := make([]SignatureData, len(multi.Signatures))
|
||||
|
||||
for j, d := range multi.Signatures {
|
||||
datas[j] = SignatureDataFromProto(d)
|
||||
}
|
||||
|
||||
return &MultiSignatureData{
|
||||
BitArray: multi.Bitarray,
|
||||
Signatures: datas,
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected case %+v", descData))
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,19 +14,16 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codec2 "github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
@ -47,7 +44,21 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||
s.cfg = cfg
|
||||
s.network = network.New(s.T(), cfg)
|
||||
|
||||
_, err := s.network.WaitForHeight(1)
|
||||
kb := s.network.Validators[0].ClientCtx.Keyring
|
||||
_, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
_, err = kb.SaveMultisig("multi", multi)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.network.WaitForHeight(1)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
|
@ -73,29 +84,23 @@ func (s *IntegrationTestSuite) TestCLIValidateSignatures() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var tx types.StdTx
|
||||
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// write unsigned tx to file
|
||||
unsignedTx, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||
defer cleanup()
|
||||
|
||||
res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
var signedTx types.StdTx
|
||||
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &signedTx)
|
||||
signedTx, err := val.ClientCtx.TxConfig.TxJSONDecoder()(res.Bytes())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||
defer cleanup()
|
||||
|
||||
txBuilder, err := val.ClientCtx.TxConfig.WrapTxBuilder(signedTx)
|
||||
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedTx.Memo = "MODIFIED STD TX"
|
||||
bz, err := val.ClientCtx.JSONMarshaler.MarshalJSON(signedTx)
|
||||
txBuilder.SetMemo("MODIFIED TX")
|
||||
bz, err := val.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
s.Require().NoError(err)
|
||||
|
||||
modifiedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), string(bz))
|
||||
|
@ -147,28 +152,26 @@ func (s *IntegrationTestSuite) TestCLISignBatch() {
|
|||
defer cleanup2()
|
||||
|
||||
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID))
|
||||
s.Require().EqualError(err, "cannot parse disfix JSON wrapper: invalid character 'm' looking for beginning of value")
|
||||
s.Require().Error(err)
|
||||
|
||||
// Sign batch malformed tx file signature only.
|
||||
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only")
|
||||
s.Require().EqualError(err, "cannot parse disfix JSON wrapper: invalid character 'm' looking for beginning of value")
|
||||
s.Require().Error(err)
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
account, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account, err := val1.ClientCtx.Keyring.Key("newAccount")
|
||||
s.Require().NoError(err)
|
||||
|
||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
||||
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||
|
||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -176,19 +179,22 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
normalGeneratedStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, normalGeneratedTx.String())
|
||||
s.Require().Equal(normalGeneratedStdTx.Fee.Gas, uint64(flags.DefaultGasLimit))
|
||||
s.Require().Equal(len(normalGeneratedStdTx.Msgs), 1)
|
||||
s.Require().Equal(0, len(normalGeneratedStdTx.GetSignatures()))
|
||||
txCfg := val1.ClientCtx.TxConfig
|
||||
|
||||
normalGeneratedStdTx, err := txCfg.TxJSONDecoder()(normalGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err := txCfg.WrapTxBuilder(normalGeneratedStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(flags.DefaultGasLimit))
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures()))
|
||||
|
||||
// Test generate sendTx with --gas=$amount
|
||||
limitedGasGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -197,19 +203,28 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
limitedGasStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, limitedGasGeneratedTx.String())
|
||||
s.Require().Equal(limitedGasStdTx.Fee.Gas, uint64(100))
|
||||
s.Require().Equal(len(limitedGasStdTx.Msgs), 1)
|
||||
s.Require().Equal(0, len(limitedGasStdTx.GetSignatures()))
|
||||
limitedGasStdTx, err := txCfg.TxJSONDecoder()(limitedGasGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = txCfg.WrapTxBuilder(limitedGasStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBuilder.GetTx().GetGas(), uint64(100))
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(0, len(txBuilder.GetTx().GetSignatures()))
|
||||
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var coins sdk.Coins
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
startTokens := coins.AmountOf(s.cfg.BondDenom)
|
||||
|
||||
// Test generate sendTx, estimate gas
|
||||
finalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
account.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -218,9 +233,12 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
finalStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, finalGeneratedTx.String())
|
||||
s.Require().Equal(uint64(flags.DefaultGasLimit), finalStdTx.Fee.Gas)
|
||||
s.Require().Equal(len(finalStdTx.Msgs), 1)
|
||||
finalStdTx, err := txCfg.TxJSONDecoder()(finalGeneratedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = txCfg.WrapTxBuilder(finalStdTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint64(flags.DefaultGasLimit), txBuilder.GetTx().GetGas())
|
||||
s.Require().Equal(len(finalStdTx.GetMsgs()), 1)
|
||||
|
||||
// Write the output to disk
|
||||
unsignedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String())
|
||||
|
@ -245,11 +263,13 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
// Sign transaction
|
||||
signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
signedFinalTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, signedTx.String())
|
||||
s.Require().Equal(len(signedFinalTx.Msgs), 1)
|
||||
s.Require().Equal(1, len(signedFinalTx.GetSignatures()))
|
||||
s.Require().Equal(val1.Address.String(), signedFinalTx.GetSigners()[0].String())
|
||||
signedFinalTx, err := txCfg.TxJSONDecoder()(signedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err = val1.ClientCtx.TxConfig.WrapTxBuilder(signedFinalTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(len(txBuilder.GetTx().GetMsgs()), 1)
|
||||
s.Require().Equal(1, len(txBuilder.GetTx().GetSignatures()))
|
||||
s.Require().Equal(val1.Address.String(), txBuilder.GetTx().GetSigners()[0].String())
|
||||
|
||||
// Write the output to disk
|
||||
signedTxFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), signedTx.String())
|
||||
|
@ -261,11 +281,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
s.Require().True(strings.Contains(res.String(), "[OK]"))
|
||||
|
||||
// Ensure foo has right amount of funds
|
||||
startTokens := sdk.TokensFromConsensusPower(400)
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var coins sdk.Coins
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(startTokens, coins.AmountOf(s.cfg.BondDenom))
|
||||
|
@ -291,7 +309,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sendTokens, coins.AmountOf(s.cfg.BondDenom))
|
||||
s.Require().Equal(sendTokens.Amount, coins.AmountOf(s.cfg.BondDenom))
|
||||
|
||||
// Ensure origin account state
|
||||
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||
|
@ -299,11 +317,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
|||
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sdk.NewInt(389999990), coins.AmountOf(s.cfg.BondDenom))
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||
s.T().SkipNow() // TODO check encoding.
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
|
@ -312,14 +328,10 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
|||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
|
@ -374,7 +386,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
|||
defer cleanup3()
|
||||
|
||||
exec, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Error(err)
|
||||
|
||||
fmt.Printf("%s", exec)
|
||||
}
|
||||
|
@ -382,15 +394,13 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
|||
func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
||||
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||
|
||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
val1.Address,
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -402,7 +412,7 @@ func (s *IntegrationTestSuite) TestCLIEncode() {
|
|||
savedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String())
|
||||
defer cleanup()
|
||||
|
||||
// Enconde
|
||||
// Encode
|
||||
encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
|
@ -412,12 +422,15 @@ func (s *IntegrationTestSuite) TestCLIEncode() {
|
|||
decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64)
|
||||
s.Require().NoError(err)
|
||||
|
||||
theTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, decodedTx.String())
|
||||
s.Require().Equal("deadbeef", theTx.Memo)
|
||||
txCfg := val1.ClientCtx.TxConfig
|
||||
theTx, err := txCfg.TxJSONDecoder()(decodedTx.Bytes())
|
||||
s.Require().NoError(err)
|
||||
txBuilder, err := val1.ClientCtx.TxConfig.WrapTxBuilder(theTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("deadbeef", txBuilder.GetTx().GetMemo())
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||
s.T().SkipNow()
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
|
@ -426,25 +439,30 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
|||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
|
||||
s.Require().NoError(err)
|
||||
|
||||
var coins sdk.Coins
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
intialCoins := coins
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||
_, err = bankcli.MsgSendExec(
|
||||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
multisigInfo.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sendTokens,
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -454,13 +472,13 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
|||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
|
||||
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
|
||||
s.Require().NoError(err)
|
||||
|
||||
var coins sdk.Coins
|
||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sendTokens.Amount, coins.AmountOf(s.cfg.BondDenom))
|
||||
diff, _ := coins.SafeSub(intialCoins)
|
||||
s.Require().Equal(sendTokens.Amount, diff.AmountOf(s.cfg.BondDenom))
|
||||
|
||||
// Generate multisig transaction.
|
||||
multiGeneratedTx, err := bankcli.MsgSendExec(
|
||||
|
@ -514,7 +532,6 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
|||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||
s.T().SkipNow()
|
||||
val1 := s.network.Validators[0]
|
||||
|
||||
codec := codec2.New()
|
||||
|
@ -523,14 +540,13 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
val1.ClientCtx.Codec = codec
|
||||
|
||||
// Generate 2 accounts and a multisig.
|
||||
account1, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
||||
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
|
||||
s.Require().NoError(err)
|
||||
|
||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
||||
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Send coins from validator to multisig.
|
||||
|
@ -539,9 +555,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
val1.ClientCtx,
|
||||
val1.Address,
|
||||
multisigInfo.GetAddress(),
|
||||
sdk.NewCoins(
|
||||
sendTokens,
|
||||
),
|
||||
sdk.NewCoins(sendTokens),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
|
@ -593,8 +607,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
defer cleanup3()
|
||||
|
||||
// Does not work in offline mode.
|
||||
val1.ClientCtx.Offline = true
|
||||
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
|
||||
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name())
|
||||
s.Require().EqualError(err, "couldn't verify signature")
|
||||
|
||||
val1.ClientCtx.Offline = false
|
||||
|
@ -617,7 +630,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
|
||||
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
||||
clientCtx := client.Context{}.WithOffline(true)
|
||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
||||
clientCtx = clientCtx.WithTxConfig(simapp.MakeEncodingConfig().TxConfig)
|
||||
|
||||
cmd := authcli.GetBroadcastCommand()
|
||||
_ = testutil.ApplyMockIODiscardOutErr(cmd)
|
||||
|
@ -628,7 +641,8 @@ func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
|||
|
||||
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
||||
txCfg := simapp.MakeEncodingConfig().TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||
|
@ -639,9 +653,17 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
|||
t.Cleanup(cleanFunc)
|
||||
|
||||
// Create new file with tx
|
||||
txContents := []byte("{\"type\":\"cosmos-sdk/StdTx\",\"value\":{\"msg\":[{\"type\":\"cosmos-sdk/MsgSend\",\"value\":{\"from_address\":\"cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw\",\"to_address\":\"cosmos1wc8mpr8m3sy3ap3j7fsgqfzx36um05pystems4\",\"amount\":[{\"denom\":\"stake\",\"amount\":\"10000\"}]}}],\"fee\":{\"amount\":[],\"gas\":\"200000\"},\"signatures\":null,\"memo\":\"\"}}")
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(200000)
|
||||
from, err := sdk.AccAddressFromBech32("cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw")
|
||||
require.NoError(t, err)
|
||||
to, err := sdk.AccAddressFromBech32("cosmos1cxlt8kznps92fwu3j6npahx4mjfutydyene2qw")
|
||||
require.NoError(t, err)
|
||||
err = builder.SetMsgs(banktypes.NewMsgSend(from, to, sdk.Coins{sdk.NewInt64Coin("stake", 10000)}))
|
||||
require.NoError(t, err)
|
||||
txContents, err := txCfg.TxJSONEncoder()(builder.GetTx())
|
||||
txFileName := filepath.Join(testDir, "tx.json")
|
||||
err := ioutil.WriteFile(txFileName, txContents, 0644)
|
||||
err = ioutil.WriteFile(txFileName, txContents, 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
cmd.SetArgs([]string{txFileName})
|
||||
|
@ -654,8 +676,3 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
|||
func TestIntegrationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IntegrationTestSuite))
|
||||
}
|
||||
|
||||
func unmarshalStdTx(t require.TestingT, c codec.JSONMarshaler, s string) (stdTx authtypes.StdTx) {
|
||||
require.Nil(t, c.UnmarshalJSON([]byte(s), &stdTx))
|
||||
return stdTx
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cli
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -37,7 +38,12 @@ func GetDecodeCommand() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintOutput(tx)
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package cli
|
|||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -10,13 +11,6 @@ import (
|
|||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
)
|
||||
|
||||
// txEncodeRespStr implements a simple Stringer wrapper for a encoded tx.
|
||||
type txEncodeRespStr string
|
||||
|
||||
func (txr txEncodeRespStr) String() string {
|
||||
return string(txr)
|
||||
}
|
||||
|
||||
// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into
|
||||
// Amino-serialized bytes
|
||||
func GetEncodeCommand() *cobra.Command {
|
||||
|
@ -44,8 +38,7 @@ If you supply a dash (-) argument in place of an input filename, the command rea
|
|||
// base64 encode the encoded tx bytes
|
||||
txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes)
|
||||
|
||||
response := txEncodeRespStr(txBytesBase64)
|
||||
return clientCtx.PrintOutput(response)
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", txBytesBase64))
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,17 @@ func TestGetCommandEncode(t *testing.T) {
|
|||
authtypes.RegisterCodec(encodingConfig.Amino)
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
txCfg := encodingConfig.TxConfig
|
||||
|
||||
// Build a test transaction
|
||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
||||
JSONEncoded, err := txGen.TxJSONEncoder()(stdTx)
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(50000)
|
||||
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
builder.SetMemo("foomemo")
|
||||
jsonEncoded, err := txCfg.TxJSONEncoder()(builder.GetTx())
|
||||
require.NoError(t, err)
|
||||
|
||||
txFile, cleanup := testutil.WriteToNewTempFile(t, string(JSONEncoded))
|
||||
txFile, cleanup := testutil.WriteToNewTempFile(t, string(jsonEncoded))
|
||||
txFileName := txFile.Name()
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
|
@ -58,15 +60,17 @@ func TestGetCommandDecode(t *testing.T) {
|
|||
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txGen)
|
||||
txCfg := encodingConfig.TxConfig
|
||||
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||
|
||||
// Build a test transaction
|
||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
||||
builder := txCfg.NewTxBuilder()
|
||||
builder.SetGasLimit(50000)
|
||||
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||
builder.SetMemo("foomemo")
|
||||
|
||||
// Encode transaction
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(stdTx)
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(builder.GetTx())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Convert the transaction into base64 encoded string
|
||||
|
|
|
@ -11,13 +11,14 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
|
@ -60,13 +61,27 @@ recommended to set such parameters manually.
|
|||
func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
cdc := clientCtx.Codec
|
||||
tx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
||||
stdTx := tx.(types.StdTx)
|
||||
clientCtx, err = client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsedTx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
if txFactory.SignMode() == signingtypes.SignMode_SIGN_MODE_UNSPECIFIED {
|
||||
txFactory = txFactory.WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
}
|
||||
|
||||
txCfg := clientCtx.TxConfig
|
||||
txBuilder, err := txCfg.WrapTxBuilder(parsedTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
|
@ -85,63 +100,53 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
|||
|
||||
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
|
||||
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating tx builder from flags")
|
||||
}
|
||||
|
||||
if !clientCtx.Offline {
|
||||
accnum, seq, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBldr = txBldr.WithAccountNumber(accnum).WithSequence(seq)
|
||||
txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq)
|
||||
}
|
||||
|
||||
// read each signature and add it to the multisig if valid
|
||||
for i := 2; i < len(args); i++ {
|
||||
stdSig, err := readAndUnmarshalStdSignature(cdc, args[i])
|
||||
sigs, err := unmarshalSignatureJSON(clientCtx, args[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate each signature
|
||||
sigBytes := types.StdSignBytes(
|
||||
txBldr.ChainID(), txBldr.AccountNumber(), txBldr.Sequence(),
|
||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
if ok := stdSig.GetPubKey().VerifyBytes(sigBytes, stdSig.Signature); !ok {
|
||||
return fmt.Errorf("couldn't verify signature")
|
||||
signingData := signing.SignerData{
|
||||
ChainID: txFactory.ChainID(),
|
||||
AccountNumber: txFactory.AccountNumber(),
|
||||
AccountSequence: txFactory.Sequence(),
|
||||
}
|
||||
|
||||
sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, sig := range sigs {
|
||||
err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't verify signature")
|
||||
}
|
||||
|
||||
if err := multisig.AddSignatureV2(multisigSig, sigV2, multisigPub.PubKeys); err != nil {
|
||||
return err
|
||||
if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.PubKeys); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sigBz, err := types.SignatureDataToAminoSignature(cdc, multisigSig)
|
||||
sigV2 := signingtypes.SignatureV2{
|
||||
PubKey: multisigPub,
|
||||
Data: multisigSig,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newStdSig := types.StdSignature{Signature: sigBz, PubKey: multisigPub.Bytes()} //nolint:staticcheck
|
||||
newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo()) //nolint:staticcheck
|
||||
|
||||
var json []byte
|
||||
|
||||
sigOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
if sigOnly {
|
||||
json, err = cdc.MarshalJSON(newTx.Signatures[0])
|
||||
} else {
|
||||
json, err = cdc.MarshalJSON(newTx)
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, sigOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -158,18 +163,14 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
defer fp.Close()
|
||||
|
||||
fmt.Fprintf(fp, "%s\n", json)
|
||||
return
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
}
|
||||
|
||||
func readAndUnmarshalStdSignature(cdc *codec.Codec, filename string) (stdSig types.StdSignature, err error) { //nolint:staticcheck
|
||||
func unmarshalSignatureJSON(clientCtx client.Context, filename string) (sigs []signingtypes.SignatureV2, err error) {
|
||||
var bytes []byte
|
||||
if bytes, err = ioutil.ReadFile(filename); err != nil {
|
||||
return
|
||||
}
|
||||
if err = cdc.UnmarshalJSON(bytes, &stdSig); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
return clientCtx.TxConfig.UnmarshalSignatureJSON(bytes)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
|
@ -9,10 +8,10 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -61,12 +60,13 @@ account key. It implies --signature-only.
|
|||
func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
|
||||
txBldr, err := types.NewTxBuilderFromFlags(bufio.NewReader(cmd.InOrStdin()), cmd.Flags(), clientCtx.HomeDir)
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
txCfg := clientCtx.TxConfig
|
||||
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
|
||||
var (
|
||||
|
@ -97,34 +97,34 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
scanner := authclient.NewBatchScanner(txCfg, infile)
|
||||
|
||||
scanner := authclient.NewBatchScanner(clientCtx.JSONMarshaler, infile)
|
||||
|
||||
for sequence := txBldr.Sequence(); scanner.Scan(); sequence++ {
|
||||
var stdTx types.StdTx
|
||||
|
||||
unsignedStdTx := scanner.StdTx()
|
||||
txBldr = txBldr.WithSequence(sequence)
|
||||
|
||||
for sequence := txFactory.Sequence(); scanner.Scan(); sequence++ {
|
||||
unsignedStdTx := scanner.Tx()
|
||||
txFactory = txFactory.WithSequence(sequence)
|
||||
txBuilder, err := txCfg.WrapTxBuilder(unsignedStdTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if multisigAddr.Empty() {
|
||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
||||
_, fromName, err := client.GetFromFields(txBldr.Keybase(), from, clientCtx.GenerateOnly)
|
||||
_, fromName, err := client.GetFromFields(txFactory.Keybase(), from, clientCtx.GenerateOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
|
||||
stdTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, unsignedStdTx, false, true)
|
||||
err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
stdTx, err = authclient.SignStdTxWithSignerAddress(txBldr, clientCtx, multisigAddr, clientCtx.GetFromName(), unsignedStdTx, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = authclient.SignTxWithSignerAddress(txFactory, clientCtx, multisigAddr, clientCtx.GetFromName(), txBuilder, true)
|
||||
}
|
||||
|
||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, stdTx, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -206,20 +206,31 @@ func preSignCmd(cmd *cobra.Command, _ []string) {
|
|||
func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
|
||||
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
clientCtx, txF, newTx, err := readTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if txF.SignMode() == signing.SignMode_SIGN_MODE_UNSPECIFIED {
|
||||
txF = txF.WithSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
}
|
||||
txCfg := clientCtx.TxConfig
|
||||
txBuilder, err := txCfg.WrapTxBuilder(newTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdTx := tx.(types.StdTx)
|
||||
|
||||
// if --signature-only is on, then override --append
|
||||
var newTx types.StdTx
|
||||
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||
multisigAddrStr, _ := cmd.Flags().GetString(flagMultisig)
|
||||
|
||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
||||
_, fromName, err := client.GetFromFields(txBldr.Keybase(), from, clientCtx.GenerateOnly)
|
||||
_, fromName, err := client.GetFromFields(txFactory.Keybase(), from, clientCtx.GenerateOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||
}
|
||||
|
@ -232,23 +243,22 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
newTx, err = authclient.SignStdTxWithSignerAddress(
|
||||
txBldr, clientCtx, multisigAddr, fromName, stdTx, clientCtx.Offline,
|
||||
err = authclient.SignTxWithSignerAddress(
|
||||
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline,
|
||||
)
|
||||
generateSignatureOnly = true
|
||||
} else {
|
||||
append, _ := cmd.Flags().GetBool(flagAppend)
|
||||
appendSig := append && !generateSignatureOnly
|
||||
newTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, stdTx, appendSig, clientCtx.Offline)
|
||||
if err != nil {
|
||||
return err
|
||||
flagAppend, _ := cmd.Flags().GetBool(flagAppend)
|
||||
appendSig := flagAppend && !generateSignatureOnly
|
||||
if appendSig {
|
||||
err = authclient.SignTx(txF, clientCtx, clientCtx.GetFromName(), txBuilder, clientCtx.Offline)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, newTx, generateSignatureOnly)
|
||||
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -265,15 +275,20 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
defer fp.Close()
|
||||
|
||||
fmt.Fprintf(fp, "%s\n", json)
|
||||
return nil
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
}
|
||||
|
||||
func getSignatureJSON(cdc codec.JSONMarshaler, newTx types.StdTx, generateSignatureOnly bool) ([]byte, error) {
|
||||
func marshalSignatureJSON(txConfig client.TxConfig, txBldr client.TxBuilder, generateSignatureOnly bool) ([]byte, error) {
|
||||
parsedTx := txBldr.GetTx()
|
||||
|
||||
if generateSignatureOnly {
|
||||
return cdc.MarshalJSON(newTx.Signatures[0])
|
||||
sigs, err := parsedTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return txConfig.MarshalSignatureJSON(sigs)
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(newTx)
|
||||
return txConfig.TxJSONEncoder()(parsedTx)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
func GetValidateSignaturesCommand() *cobra.Command {
|
||||
|
@ -41,11 +39,15 @@ transaction will be not be performed as that will require RPC communication with
|
|||
func makeValidateSignaturesCmd() func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx, txBldr, stdTx, err := readTxAndInitContexts(clientCtx, cmd, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdTx := tx.(types.StdTx)
|
||||
|
||||
if !printAndValidateSigs(cmd, clientCtx, txBldr.ChainID(), stdTx, clientCtx.Offline) {
|
||||
return fmt.Errorf("signatures validation failed")
|
||||
|
@ -59,17 +61,22 @@ func makeValidateSignaturesCmd() func(cmd *cobra.Command, args []string) error {
|
|||
// expected signers. In addition, if offline has not been supplied, the signature is
|
||||
// verified over the transaction sign bytes. Returns false if the validation fails.
|
||||
func printAndValidateSigs(
|
||||
cmd *cobra.Command, clientCtx client.Context, chainID string, stdTx types.StdTx, offline bool,
|
||||
cmd *cobra.Command, clientCtx client.Context, chainID string, tx sdk.Tx, offline bool,
|
||||
) bool {
|
||||
cmd.Println("Signers:")
|
||||
signers := stdTx.GetSigners()
|
||||
sigTx := tx.(authsigning.SigVerifiableTx)
|
||||
signModeHandler := clientCtx.TxConfig.SignModeHandler()
|
||||
|
||||
cmd.Println("Signers:")
|
||||
signers := sigTx.GetSigners()
|
||||
for i, signer := range signers {
|
||||
cmd.Printf(" %v: %v\n", i, signer.String())
|
||||
}
|
||||
|
||||
success := true
|
||||
sigs := stdTx.Signatures
|
||||
sigs, err := sigTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cmd.Println("")
|
||||
cmd.Println("Signatures:")
|
||||
|
||||
|
@ -79,9 +86,10 @@ func printAndValidateSigs(
|
|||
|
||||
for i, sig := range sigs {
|
||||
var (
|
||||
pubKey = sig.PubKey
|
||||
multiSigHeader string
|
||||
multiSigMsg string
|
||||
sigAddr = sdk.AccAddress(sig.GetPubKey().Address())
|
||||
sigAddr = sdk.AccAddress(pubKey.Address())
|
||||
sigSanity = "OK"
|
||||
)
|
||||
|
||||
|
@ -93,40 +101,21 @@ func printAndValidateSigs(
|
|||
// Validate the actual signature over the transaction bytes since we can
|
||||
// reach out to a full node to query accounts.
|
||||
if !offline && success {
|
||||
acc, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccount(clientCtx, sigAddr)
|
||||
accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, sigAddr)
|
||||
if err != nil {
|
||||
cmd.Printf("failed to get account: %s\n", sigAddr)
|
||||
return false
|
||||
}
|
||||
|
||||
sigBytes := types.StdSignBytes(
|
||||
chainID, acc.GetAccountNumber(), acc.GetSequence(),
|
||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
||||
)
|
||||
|
||||
if ok := sig.GetPubKey().VerifyBytes(sigBytes, sig.Signature); !ok {
|
||||
sigSanity = "ERROR: signature invalid"
|
||||
success = false
|
||||
signingData := authsigning.SignerData{
|
||||
ChainID: chainID,
|
||||
AccountNumber: accNum,
|
||||
AccountSequence: accSeq,
|
||||
}
|
||||
}
|
||||
|
||||
multiPK, ok := sig.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||
if ok {
|
||||
var multiSig multisig.AminoMultisignature
|
||||
clientCtx.Codec.MustUnmarshalBinaryBare(sig.Signature, &multiSig)
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString("\n MultiSig Signatures:\n")
|
||||
|
||||
for i := 0; i < multiSig.BitArray.Count(); i++ {
|
||||
if multiSig.BitArray.GetIndex(i) {
|
||||
addr := sdk.AccAddress(multiPK.PubKeys[i].Address().Bytes())
|
||||
b.WriteString(fmt.Sprintf(" %d: %s (weight: %d)\n", i, addr, 1))
|
||||
}
|
||||
err = authsigning.VerifySignature(pubKey, signingData, sig.Data, signModeHandler, sigTx)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
multiSigHeader = fmt.Sprintf(" [multisig threshold: %d/%d]", multiPK.K, len(multiPK.PubKeys))
|
||||
multiSigMsg = b.String()
|
||||
}
|
||||
|
||||
cmd.Printf(" %d: %s\t\t\t[%s]%s%s\n", i, sigAddr.String(), sigSanity, multiSigHeader, multiSigMsg)
|
||||
|
@ -137,21 +126,13 @@ func printAndValidateSigs(
|
|||
return success
|
||||
}
|
||||
|
||||
func readStdTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (
|
||||
client.Context, types.TxBuilder, sdk.Tx, error,
|
||||
) {
|
||||
func readTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (client.Context, tx.Factory, sdk.Tx, error) {
|
||||
stdTx, err := authclient.ReadTxFromFile(clientCtx, filename)
|
||||
if err != nil {
|
||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
||||
return clientCtx, tx.Factory{}, nil, err
|
||||
}
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
clientCtx = clientCtx.WithInput(inBuf)
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
|
||||
if err != nil {
|
||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
||||
}
|
||||
|
||||
return clientCtx, txBldr, stdTx, nil
|
||||
return clientCtx, txFactory, stdTx, nil
|
||||
}
|
||||
|
|
|
@ -10,10 +10,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
@ -38,81 +37,6 @@ func (gr GasEstimateResponse) String() string {
|
|||
return fmt.Sprintf("gas estimate: %d", gr.GasEstimate)
|
||||
}
|
||||
|
||||
// GenerateOrBroadcastMsgs creates a StdTx given a series of messages. If
|
||||
// the provided context has generate-only enabled, the tx will only be printed
|
||||
// to STDOUT in a fully offline manner. Otherwise, the tx will be signed and
|
||||
// broadcasted.
|
||||
func GenerateOrBroadcastMsgs(clientCtx client.Context, txBldr authtypes.TxBuilder, msgs []sdk.Msg) error {
|
||||
if clientCtx.GenerateOnly {
|
||||
return PrintUnsignedStdTx(txBldr, clientCtx, msgs)
|
||||
}
|
||||
|
||||
return CompleteAndBroadcastTxCLI(txBldr, clientCtx, msgs)
|
||||
}
|
||||
|
||||
// CompleteAndBroadcastTxCLI implements a utility function that facilitates
|
||||
// sending a series of messages in a signed transaction given a TxBuilder and a
|
||||
// QueryContext. It ensures that the account exists, has a proper number and
|
||||
// sequence set. In addition, it builds and signs a transaction with the
|
||||
// supplied messages. Finally, it broadcasts the signed transaction to a node.
|
||||
func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
txBldr, err := PrepareTxBuilder(txBldr, clientCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromName := clientCtx.GetFromName()
|
||||
|
||||
if txBldr.SimulateAndExecute() || clientCtx.Simulate {
|
||||
txBldr, err = EnrichWithGas(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gasEst := GasEstimateResponse{GasEstimate: txBldr.Gas()}
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n", gasEst.String())
|
||||
}
|
||||
|
||||
if clientCtx.Simulate {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !clientCtx.SkipConfirm {
|
||||
stdSignMsg, err := txBldr.BuildSignMsg(msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdSignMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json)
|
||||
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr)
|
||||
if err != nil || !ok {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// build and sign the transaction
|
||||
txBytes, err := txBldr.BuildAndSign(fromName, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// broadcast to a Tendermint node
|
||||
res, err := clientCtx.BroadcastTx(txBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintOutput(res)
|
||||
}
|
||||
|
||||
// EnrichWithGas calculates the gas estimate that would be consumed by the
|
||||
// transaction and set the transaction's respective value accordingly.
|
||||
func EnrichWithGas(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) (authtypes.TxBuilder, error) {
|
||||
|
@ -148,74 +72,52 @@ func CalculateGas(
|
|||
}
|
||||
|
||||
// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
|
||||
func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
stdTx, err := buildUnsignedStdTxOffline(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(clientCtx.Output, "%s\n", json)
|
||||
return nil
|
||||
func PrintUnsignedStdTx(txBldr tx.Factory, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||
err := tx.GenerateOrBroadcastTxWithFactory(clientCtx, txBldr, msgs...)
|
||||
return err
|
||||
}
|
||||
|
||||
// SignStdTx appends a signature to a StdTx and returns a copy of it. If appendSig
|
||||
// SignTx appends a signature to a transaction. If appendSig
|
||||
// is false, it replaces the signatures already attached with the new signature.
|
||||
// Don't perform online validation or lookups if offline is true.
|
||||
func SignStdTx(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context, name string,
|
||||
stdTx authtypes.StdTx, appendSig bool, offline bool,
|
||||
) (authtypes.StdTx, error) {
|
||||
|
||||
var signedStdTx authtypes.StdTx
|
||||
|
||||
info, err := txBldr.Keybase().Key(name)
|
||||
func SignTx(txFactory tx.Factory, clientCtx client.Context, name string, stdTx client.TxBuilder, offline bool) error {
|
||||
info, err := txFactory.Keybase().Key(name)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
|
||||
addr := info.GetPubKey().Address()
|
||||
|
||||
// check whether the address is a signer
|
||||
if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) {
|
||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
addr := sdk.AccAddress(info.GetPubKey().Address())
|
||||
if !isTxSigner(addr, stdTx.GetTx().GetSigners()) {
|
||||
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
}
|
||||
|
||||
if !offline {
|
||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, sdk.AccAddress(addr))
|
||||
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr.SignStdTx(name, stdTx, appendSig)
|
||||
return tx.Sign(txFactory, name, stdTx)
|
||||
}
|
||||
|
||||
// SignStdTxWithSignerAddress attaches a signature to a StdTx and returns a copy of a it.
|
||||
// SignTxWithSignerAddress attaches a signature to a transaction.
|
||||
// Don't perform online validation or lookups if offline is true, else
|
||||
// populate account and sequence numbers from a foreign account.
|
||||
func SignStdTxWithSignerAddress(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context,
|
||||
addr sdk.AccAddress, name string, stdTx authtypes.StdTx, offline bool,
|
||||
) (signedStdTx authtypes.StdTx, err error) {
|
||||
func SignTxWithSignerAddress(txFactory tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||
name string, txBuilder client.TxBuilder, offline bool) (err error) {
|
||||
|
||||
// check whether the address is a signer
|
||||
if !isTxSigner(addr, stdTx.GetSigners()) {
|
||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
|
||||
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||
}
|
||||
|
||||
if !offline {
|
||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, addr)
|
||||
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||
if err != nil {
|
||||
return signedStdTx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr.SignStdTx(name, stdTx, false)
|
||||
return tx.Sign(txFactory, name, txBuilder)
|
||||
}
|
||||
|
||||
// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin.
|
||||
|
@ -236,21 +138,21 @@ func ReadTxFromFile(ctx client.Context, filename string) (tx sdk.Tx, err error)
|
|||
}
|
||||
|
||||
// NewBatchScanner returns a new BatchScanner to read newline-delimited StdTx transactions from r.
|
||||
func NewBatchScanner(cdc codec.JSONMarshaler, r io.Reader) *BatchScanner {
|
||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cdc: cdc}
|
||||
func NewBatchScanner(cfg client.TxConfig, r io.Reader) *BatchScanner {
|
||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cfg: cfg}
|
||||
}
|
||||
|
||||
// BatchScanner provides a convenient interface for reading batch data such as a file
|
||||
// of newline-delimited JSON encoded StdTx.
|
||||
type BatchScanner struct {
|
||||
*bufio.Scanner
|
||||
stdTx authtypes.StdTx
|
||||
cdc codec.JSONMarshaler
|
||||
theTx sdk.Tx
|
||||
cfg client.TxConfig
|
||||
unmarshalErr error
|
||||
}
|
||||
|
||||
// StdTx returns the most recent StdTx unmarshalled by a call to Scan.
|
||||
func (bs BatchScanner) StdTx() authtypes.StdTx { return bs.stdTx }
|
||||
// Tx returns the most recent Tx unmarshalled by a call to Scan.
|
||||
func (bs BatchScanner) Tx() sdk.Tx { return bs.theTx }
|
||||
|
||||
// UnmarshalErr returns the first unmarshalling error that was encountered by the scanner.
|
||||
func (bs BatchScanner) UnmarshalErr() error { return bs.unmarshalErr }
|
||||
|
@ -261,7 +163,9 @@ func (bs *BatchScanner) Scan() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if err := bs.cdc.UnmarshalJSON(bs.Bytes(), &bs.stdTx); err != nil && bs.unmarshalErr == nil {
|
||||
tx, err := bs.cfg.TxJSONDecoder()(bs.Bytes())
|
||||
bs.theTx = tx
|
||||
if err != nil && bs.unmarshalErr == nil {
|
||||
bs.unmarshalErr = err
|
||||
return false
|
||||
}
|
||||
|
@ -270,8 +174,8 @@ func (bs *BatchScanner) Scan() bool {
|
|||
}
|
||||
|
||||
func populateAccountFromState(
|
||||
txBldr authtypes.TxBuilder, clientCtx client.Context, addr sdk.AccAddress,
|
||||
) (authtypes.TxBuilder, error) {
|
||||
txBldr tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||
) (tx.Factory, error) {
|
||||
|
||||
num, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
|
||||
if err != nil {
|
||||
|
@ -316,56 +220,6 @@ func parseQueryResponse(bz []byte) (sdk.SimulationResponse, error) {
|
|||
return simRes, nil
|
||||
}
|
||||
|
||||
// PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx.
|
||||
func PrepareTxBuilder(txBldr authtypes.TxBuilder, clientCtx client.Context) (authtypes.TxBuilder, error) {
|
||||
from := clientCtx.GetFromAddress()
|
||||
accGetter := clientCtx.AccountRetriever
|
||||
if err := accGetter.EnsureExists(clientCtx, from); err != nil {
|
||||
return txBldr, err
|
||||
}
|
||||
|
||||
txbldrAccNum, txbldrAccSeq := txBldr.AccountNumber(), txBldr.Sequence()
|
||||
// TODO: (ref #1903) Allow for user supplied account number without
|
||||
// automatically doing a manual lookup.
|
||||
if txbldrAccNum == 0 || txbldrAccSeq == 0 {
|
||||
num, seq, err := accGetter.GetAccountNumberSequence(clientCtx, from)
|
||||
if err != nil {
|
||||
return txBldr, err
|
||||
}
|
||||
|
||||
if txbldrAccNum == 0 {
|
||||
txBldr = txBldr.WithAccountNumber(num)
|
||||
}
|
||||
if txbldrAccSeq == 0 {
|
||||
txBldr = txBldr.WithSequence(seq)
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr, nil
|
||||
}
|
||||
|
||||
func buildUnsignedStdTxOffline(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) (stdTx authtypes.StdTx, err error) {
|
||||
if txBldr.SimulateAndExecute() {
|
||||
if clientCtx.Offline {
|
||||
return stdTx, errors.New("cannot estimate gas in offline mode")
|
||||
}
|
||||
|
||||
txBldr, err = EnrichWithGas(txBldr, clientCtx, msgs)
|
||||
if err != nil {
|
||||
return stdTx, err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas())
|
||||
}
|
||||
|
||||
stdSignMsg, err := txBldr.BuildSignMsg(msgs)
|
||||
if err != nil {
|
||||
return stdTx, err
|
||||
}
|
||||
|
||||
return authtypes.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil
|
||||
}
|
||||
|
||||
func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
|
||||
for _, s := range signers {
|
||||
if bytes.Equal(user.Bytes(), s.Bytes()) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
|
@ -149,8 +150,12 @@ func TestReadStdTxFromFile(t *testing.T) {
|
|||
|
||||
func TestBatchScanner_Scan(t *testing.T) {
|
||||
t.Parallel()
|
||||
cdc := codec.New()
|
||||
sdk.RegisterCodec(cdc)
|
||||
encodingConfig := simappparams.MakeEncodingConfig()
|
||||
std.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.WithTxConfig(txGen)
|
||||
|
||||
batch1 := `{"msg":[],"fee":{"amount":[{"denom":"atom","amount":"150"}],"gas":"50000"},"signatures":[],"memo":"foomemo"}
|
||||
{"msg":[],"fee":{"amount":[{"denom":"atom","amount":"150"}],"gas":"10000"},"signatures":[],"memo":"foomemo"}
|
||||
|
@ -182,12 +187,12 @@ malformed
|
|||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
scanner, i := NewBatchScanner(cdc, strings.NewReader(tt.batch)), 0
|
||||
scanner, i := NewBatchScanner(clientCtx.TxConfig, strings.NewReader(tt.batch)), 0
|
||||
for scanner.Scan() {
|
||||
_ = scanner.StdTx()
|
||||
_ = scanner.Tx()
|
||||
i++
|
||||
}
|
||||
|
||||
t.Log(scanner.theTx)
|
||||
require.Equal(t, tt.wantScannerError, scanner.Err() != nil)
|
||||
require.Equal(t, tt.wantUnmarshalError, scanner.UnmarshalErr() != nil)
|
||||
require.Equal(t, tt.numTxs, i)
|
||||
|
@ -206,48 +211,6 @@ func compareEncoders(t *testing.T, expected sdk.TxEncoder, actual sdk.TxEncoder)
|
|||
require.Equal(t, defaultEncoderBytes, encoderBytes)
|
||||
}
|
||||
|
||||
func TestPrepareTxBuilder(t *testing.T) {
|
||||
cdc := makeCodec()
|
||||
|
||||
encodingConfig := simappparams.MakeEncodingConfig()
|
||||
sdk.RegisterCodec(encodingConfig.Amino)
|
||||
|
||||
fromAddr := sdk.AccAddress("test-addr0000000000")
|
||||
fromAddrStr := fromAddr.String()
|
||||
|
||||
var accNum uint64 = 10
|
||||
var accSeq uint64 = 17
|
||||
|
||||
txGen := encodingConfig.TxConfig
|
||||
clientCtx := client.Context{}
|
||||
clientCtx = clientCtx.
|
||||
WithTxConfig(txGen).
|
||||
WithJSONMarshaler(encodingConfig.Marshaler).
|
||||
WithAccountRetriever(client.TestAccountRetriever{Accounts: map[string]struct {
|
||||
Address sdk.AccAddress
|
||||
Num uint64
|
||||
Seq uint64
|
||||
}{
|
||||
fromAddrStr: {
|
||||
Address: fromAddr,
|
||||
Num: accNum,
|
||||
Seq: accSeq,
|
||||
},
|
||||
}}).
|
||||
WithFromAddress(fromAddr)
|
||||
|
||||
bldr := authtypes.NewTxBuilder(
|
||||
authtypes.DefaultTxEncoder(cdc), 0, 0,
|
||||
200000, 1.1, false, "test-chain",
|
||||
"test-builder", sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))),
|
||||
sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDecWithPrec(10000, sdk.Precision))})
|
||||
|
||||
bldr, err := PrepareTxBuilder(bldr, clientCtx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accNum, bldr.AccountNumber())
|
||||
require.Equal(t, accSeq, bldr.Sequence())
|
||||
}
|
||||
|
||||
func makeCodec() *codec.Codec {
|
||||
var cdc = codec.New()
|
||||
sdk.RegisterCodec(cdc)
|
||||
|
|
|
@ -3,8 +3,9 @@ package tx
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
|
@ -17,17 +18,19 @@ type generator struct {
|
|||
encoder sdk.TxEncoder
|
||||
jsonDecoder sdk.TxDecoder
|
||||
jsonEncoder sdk.TxEncoder
|
||||
protoCodec *codec.ProtoCodec
|
||||
}
|
||||
|
||||
// NewTxConfig returns a new protobuf TxConfig using the provided Marshaler, PublicKeyCodec and SignModeHandler.
|
||||
func NewTxConfig(anyUnpacker codectypes.AnyUnpacker, pubkeyCodec types.PublicKeyCodec, signModeHandler signing.SignModeHandler) client.TxConfig {
|
||||
// NewTxConfig returns a new protobuf TxConfig using the provided ProtoCodec, PublicKeyCodec and SignModeHandler.
|
||||
func NewTxConfig(protoCodec *codec.ProtoCodec, pubkeyCodec types.PublicKeyCodec, signModeHandler signing.SignModeHandler) client.TxConfig {
|
||||
return &generator{
|
||||
pubkeyCodec: pubkeyCodec,
|
||||
handler: signModeHandler,
|
||||
decoder: DefaultTxDecoder(anyUnpacker, pubkeyCodec),
|
||||
decoder: DefaultTxDecoder(protoCodec, pubkeyCodec),
|
||||
encoder: DefaultTxEncoder(),
|
||||
jsonDecoder: DefaultJSONTxDecoder(anyUnpacker, pubkeyCodec),
|
||||
jsonDecoder: DefaultJSONTxDecoder(protoCodec, pubkeyCodec),
|
||||
jsonEncoder: DefaultJSONTxEncoder(),
|
||||
protoCodec: protoCodec,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ package tx
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
|
@ -102,3 +104,50 @@ func decodeMultisignatures(bz []byte) ([][]byte, error) {
|
|||
}
|
||||
return multisig.Signatures, nil
|
||||
}
|
||||
|
||||
func (g generator) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error) {
|
||||
descs := make([]*signing.SignatureDescriptor, len(sigs))
|
||||
|
||||
for i, sig := range sigs {
|
||||
publicKey, err := g.pubkeyCodec.Encode(sig.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
descData := signing.SignatureDataToProto(sig.Data)
|
||||
|
||||
descs[i] = &signing.SignatureDescriptor{
|
||||
PublicKey: publicKey,
|
||||
Data: descData,
|
||||
}
|
||||
}
|
||||
|
||||
toJSON := &signing.SignatureDescriptors{Signatures: descs}
|
||||
|
||||
return codec.ProtoMarshalJSON(toJSON)
|
||||
}
|
||||
|
||||
func (g generator) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, error) {
|
||||
var sigDescs signing.SignatureDescriptors
|
||||
err := g.protoCodec.UnmarshalJSON(bz, &sigDescs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigs := make([]signing.SignatureV2, len(sigDescs.Signatures))
|
||||
for i, desc := range sigDescs.Signatures {
|
||||
pubKey, err := g.pubkeyCodec.Decode(desc.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := signing.SignatureDataFromProto(desc.Data)
|
||||
|
||||
sigs[i] = signing.SignatureV2{
|
||||
PubKey: pubKey,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
return sigs, nil
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/legacy"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
|
@ -46,29 +45,12 @@ func (s *StdTxBuilder) SetSignatures(signatures ...signing.SignatureV2) error {
|
|||
sigs := make([]StdSignature, len(signatures))
|
||||
|
||||
for i, sig := range signatures {
|
||||
var pubKeyBz []byte
|
||||
|
||||
pubKey := sig.PubKey
|
||||
if pubKey != nil {
|
||||
pubKeyBz = pubKey.Bytes()
|
||||
stdSig, err := SignatureV2ToStdSignature(s.cdc, sig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
sigBz []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if sig.Data != nil {
|
||||
sigBz, err = SignatureDataToAminoSignature(legacy.Cdc, sig.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
sigs[i] = StdSignature{
|
||||
PubKey: pubKeyBz,
|
||||
Signature: sigBz,
|
||||
}
|
||||
sigs[i] = stdSig
|
||||
}
|
||||
|
||||
s.Signatures = sigs
|
||||
|
@ -131,6 +113,38 @@ func (s StdTxConfig) TxJSONDecoder() sdk.TxDecoder {
|
|||
return DefaultJSONTxDecoder(s.Cdc)
|
||||
}
|
||||
|
||||
func (s StdTxConfig) MarshalSignatureJSON(sigs []signing.SignatureV2) ([]byte, error) {
|
||||
stdSigs := make([]StdSignature, len(sigs))
|
||||
for i, sig := range sigs {
|
||||
stdSig, err := SignatureV2ToStdSignature(s.Cdc, sig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stdSigs[i] = stdSig
|
||||
}
|
||||
return s.Cdc.MarshalJSON(stdSigs)
|
||||
}
|
||||
|
||||
func (s StdTxConfig) UnmarshalSignatureJSON(bz []byte) ([]signing.SignatureV2, error) {
|
||||
var stdSigs []StdSignature
|
||||
err := s.Cdc.UnmarshalJSON(bz, &stdSigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigs := make([]signing.SignatureV2, len(stdSigs))
|
||||
for i, stdSig := range stdSigs {
|
||||
sig, err := StdSignatureToSignatureV2(s.Cdc, stdSig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sigs[i] = sig
|
||||
}
|
||||
|
||||
return sigs, nil
|
||||
}
|
||||
|
||||
func (s StdTxConfig) SignModeHandler() authsigning.SignModeHandler {
|
||||
return LegacyAminoJSONHandler{}
|
||||
}
|
||||
|
|
|
@ -395,6 +395,33 @@ func StdSignatureToSignatureV2(cdc *codec.Codec, sig StdSignature) (signing.Sign
|
|||
}, nil
|
||||
}
|
||||
|
||||
// SignatureV2ToStdSignature converts a SignatureV2 to a StdSignature
|
||||
func SignatureV2ToStdSignature(cdc *codec.Codec, sig signing.SignatureV2) (StdSignature, error) {
|
||||
var pubKeyBz []byte
|
||||
|
||||
pubKey := sig.PubKey
|
||||
if pubKey != nil {
|
||||
pubKeyBz = pubKey.Bytes()
|
||||
}
|
||||
|
||||
var (
|
||||
sigBz []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if sig.Data != nil {
|
||||
sigBz, err = SignatureDataToAminoSignature(cdc, sig.Data)
|
||||
if err != nil {
|
||||
return StdSignature{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return StdSignature{
|
||||
PubKey: pubKeyBz,
|
||||
Signature: sigBz,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func pubKeySigToSigData(cdc *codec.Codec, key crypto.PubKey, sig []byte) (signing.SignatureData, error) {
|
||||
multiPK, ok := key.(multisig.PubKey)
|
||||
if !ok {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
@ -133,16 +134,17 @@ $ %s gentx my-key-name --home=/path/to/home/dir --keyring-backend=os --chain-id=
|
|||
return errors.Wrap(err, "failed to validate account in genesis")
|
||||
}
|
||||
|
||||
txBldr, err := authtypes.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
|
||||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating tx builder")
|
||||
}
|
||||
|
||||
txBldr = txBldr.WithTxEncoder(authclient.GetTxEncoder(clientCtx.Codec))
|
||||
txGen := clientCtx.TxConfig
|
||||
txBuilder := txGen.NewTxBuilder()
|
||||
clientCtx = clientCtx.WithInput(inBuf).WithFromAddress(key.GetAddress())
|
||||
|
||||
// create a 'create-validator' message
|
||||
txBldr, msg, err := cli.BuildCreateValidatorMsg(clientCtx, createValCfg, txBldr, true)
|
||||
txBldr, msg, err := cli.BuildCreateValidatorMsg(clientCtx, createValCfg, txFactory, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build create-validator message")
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ $ %s gentx my-key-name --home=/path/to/home/dir --keyring-backend=os --chain-id=
|
|||
}
|
||||
|
||||
// sign the transaction and write it to the output file
|
||||
signedTx, err := authclient.SignStdTx(txBldr, clientCtx, name, stdTx, false, true)
|
||||
err = authclient.SignTx(txFactory, clientCtx, name, txBuilder, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to sign std tx")
|
||||
}
|
||||
|
@ -180,7 +182,7 @@ $ %s gentx my-key-name --home=/path/to/home/dir --keyring-backend=os --chain-id=
|
|||
}
|
||||
}
|
||||
|
||||
if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil {
|
||||
if err := writeSignedGenTx(cdc, outputDocument, stdTx); err != nil {
|
||||
return errors.Wrap(err, "failed to write signed gen tx")
|
||||
}
|
||||
|
||||
|
@ -219,7 +221,7 @@ func readUnsignedGenTxFile(cdc codec.JSONMarshaler, r io.Reader) (authtypes.StdT
|
|||
return stdTx, err
|
||||
}
|
||||
|
||||
func writeSignedGenTx(cdc codec.JSONMarshaler, outputDocument string, tx authtypes.StdTx) error {
|
||||
func writeSignedGenTx(cdc codec.JSONMarshaler, outputDocument string, tx sdk.Tx) error {
|
||||
outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -109,6 +109,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
false, &sdk.TxResponse{}, 0,
|
||||
|
@ -122,6 +123,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() {
|
|||
fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)).String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||
},
|
||||
false, &sdk.TxResponse{}, 0,
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
|
@ -503,7 +502,7 @@ func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, c
|
|||
}
|
||||
|
||||
// BuildCreateValidatorMsg makes a new MsgCreateValidator.
|
||||
func BuildCreateValidatorMsg(clientCtx client.Context, config TxCreateValidatorConfig, txBldr authtypes.TxBuilder, generateOnly bool) (authtypes.TxBuilder, sdk.Msg, error) {
|
||||
func BuildCreateValidatorMsg(clientCtx client.Context, config TxCreateValidatorConfig, txBldr tx.Factory, generateOnly bool) (tx.Factory, sdk.Msg, error) {
|
||||
amounstStr := config.Amount
|
||||
amount, err := sdk.ParseCoin(amounstStr)
|
||||
|
||||
|
|
Loading…
Reference in New Issue