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
|
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
|
// 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
|
// 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.
|
// 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
|
f.simulateAndExecute = sim
|
||||||
return f
|
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 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
|
// BroadcastTx attempts to generate, sign and broadcast a transaction with the
|
||||||
|
|
|
@ -17,6 +17,8 @@ type (
|
||||||
TxDecoder() sdk.TxDecoder
|
TxDecoder() sdk.TxDecoder
|
||||||
TxJSONEncoder() sdk.TxEncoder
|
TxJSONEncoder() sdk.TxEncoder
|
||||||
TxJSONDecoder() sdk.TxDecoder
|
TxJSONDecoder() sdk.TxDecoder
|
||||||
|
MarshalSignatureJSON([]signingtypes.SignatureV2) ([]byte, error)
|
||||||
|
UnmarshalSignatureJSON([]byte) ([]signingtypes.SignatureV2, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxConfig defines an interface a client can utilize to generate an
|
// TxConfig defines an interface a client can utilize to generate an
|
||||||
|
|
|
@ -16,7 +16,9 @@ type ProtoCodec struct {
|
||||||
anyUnpacker types.AnyUnpacker
|
anyUnpacker types.AnyUnpacker
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProtoCodec(anyUnpacker types.AnyUnpacker) Marshaler {
|
var _ Marshaler = &ProtoCodec{}
|
||||||
|
|
||||||
|
func NewProtoCodec(anyUnpacker types.AnyUnpacker) *ProtoCodec {
|
||||||
return &ProtoCodec{anyUnpacker: anyUnpacker}
|
return &ProtoCodec{anyUnpacker: anyUnpacker}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ func mustAny(msg proto.Message) *types.Any {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkProtoCodecMarshalBinaryLengthPrefixed(b *testing.B) {
|
func BenchmarkProtoCodecMarshalBinaryLengthPrefixed(b *testing.B) {
|
||||||
var pCdc = codec.NewProtoCodec(types.NewInterfaceRegistry()).(*codec.ProtoCodec)
|
var pCdc = codec.NewProtoCodec(types.NewInterfaceRegistry())
|
||||||
var msg = &testdata.HasAnimal{
|
var msg = &testdata.HasAnimal{
|
||||||
X: 1000,
|
X: 1000,
|
||||||
Animal: mustAny(&testdata.HasAnimal{
|
Animal: mustAny(&testdata.HasAnimal{
|
||||||
|
|
|
@ -17,6 +17,9 @@ type PubKey interface {
|
||||||
|
|
||||||
// GetPubKeys returns the crypto.PubKey's nested within the multi-sig PubKey
|
// GetPubKeys returns the crypto.PubKey's nested within the multi-sig PubKey
|
||||||
GetPubKeys() []crypto.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.
|
// 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
|
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.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.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.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 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
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=
|
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-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 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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.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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
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/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=
|
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=
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package cosmos.tx.signing;
|
package cosmos.tx.signing;
|
||||||
|
|
||||||
|
import "cosmos/crypto/crypto.proto";
|
||||||
|
|
||||||
option go_package = "github.com/cosmos/cosmos-sdk/types/tx/signing";
|
option go_package = "github.com/cosmos/cosmos-sdk/types/tx/signing";
|
||||||
|
|
||||||
// SignMode represents a signing mode with its own security guarantees
|
// 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
|
// Amino JSON and will be removed in the future
|
||||||
SIGN_MODE_LEGACY_AMINO_JSON = 127;
|
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.
|
// MakeEncodingConfig creates an EncodingConfig for an amino based test configuration.
|
||||||
func MakeEncodingConfig() EncodingConfig {
|
func MakeEncodingConfig() EncodingConfig {
|
||||||
cdc := codec.New()
|
amino := codec.New()
|
||||||
interfaceRegistry := types.NewInterfaceRegistry()
|
interfaceRegistry := types.NewInterfaceRegistry()
|
||||||
marshaler := codec.NewHybridCodec(cdc, interfaceRegistry)
|
marshaler := codec.NewHybridCodec(amino, interfaceRegistry)
|
||||||
txGen := tx.NewTxConfig(interfaceRegistry, std.DefaultPublicKeyCodec{}, tx.DefaultSignModeHandler())
|
txGen := tx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), std.DefaultPublicKeyCodec{}, tx.DefaultSignModeHandler())
|
||||||
|
|
||||||
return EncodingConfig{
|
return EncodingConfig{
|
||||||
InterfaceRegistry: interfaceRegistry,
|
InterfaceRegistry: interfaceRegistry,
|
||||||
Marshaler: marshaler,
|
Marshaler: marshaler,
|
||||||
TxConfig: txGen,
|
TxConfig: txGen,
|
||||||
Amino: cdc,
|
Amino: amino,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
tmcfg "github.com/tendermint/tendermint/config"
|
tmcfg "github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
@ -29,6 +27,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
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/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"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
|
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
|
// 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
|
// 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.
|
// the signatures themselves for either single or multi-signatures.
|
||||||
Data SignatureData
|
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"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
|
||||||
codec2 "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/hd"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
"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"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||||
authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
|
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"
|
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
)
|
)
|
||||||
|
@ -47,7 +44,21 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
||||||
s.cfg = cfg
|
s.cfg = cfg
|
||||||
s.network = network.New(s.T(), 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)
|
s.Require().NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,29 +84,23 @@ func (s *IntegrationTestSuite) TestCLIValidateSignatures() {
|
||||||
)
|
)
|
||||||
s.Require().NoError(err)
|
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
|
// write unsigned tx to file
|
||||||
unsignedTx, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
unsignedTx, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name())
|
res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
signedTx, err := val.ClientCtx.TxConfig.TxJSONDecoder()(res.Bytes())
|
||||||
var signedTx types.StdTx
|
|
||||||
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &signedTx)
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
signedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
signedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
txBuilder, err := val.ClientCtx.TxConfig.WrapTxBuilder(signedTx)
|
||||||
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name())
|
res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
signedTx.Memo = "MODIFIED STD TX"
|
txBuilder.SetMemo("MODIFIED TX")
|
||||||
bz, err := val.ClientCtx.JSONMarshaler.MarshalJSON(signedTx)
|
bz, err := val.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
modifiedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), string(bz))
|
modifiedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), string(bz))
|
||||||
|
@ -147,28 +152,26 @@ func (s *IntegrationTestSuite) TestCLISignBatch() {
|
||||||
defer cleanup2()
|
defer cleanup2()
|
||||||
|
|
||||||
res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID))
|
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.
|
// 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")
|
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() {
|
func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||||
val1 := s.network.Validators[0]
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||||
|
|
||||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
account.GetAddress(),
|
account.GetAddress(),
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
normalGeneratedStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, normalGeneratedTx.String())
|
txCfg := val1.ClientCtx.TxConfig
|
||||||
s.Require().Equal(normalGeneratedStdTx.Fee.Gas, uint64(flags.DefaultGasLimit))
|
|
||||||
s.Require().Equal(len(normalGeneratedStdTx.Msgs), 1)
|
normalGeneratedStdTx, err := txCfg.TxJSONDecoder()(normalGeneratedTx.Bytes())
|
||||||
s.Require().Equal(0, len(normalGeneratedStdTx.GetSignatures()))
|
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
|
// Test generate sendTx with --gas=$amount
|
||||||
limitedGasGeneratedTx, err := bankcli.MsgSendExec(
|
limitedGasGeneratedTx, err := bankcli.MsgSendExec(
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
account.GetAddress(),
|
account.GetAddress(),
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
limitedGasStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, limitedGasGeneratedTx.String())
|
limitedGasStdTx, err := txCfg.TxJSONDecoder()(limitedGasGeneratedTx.Bytes())
|
||||||
s.Require().Equal(limitedGasStdTx.Fee.Gas, uint64(100))
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(len(limitedGasStdTx.Msgs), 1)
|
txBuilder, err = txCfg.WrapTxBuilder(limitedGasStdTx)
|
||||||
s.Require().Equal(0, len(limitedGasStdTx.GetSignatures()))
|
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
|
// Test generate sendTx, estimate gas
|
||||||
finalGeneratedTx, err := bankcli.MsgSendExec(
|
finalGeneratedTx, err := bankcli.MsgSendExec(
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
account.GetAddress(),
|
account.GetAddress(),
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
finalStdTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, finalGeneratedTx.String())
|
finalStdTx, err := txCfg.TxJSONDecoder()(finalGeneratedTx.Bytes())
|
||||||
s.Require().Equal(uint64(flags.DefaultGasLimit), finalStdTx.Fee.Gas)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(len(finalStdTx.Msgs), 1)
|
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
|
// Write the output to disk
|
||||||
unsignedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String())
|
unsignedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String())
|
||||||
|
@ -245,11 +263,13 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||||
// Sign transaction
|
// Sign transaction
|
||||||
signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name())
|
signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
signedFinalTx, err := txCfg.TxJSONDecoder()(signedTx.Bytes())
|
||||||
signedFinalTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, signedTx.String())
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(len(signedFinalTx.Msgs), 1)
|
txBuilder, err = val1.ClientCtx.TxConfig.WrapTxBuilder(signedFinalTx)
|
||||||
s.Require().Equal(1, len(signedFinalTx.GetSignatures()))
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(val1.Address.String(), signedFinalTx.GetSigners()[0].String())
|
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
|
// Write the output to disk
|
||||||
signedTxFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), signedTx.String())
|
signedTxFile, cleanup2 := testutil.WriteToNewTempFile(s.T(), signedTx.String())
|
||||||
|
@ -261,11 +281,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||||
s.Require().True(strings.Contains(res.String(), "[OK]"))
|
s.Require().True(strings.Contains(res.String(), "[OK]"))
|
||||||
|
|
||||||
// Ensure foo has right amount of funds
|
// 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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
var coins sdk.Coins
|
|
||||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(startTokens, coins.AmountOf(s.cfg.BondDenom))
|
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)
|
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||||
s.Require().NoError(err)
|
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
|
// Ensure origin account state
|
||||||
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, val1.Address)
|
||||||
|
@ -299,11 +317,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
|
||||||
|
|
||||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
s.Require().Equal(sdk.NewInt(389999990), coins.AmountOf(s.cfg.BondDenom))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||||
s.T().SkipNow() // TODO check encoding.
|
|
||||||
val1 := s.network.Validators[0]
|
val1 := s.network.Validators[0]
|
||||||
|
|
||||||
codec := codec2.New()
|
codec := codec2.New()
|
||||||
|
@ -312,14 +328,10 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||||
val1.ClientCtx.Codec = codec
|
val1.ClientCtx.Codec = codec
|
||||||
|
|
||||||
// Generate 2 accounts and a multisig.
|
// 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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
account2, _, err := val1.ClientCtx.Keyring.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1)
|
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||||
s.Require().NoError(err)
|
|
||||||
|
|
||||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
|
||||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Send coins from validator to multisig.
|
// Send coins from validator to multisig.
|
||||||
|
@ -374,7 +386,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||||
defer cleanup3()
|
defer cleanup3()
|
||||||
|
|
||||||
exec, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name())
|
exec, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name())
|
||||||
s.Require().NoError(err)
|
s.Require().Error(err)
|
||||||
|
|
||||||
fmt.Printf("%s", exec)
|
fmt.Printf("%s", exec)
|
||||||
}
|
}
|
||||||
|
@ -382,15 +394,13 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
|
||||||
func (s *IntegrationTestSuite) TestCLIEncode() {
|
func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||||
val1 := s.network.Validators[0]
|
val1 := s.network.Validators[0]
|
||||||
|
|
||||||
sendTokens := sdk.TokensFromConsensusPower(10)
|
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10))
|
||||||
|
|
||||||
normalGeneratedTx, err := bankcli.MsgSendExec(
|
normalGeneratedTx, err := bankcli.MsgSendExec(
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sdk.NewCoin(s.cfg.BondDenom, sendTokens),
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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())
|
savedTxFile, cleanup := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String())
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// Enconde
|
// Encode
|
||||||
encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name())
|
encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name())
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
@ -412,12 +422,15 @@ func (s *IntegrationTestSuite) TestCLIEncode() {
|
||||||
decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64)
|
decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
theTx := unmarshalStdTx(s.T(), val1.ClientCtx.JSONMarshaler, decodedTx.String())
|
txCfg := val1.ClientCtx.TxConfig
|
||||||
s.Require().Equal("deadbeef", theTx.Memo)
|
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() {
|
func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||||
s.T().SkipNow()
|
|
||||||
val1 := s.network.Validators[0]
|
val1 := s.network.Validators[0]
|
||||||
|
|
||||||
codec := codec2.New()
|
codec := codec2.New()
|
||||||
|
@ -426,25 +439,30 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||||
val1.ClientCtx.Codec = codec
|
val1.ClientCtx.Codec = codec
|
||||||
|
|
||||||
// Generate 2 accounts and a multisig.
|
// 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)
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
|
||||||
s.Require().NoError(err)
|
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.
|
// Send coins from validator to multisig.
|
||||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||||
_, err = bankcli.MsgSendExec(
|
_, err = bankcli.MsgSendExec(
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
multisigInfo.GetAddress(),
|
multisigInfo.GetAddress(),
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sendTokens,
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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())
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
var coins sdk.Coins
|
|
||||||
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &coins)
|
||||||
s.Require().NoError(err)
|
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.
|
// Generate multisig transaction.
|
||||||
multiGeneratedTx, err := bankcli.MsgSendExec(
|
multiGeneratedTx, err := bankcli.MsgSendExec(
|
||||||
|
@ -514,7 +532,6 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegrationTestSuite) TestCLIMultisign() {
|
func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||||
s.T().SkipNow()
|
|
||||||
val1 := s.network.Validators[0]
|
val1 := s.network.Validators[0]
|
||||||
|
|
||||||
codec := codec2.New()
|
codec := codec2.New()
|
||||||
|
@ -523,14 +540,13 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||||
val1.ClientCtx.Codec = codec
|
val1.ClientCtx.Codec = codec
|
||||||
|
|
||||||
// Generate 2 accounts and a multisig.
|
// 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)
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
multi := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{account1.GetPubKey(), account2.GetPubKey()})
|
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
|
||||||
multisigInfo, err := val1.ClientCtx.Keyring.SaveMultisig("multi", multi)
|
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Send coins from validator to multisig.
|
// Send coins from validator to multisig.
|
||||||
|
@ -539,9 +555,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||||
val1.ClientCtx,
|
val1.ClientCtx,
|
||||||
val1.Address,
|
val1.Address,
|
||||||
multisigInfo.GetAddress(),
|
multisigInfo.GetAddress(),
|
||||||
sdk.NewCoins(
|
sdk.NewCoins(sendTokens),
|
||||||
sendTokens,
|
|
||||||
),
|
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
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()),
|
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()
|
defer cleanup3()
|
||||||
|
|
||||||
// Does not work in offline mode.
|
// Does not work in offline mode.
|
||||||
val1.ClientCtx.Offline = true
|
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name())
|
||||||
_, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
|
|
||||||
s.Require().EqualError(err, "couldn't verify signature")
|
s.Require().EqualError(err, "couldn't verify signature")
|
||||||
|
|
||||||
val1.ClientCtx.Offline = false
|
val1.ClientCtx.Offline = false
|
||||||
|
@ -617,7 +630,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
||||||
|
|
||||||
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
||||||
clientCtx := client.Context{}.WithOffline(true)
|
clientCtx := client.Context{}.WithOffline(true)
|
||||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
clientCtx = clientCtx.WithTxConfig(simapp.MakeEncodingConfig().TxConfig)
|
||||||
|
|
||||||
cmd := authcli.GetBroadcastCommand()
|
cmd := authcli.GetBroadcastCommand()
|
||||||
_ = testutil.ApplyMockIODiscardOutErr(cmd)
|
_ = testutil.ApplyMockIODiscardOutErr(cmd)
|
||||||
|
@ -628,7 +641,8 @@ func TestGetBroadcastCommand_OfflineFlag(t *testing.T) {
|
||||||
|
|
||||||
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||||
clientCtx := client.Context{}
|
clientCtx := client.Context{}
|
||||||
clientCtx = clientCtx.WithTxConfig(simappparams.MakeEncodingConfig().TxConfig)
|
txCfg := simapp.MakeEncodingConfig().TxConfig
|
||||||
|
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||||
|
@ -639,9 +653,17 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||||
t.Cleanup(cleanFunc)
|
t.Cleanup(cleanFunc)
|
||||||
|
|
||||||
// Create new file with tx
|
// 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")
|
txFileName := filepath.Join(testDir, "tx.json")
|
||||||
err := ioutil.WriteFile(txFileName, txContents, 0644)
|
err = ioutil.WriteFile(txFileName, txContents, 0644)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cmd.SetArgs([]string{txFileName})
|
cmd.SetArgs([]string{txFileName})
|
||||||
|
@ -654,8 +676,3 @@ func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) {
|
||||||
func TestIntegrationTestSuite(t *testing.T) {
|
func TestIntegrationTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(IntegrationTestSuite))
|
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 (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
@ -37,7 +38,12 @@ func GetDecodeCommand() *cobra.Command {
|
||||||
return err
|
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 (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
@ -10,13 +11,6 @@ import (
|
||||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
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
|
// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into
|
||||||
// Amino-serialized bytes
|
// Amino-serialized bytes
|
||||||
func GetEncodeCommand() *cobra.Command {
|
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
|
// base64 encode the encoded tx bytes
|
||||||
txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes)
|
txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes)
|
||||||
|
|
||||||
response := txEncodeRespStr(txBytesBase64)
|
return clientCtx.PrintString(fmt.Sprintf("%s\n", txBytesBase64))
|
||||||
return clientCtx.PrintOutput(response)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,17 @@ func TestGetCommandEncode(t *testing.T) {
|
||||||
authtypes.RegisterCodec(encodingConfig.Amino)
|
authtypes.RegisterCodec(encodingConfig.Amino)
|
||||||
sdk.RegisterCodec(encodingConfig.Amino)
|
sdk.RegisterCodec(encodingConfig.Amino)
|
||||||
|
|
||||||
txGen := encodingConfig.TxConfig
|
txCfg := encodingConfig.TxConfig
|
||||||
|
|
||||||
// Build a test transaction
|
// Build a test transaction
|
||||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
builder := txCfg.NewTxBuilder()
|
||||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
builder.SetGasLimit(50000)
|
||||||
JSONEncoded, err := txGen.TxJSONEncoder()(stdTx)
|
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||||
|
builder.SetMemo("foomemo")
|
||||||
|
jsonEncoded, err := txCfg.TxJSONEncoder()(builder.GetTx())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txFile, cleanup := testutil.WriteToNewTempFile(t, string(JSONEncoded))
|
txFile, cleanup := testutil.WriteToNewTempFile(t, string(jsonEncoded))
|
||||||
txFileName := txFile.Name()
|
txFileName := txFile.Name()
|
||||||
t.Cleanup(cleanup)
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
|
@ -58,15 +60,17 @@ func TestGetCommandDecode(t *testing.T) {
|
||||||
|
|
||||||
sdk.RegisterCodec(encodingConfig.Amino)
|
sdk.RegisterCodec(encodingConfig.Amino)
|
||||||
|
|
||||||
txGen := encodingConfig.TxConfig
|
txCfg := encodingConfig.TxConfig
|
||||||
clientCtx = clientCtx.WithTxConfig(txGen)
|
clientCtx = clientCtx.WithTxConfig(txCfg)
|
||||||
|
|
||||||
// Build a test transaction
|
// Build a test transaction
|
||||||
fee := authtypes.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
builder := txCfg.NewTxBuilder()
|
||||||
stdTx := authtypes.NewStdTx([]sdk.Msg{}, fee, []authtypes.StdSignature{}, "foomemo")
|
builder.SetGasLimit(50000)
|
||||||
|
builder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
|
||||||
|
builder.SetMemo("foomemo")
|
||||||
|
|
||||||
// Encode transaction
|
// Encode transaction
|
||||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(stdTx)
|
txBytes, err := clientCtx.TxConfig.TxEncoder()(builder.GetTx())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Convert the transaction into base64 encoded string
|
// Convert the transaction into base64 encoded string
|
||||||
|
|
|
@ -11,13 +11,14 @@ import (
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"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/keyring"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
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"
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
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"
|
"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 {
|
func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) (err error) {
|
return func(cmd *cobra.Command, args []string) (err error) {
|
||||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||||
cdc := clientCtx.Codec
|
clientCtx, err = client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||||
tx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
if err != nil {
|
||||||
stdTx := tx.(types.StdTx)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedTx, err := authclient.ReadTxFromFile(clientCtx, args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
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)
|
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||||
|
|
||||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||||
|
@ -85,63 +100,53 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
multisigPub := multisigInfo.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
||||||
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
|
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 {
|
if !clientCtx.Offline {
|
||||||
accnum, seq, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
|
accnum, seq, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// read each signature and add it to the multisig if valid
|
||||||
for i := 2; i < len(args); i++ {
|
for i := 2; i < len(args); i++ {
|
||||||
stdSig, err := readAndUnmarshalStdSignature(cdc, args[i])
|
sigs, err := unmarshalSignatureJSON(clientCtx, args[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate each signature
|
signingData := signing.SignerData{
|
||||||
sigBytes := types.StdSignBytes(
|
ChainID: txFactory.ChainID(),
|
||||||
txBldr.ChainID(), txBldr.AccountNumber(), txBldr.Sequence(),
|
AccountNumber: txFactory.AccountNumber(),
|
||||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
AccountSequence: txFactory.Sequence(),
|
||||||
)
|
|
||||||
if ok := stdSig.GetPubKey().VerifyBytes(sigBytes, stdSig.Signature); !ok {
|
|
||||||
return fmt.Errorf("couldn't verify signature")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sigV2, err := types.StdSignatureToSignatureV2(cdc, stdSig)
|
for _, sig := range sigs {
|
||||||
if err != nil {
|
err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx())
|
||||||
return nil
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("couldn't verify signature")
|
||||||
|
}
|
||||||
|
|
||||||
if err := multisig.AddSignatureV2(multisigSig, sigV2, multisigPub.PubKeys); err != nil {
|
if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.PubKeys); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sigBz, err := types.SignatureDataToAminoSignature(cdc, multisigSig)
|
sigV2 := signingtypes.SignatureV2{
|
||||||
|
PubKey: multisigPub,
|
||||||
|
Data: multisigSig,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = txBuilder.SetSignatures(sigV2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -158,18 +163,14 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
defer fp.Close()
|
defer fp.Close()
|
||||||
|
|
||||||
fmt.Fprintf(fp, "%s\n", json)
|
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
var bytes []byte
|
||||||
if bytes, err = ioutil.ReadFile(filename); err != nil {
|
if bytes, err = ioutil.ReadFile(filename); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = cdc.UnmarshalJSON(bytes, &stdSig); err != nil {
|
return clientCtx.TxConfig.UnmarshalSignatureJSON(bytes)
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -9,10 +8,10 @@ import (
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -61,12 +60,13 @@ account key. It implies --signature-only.
|
||||||
func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||||
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||||
txBldr, err := types.NewTxBuilderFromFlags(bufio.NewReader(cmd.InOrStdin()), cmd.Flags(), clientCtx.HomeDir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||||
|
|
||||||
|
txCfg := clientCtx.TxConfig
|
||||||
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -97,34 +97,34 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
scanner := authclient.NewBatchScanner(txCfg, infile)
|
||||||
|
|
||||||
scanner := authclient.NewBatchScanner(clientCtx.JSONMarshaler, infile)
|
for sequence := txFactory.Sequence(); scanner.Scan(); sequence++ {
|
||||||
|
unsignedStdTx := scanner.Tx()
|
||||||
for sequence := txBldr.Sequence(); scanner.Scan(); sequence++ {
|
txFactory = txFactory.WithSequence(sequence)
|
||||||
var stdTx types.StdTx
|
txBuilder, err := txCfg.WrapTxBuilder(unsignedStdTx)
|
||||||
|
if err != nil {
|
||||||
unsignedStdTx := scanner.StdTx()
|
return err
|
||||||
txBldr = txBldr.WithSequence(sequence)
|
}
|
||||||
|
|
||||||
if multisigAddr.Empty() {
|
if multisigAddr.Empty() {
|
||||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
return fmt.Errorf("error getting account from keybase: %w", err)
|
||||||
}
|
}
|
||||||
|
err = authclient.SignTx(txFactory, clientCtx, fromName, txBuilder, true)
|
||||||
stdTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, unsignedStdTx, false, true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stdTx, err = authclient.SignStdTxWithSignerAddress(txBldr, clientCtx, multisigAddr, clientCtx.GetFromName(), unsignedStdTx, true)
|
err = authclient.SignTxWithSignerAddress(txFactory, clientCtx, multisigAddr, clientCtx.GetFromName(), txBuilder, true)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, stdTx, generateSignatureOnly)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -206,20 +206,31 @@ func preSignCmd(cmd *cobra.Command, _ []string) {
|
||||||
func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||||
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
||||||
clientCtx, txBldr, tx, err := readStdTxAndInitContexts(clientCtx, cmd, args[0])
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stdTx := tx.(types.StdTx)
|
|
||||||
|
|
||||||
// if --signature-only is on, then override --append
|
// if --signature-only is on, then override --append
|
||||||
var newTx types.StdTx
|
|
||||||
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
generateSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly)
|
||||||
multisigAddrStr, _ := cmd.Flags().GetString(flagMultisig)
|
multisigAddrStr, _ := cmd.Flags().GetString(flagMultisig)
|
||||||
|
|
||||||
from, _ := cmd.Flags().GetString(flags.FlagFrom)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting account from keybase: %w", err)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newTx, err = authclient.SignStdTxWithSignerAddress(
|
err = authclient.SignTxWithSignerAddress(
|
||||||
txBldr, clientCtx, multisigAddr, fromName, stdTx, clientCtx.Offline,
|
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline,
|
||||||
)
|
)
|
||||||
generateSignatureOnly = true
|
generateSignatureOnly = true
|
||||||
} else {
|
} else {
|
||||||
append, _ := cmd.Flags().GetBool(flagAppend)
|
flagAppend, _ := cmd.Flags().GetBool(flagAppend)
|
||||||
appendSig := append && !generateSignatureOnly
|
appendSig := flagAppend && !generateSignatureOnly
|
||||||
newTx, err = authclient.SignStdTx(txBldr, clientCtx, fromName, stdTx, appendSig, clientCtx.Offline)
|
if appendSig {
|
||||||
if err != nil {
|
err = authclient.SignTx(txF, clientCtx, clientCtx.GetFromName(), txBuilder, clientCtx.Offline)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
json, err := getSignatureJSON(clientCtx.JSONMarshaler, newTx, generateSignatureOnly)
|
json, err := marshalSignatureJSON(txCfg, txBuilder, generateSignatureOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -265,15 +275,20 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
defer fp.Close()
|
defer fp.Close()
|
||||||
|
|
||||||
fmt.Fprintf(fp, "%s\n", json)
|
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
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
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
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 {
|
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 {
|
func makeValidateSignaturesCmd() func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stdTx := tx.(types.StdTx)
|
|
||||||
|
|
||||||
if !printAndValidateSigs(cmd, clientCtx, txBldr.ChainID(), stdTx, clientCtx.Offline) {
|
if !printAndValidateSigs(cmd, clientCtx, txBldr.ChainID(), stdTx, clientCtx.Offline) {
|
||||||
return fmt.Errorf("signatures validation failed")
|
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
|
// 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.
|
// verified over the transaction sign bytes. Returns false if the validation fails.
|
||||||
func printAndValidateSigs(
|
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 {
|
) bool {
|
||||||
cmd.Println("Signers:")
|
sigTx := tx.(authsigning.SigVerifiableTx)
|
||||||
signers := stdTx.GetSigners()
|
signModeHandler := clientCtx.TxConfig.SignModeHandler()
|
||||||
|
|
||||||
|
cmd.Println("Signers:")
|
||||||
|
signers := sigTx.GetSigners()
|
||||||
for i, signer := range signers {
|
for i, signer := range signers {
|
||||||
cmd.Printf(" %v: %v\n", i, signer.String())
|
cmd.Printf(" %v: %v\n", i, signer.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
success := true
|
success := true
|
||||||
sigs := stdTx.Signatures
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
cmd.Println("")
|
cmd.Println("")
|
||||||
cmd.Println("Signatures:")
|
cmd.Println("Signatures:")
|
||||||
|
|
||||||
|
@ -79,9 +86,10 @@ func printAndValidateSigs(
|
||||||
|
|
||||||
for i, sig := range sigs {
|
for i, sig := range sigs {
|
||||||
var (
|
var (
|
||||||
|
pubKey = sig.PubKey
|
||||||
multiSigHeader string
|
multiSigHeader string
|
||||||
multiSigMsg string
|
multiSigMsg string
|
||||||
sigAddr = sdk.AccAddress(sig.GetPubKey().Address())
|
sigAddr = sdk.AccAddress(pubKey.Address())
|
||||||
sigSanity = "OK"
|
sigSanity = "OK"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -93,40 +101,21 @@ func printAndValidateSigs(
|
||||||
// Validate the actual signature over the transaction bytes since we can
|
// Validate the actual signature over the transaction bytes since we can
|
||||||
// reach out to a full node to query accounts.
|
// reach out to a full node to query accounts.
|
||||||
if !offline && success {
|
if !offline && success {
|
||||||
acc, err := types.NewAccountRetriever(clientCtx.JSONMarshaler).GetAccount(clientCtx, sigAddr)
|
accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, sigAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.Printf("failed to get account: %s\n", sigAddr)
|
cmd.Printf("failed to get account: %s\n", sigAddr)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sigBytes := types.StdSignBytes(
|
signingData := authsigning.SignerData{
|
||||||
chainID, acc.GetAccountNumber(), acc.GetSequence(),
|
ChainID: chainID,
|
||||||
stdTx.Fee, stdTx.GetMsgs(), stdTx.GetMemo(),
|
AccountNumber: accNum,
|
||||||
)
|
AccountSequence: accSeq,
|
||||||
|
|
||||||
if ok := sig.GetPubKey().VerifyBytes(sigBytes, sig.Signature); !ok {
|
|
||||||
sigSanity = "ERROR: signature invalid"
|
|
||||||
success = false
|
|
||||||
}
|
}
|
||||||
}
|
err = authsigning.VerifySignature(pubKey, signingData, sig.Data, signModeHandler, sigTx)
|
||||||
|
if err != nil {
|
||||||
multiPK, ok := sig.GetPubKey().(multisig.PubKeyMultisigThreshold)
|
return false
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
func readStdTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (
|
func readTxAndInitContexts(clientCtx client.Context, cmd *cobra.Command, filename string) (client.Context, tx.Factory, sdk.Tx, error) {
|
||||||
client.Context, types.TxBuilder, sdk.Tx, error,
|
|
||||||
) {
|
|
||||||
stdTx, err := authclient.ReadTxFromFile(clientCtx, filename)
|
stdTx, err := authclient.ReadTxFromFile(clientCtx, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
return clientCtx, tx.Factory{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||||
clientCtx = clientCtx.WithInput(inBuf)
|
|
||||||
|
|
||||||
txBldr, err := types.NewTxBuilderFromFlags(inBuf, cmd.Flags(), clientCtx.HomeDir)
|
return clientCtx, txFactory, stdTx, nil
|
||||||
if err != nil {
|
|
||||||
return client.Context{}, types.TxBuilder{}, types.StdTx{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return clientCtx, txBldr, stdTx, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/jsonpb"
|
"github.com/gogo/protobuf/jsonpb"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"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"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
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)
|
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
|
// EnrichWithGas calculates the gas estimate that would be consumed by the
|
||||||
// transaction and set the transaction's respective value accordingly.
|
// transaction and set the transaction's respective value accordingly.
|
||||||
func EnrichWithGas(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) (authtypes.TxBuilder, error) {
|
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.
|
// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
|
||||||
func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, clientCtx client.Context, msgs []sdk.Msg) error {
|
func PrintUnsignedStdTx(txBldr tx.Factory, clientCtx client.Context, msgs []sdk.Msg) error {
|
||||||
stdTx, err := buildUnsignedStdTxOffline(txBldr, clientCtx, msgs)
|
err := tx.GenerateOrBroadcastTxWithFactory(clientCtx, txBldr, msgs...)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdTx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = fmt.Fprintf(clientCtx.Output, "%s\n", json)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// is false, it replaces the signatures already attached with the new signature.
|
||||||
// Don't perform online validation or lookups if offline is true.
|
// Don't perform online validation or lookups if offline is true.
|
||||||
func SignStdTx(
|
func SignTx(txFactory tx.Factory, clientCtx client.Context, name string, stdTx client.TxBuilder, offline bool) error {
|
||||||
txBldr authtypes.TxBuilder, clientCtx client.Context, name string,
|
info, err := txFactory.Keybase().Key(name)
|
||||||
stdTx authtypes.StdTx, appendSig bool, offline bool,
|
|
||||||
) (authtypes.StdTx, error) {
|
|
||||||
|
|
||||||
var signedStdTx authtypes.StdTx
|
|
||||||
|
|
||||||
info, err := txBldr.Keybase().Key(name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return signedStdTx, err
|
return err
|
||||||
}
|
}
|
||||||
|
addr := sdk.AccAddress(info.GetPubKey().Address())
|
||||||
addr := info.GetPubKey().Address()
|
if !isTxSigner(addr, stdTx.GetTx().GetSigners()) {
|
||||||
|
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||||
// check whether the address is a signer
|
|
||||||
if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) {
|
|
||||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !offline {
|
if !offline {
|
||||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, sdk.AccAddress(addr))
|
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||||
if err != nil {
|
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
|
// Don't perform online validation or lookups if offline is true, else
|
||||||
// populate account and sequence numbers from a foreign account.
|
// populate account and sequence numbers from a foreign account.
|
||||||
func SignStdTxWithSignerAddress(
|
func SignTxWithSignerAddress(txFactory tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||||
txBldr authtypes.TxBuilder, clientCtx client.Context,
|
name string, txBuilder client.TxBuilder, offline bool) (err error) {
|
||||||
addr sdk.AccAddress, name string, stdTx authtypes.StdTx, offline bool,
|
|
||||||
) (signedStdTx authtypes.StdTx, err error) {
|
|
||||||
|
|
||||||
// check whether the address is a signer
|
// check whether the address is a signer
|
||||||
if !isTxSigner(addr, stdTx.GetSigners()) {
|
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
|
||||||
return signedStdTx, fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !offline {
|
if !offline {
|
||||||
txBldr, err = populateAccountFromState(txBldr, clientCtx, addr)
|
txFactory, err = populateAccountFromState(txFactory, clientCtx, addr)
|
||||||
if err != nil {
|
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.
|
// 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.
|
// NewBatchScanner returns a new BatchScanner to read newline-delimited StdTx transactions from r.
|
||||||
func NewBatchScanner(cdc codec.JSONMarshaler, r io.Reader) *BatchScanner {
|
func NewBatchScanner(cfg client.TxConfig, r io.Reader) *BatchScanner {
|
||||||
return &BatchScanner{Scanner: bufio.NewScanner(r), cdc: cdc}
|
return &BatchScanner{Scanner: bufio.NewScanner(r), cfg: cfg}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchScanner provides a convenient interface for reading batch data such as a file
|
// BatchScanner provides a convenient interface for reading batch data such as a file
|
||||||
// of newline-delimited JSON encoded StdTx.
|
// of newline-delimited JSON encoded StdTx.
|
||||||
type BatchScanner struct {
|
type BatchScanner struct {
|
||||||
*bufio.Scanner
|
*bufio.Scanner
|
||||||
stdTx authtypes.StdTx
|
theTx sdk.Tx
|
||||||
cdc codec.JSONMarshaler
|
cfg client.TxConfig
|
||||||
unmarshalErr error
|
unmarshalErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdTx returns the most recent StdTx unmarshalled by a call to Scan.
|
// Tx returns the most recent Tx unmarshalled by a call to Scan.
|
||||||
func (bs BatchScanner) StdTx() authtypes.StdTx { return bs.stdTx }
|
func (bs BatchScanner) Tx() sdk.Tx { return bs.theTx }
|
||||||
|
|
||||||
// UnmarshalErr returns the first unmarshalling error that was encountered by the scanner.
|
// UnmarshalErr returns the first unmarshalling error that was encountered by the scanner.
|
||||||
func (bs BatchScanner) UnmarshalErr() error { return bs.unmarshalErr }
|
func (bs BatchScanner) UnmarshalErr() error { return bs.unmarshalErr }
|
||||||
|
@ -261,7 +163,9 @@ func (bs *BatchScanner) Scan() bool {
|
||||||
return false
|
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
|
bs.unmarshalErr = err
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -270,8 +174,8 @@ func (bs *BatchScanner) Scan() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateAccountFromState(
|
func populateAccountFromState(
|
||||||
txBldr authtypes.TxBuilder, clientCtx client.Context, addr sdk.AccAddress,
|
txBldr tx.Factory, clientCtx client.Context, addr sdk.AccAddress,
|
||||||
) (authtypes.TxBuilder, error) {
|
) (tx.Factory, error) {
|
||||||
|
|
||||||
num, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
|
num, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -316,56 +220,6 @@ func parseQueryResponse(bz []byte) (sdk.SimulationResponse, error) {
|
||||||
return simRes, nil
|
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 {
|
func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
|
||||||
for _, s := range signers {
|
for _, s := range signers {
|
||||||
if bytes.Equal(user.Bytes(), s.Bytes()) {
|
if bytes.Equal(user.Bytes(), s.Bytes()) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/std"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil"
|
"github.com/cosmos/cosmos-sdk/testutil"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
|
||||||
|
@ -149,8 +150,12 @@ func TestReadStdTxFromFile(t *testing.T) {
|
||||||
|
|
||||||
func TestBatchScanner_Scan(t *testing.T) {
|
func TestBatchScanner_Scan(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
cdc := codec.New()
|
encodingConfig := simappparams.MakeEncodingConfig()
|
||||||
sdk.RegisterCodec(cdc)
|
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"}
|
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"}
|
{"msg":[],"fee":{"amount":[{"denom":"atom","amount":"150"}],"gas":"10000"},"signatures":[],"memo":"foomemo"}
|
||||||
|
@ -182,12 +187,12 @@ malformed
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
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() {
|
for scanner.Scan() {
|
||||||
_ = scanner.StdTx()
|
_ = scanner.Tx()
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
t.Log(scanner.theTx)
|
||||||
require.Equal(t, tt.wantScannerError, scanner.Err() != nil)
|
require.Equal(t, tt.wantScannerError, scanner.Err() != nil)
|
||||||
require.Equal(t, tt.wantUnmarshalError, scanner.UnmarshalErr() != nil)
|
require.Equal(t, tt.wantUnmarshalError, scanner.UnmarshalErr() != nil)
|
||||||
require.Equal(t, tt.numTxs, i)
|
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)
|
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 {
|
func makeCodec() *codec.Codec {
|
||||||
var cdc = codec.New()
|
var cdc = codec.New()
|
||||||
sdk.RegisterCodec(cdc)
|
sdk.RegisterCodec(cdc)
|
||||||
|
|
|
@ -3,8 +3,9 @@ package tx
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
@ -17,17 +18,19 @@ type generator struct {
|
||||||
encoder sdk.TxEncoder
|
encoder sdk.TxEncoder
|
||||||
jsonDecoder sdk.TxDecoder
|
jsonDecoder sdk.TxDecoder
|
||||||
jsonEncoder sdk.TxEncoder
|
jsonEncoder sdk.TxEncoder
|
||||||
|
protoCodec *codec.ProtoCodec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTxConfig returns a new protobuf TxConfig using the provided Marshaler, PublicKeyCodec and SignModeHandler.
|
// NewTxConfig returns a new protobuf TxConfig using the provided ProtoCodec, PublicKeyCodec and SignModeHandler.
|
||||||
func NewTxConfig(anyUnpacker codectypes.AnyUnpacker, pubkeyCodec types.PublicKeyCodec, signModeHandler signing.SignModeHandler) client.TxConfig {
|
func NewTxConfig(protoCodec *codec.ProtoCodec, pubkeyCodec types.PublicKeyCodec, signModeHandler signing.SignModeHandler) client.TxConfig {
|
||||||
return &generator{
|
return &generator{
|
||||||
pubkeyCodec: pubkeyCodec,
|
pubkeyCodec: pubkeyCodec,
|
||||||
handler: signModeHandler,
|
handler: signModeHandler,
|
||||||
decoder: DefaultTxDecoder(anyUnpacker, pubkeyCodec),
|
decoder: DefaultTxDecoder(protoCodec, pubkeyCodec),
|
||||||
encoder: DefaultTxEncoder(),
|
encoder: DefaultTxEncoder(),
|
||||||
jsonDecoder: DefaultJSONTxDecoder(anyUnpacker, pubkeyCodec),
|
jsonDecoder: DefaultJSONTxDecoder(protoCodec, pubkeyCodec),
|
||||||
jsonEncoder: DefaultJSONTxEncoder(),
|
jsonEncoder: DefaultJSONTxEncoder(),
|
||||||
|
protoCodec: protoCodec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package tx
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
@ -102,3 +104,50 @@ func decodeMultisignatures(bz []byte) ([][]byte, error) {
|
||||||
}
|
}
|
||||||
return multisig.Signatures, nil
|
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/client"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/legacy"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"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))
|
sigs := make([]StdSignature, len(signatures))
|
||||||
|
|
||||||
for i, sig := range signatures {
|
for i, sig := range signatures {
|
||||||
var pubKeyBz []byte
|
stdSig, err := SignatureV2ToStdSignature(s.cdc, sig)
|
||||||
|
if err != nil {
|
||||||
pubKey := sig.PubKey
|
return err
|
||||||
if pubKey != nil {
|
|
||||||
pubKeyBz = pubKey.Bytes()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
sigs[i] = stdSig
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Signatures = sigs
|
s.Signatures = sigs
|
||||||
|
@ -131,6 +113,38 @@ func (s StdTxConfig) TxJSONDecoder() sdk.TxDecoder {
|
||||||
return DefaultJSONTxDecoder(s.Cdc)
|
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 {
|
func (s StdTxConfig) SignModeHandler() authsigning.SignModeHandler {
|
||||||
return LegacyAminoJSONHandler{}
|
return LegacyAminoJSONHandler{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,6 +395,33 @@ func StdSignatureToSignatureV2(cdc *codec.Codec, sig StdSignature) (signing.Sign
|
||||||
}, nil
|
}, 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) {
|
func pubKeySigToSigData(cdc *codec.Codec, key crypto.PubKey, sig []byte) (signing.SignatureData, error) {
|
||||||
multiPK, ok := key.(multisig.PubKey)
|
multiPK, ok := key.(multisig.PubKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"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/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"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")
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error creating tx builder")
|
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())
|
clientCtx = clientCtx.WithInput(inBuf).WithFromAddress(key.GetAddress())
|
||||||
|
|
||||||
// create a 'create-validator' message
|
// 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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to build create-validator message")
|
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
|
// 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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to sign std tx")
|
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")
|
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
|
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)
|
outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -109,6 +109,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() {
|
||||||
fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()),
|
fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
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()),
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||||
},
|
},
|
||||||
false, &sdk.TxResponse{}, 0,
|
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", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)).String()),
|
||||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
|
||||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
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()),
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
|
||||||
},
|
},
|
||||||
false, &sdk.TxResponse{}, 0,
|
false, &sdk.TxResponse{}, 0,
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/version"
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/staking/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.
|
// 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
|
amounstStr := config.Amount
|
||||||
amount, err := sdk.ParseCoin(amounstStr)
|
amount, err := sdk.ParseCoin(amounstStr)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue