Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for protobuf TxGenerator and SIGN_MODE_DIRECT #6385

Merged
merged 57 commits into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
36ad7b7
Add TxWrapper, encoder, decoder and DirectModeHandler
aaronc Jun 10, 2020
e2f344a
fix pkg name
aaronc Jun 10, 2020
6ddfe37
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 10, 2020
50b6321
Update API and leave test TODO's
aaronc Jun 10, 2020
5f671c5
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 11, 2020
488742d
Update TxWrapper API
aaronc Jun 11, 2020
e67eaf8
tests for tx wrapper (#6410)
atheeshp Jun 12, 2020
f136f7e
Refactoring
aaronc Jun 12, 2020
633ca23
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 12, 2020
3ba70b0
Refactoring
aaronc Jun 12, 2020
e00d007
Integrate SignatureV2 API
aaronc Jun 12, 2020
5aea3ee
Fix wrapper tests
anilcse Jun 16, 2020
1c8f96d
Fix tests
anilcse Jun 16, 2020
f2dae43
Linting and API tweaks
aaronc Jun 16, 2020
ccbea1a
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 18, 2020
afb288d
Update API
aaronc Jun 18, 2020
a44e419
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 29, 2020
24095cc
WIP on updating API
aaronc Jun 29, 2020
6668490
Fix tests
aaronc Jun 29, 2020
166d301
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 30, 2020
d9c0222
Update to new SigVerifiableTx
aaronc Jun 30, 2020
b3b133b
Rename
aaronc Jun 30, 2020
f84e510
Update docs to reflect ADR 020
aaronc Jun 30, 2020
dc1c88d
proto-gen
aaronc Jun 30, 2020
ab60715
proto docs
aaronc Jun 30, 2020
129a222
cleanup
aaronc Jun 30, 2020
b538e12
cleanup
aaronc Jun 30, 2020
f18ea60
cleanup
aaronc Jun 30, 2020
13c3b5a
cleanup
aaronc Jun 30, 2020
a74165b
cleanup
aaronc Jun 30, 2020
eb22466
cleanup
aaronc Jun 30, 2020
f25b382
cleanup
aaronc Jun 30, 2020
9813ea3
Merge branch 'master' into aaronc/6213-sign-mode-direct
aaronc Jun 30, 2020
dc9c6cb
Add tests
aaronc Jun 30, 2020
864d506
Refactor and improving test coverage
aaronc Jun 30, 2020
28a3536
WIP on test coverage
aaronc Jun 30, 2020
ced7a4d
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jun 30, 2020
81bc3d0
WIP on test coverage
aaronc Jul 1, 2020
ec84fc8
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jul 1, 2020
7817dc4
proto-gen
aaronc Jul 1, 2020
0986644
Fix CompactBitArray.Size() bug
aaronc Jul 1, 2020
24f644e
Rename
aaronc Jul 1, 2020
10e450c
Remove Builder interface
aaronc Jul 1, 2020
7f2f412
Merge branch 'master' into aaronc/6213-sign-mode-direct
alexanderbez Jul 2, 2020
a2b94da
Merge branch 'master' into aaronc/6213-sign-mode-direct
aaronc Jul 2, 2020
5714dd6
Address review comments
sahith-narahari Jul 6, 2020
c13f899
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into aa…
aaronc Jul 6, 2020
90a6a97
Update x/auth/tx/sigs.go
aaronc Jul 6, 2020
d4eab3d
Update x/auth/tx/encoder.go
aaronc Jul 6, 2020
c06d2e6
Update x/auth/tx/encoder.go
aaronc Jul 6, 2020
301a58e
Merge branch 'aaronc/6213-sign-mode-direct' of github.com:cosmos/cosm…
sahith-narahari Jul 6, 2020
fe81982
Address review feedback
aaronc Jul 6, 2020
7b9217a
Fix build issues
sahith-narahari Jul 6, 2020
d3b9ab2
Merge branch 'aaronc/6213-sign-mode-direct' of github.com:cosmos/cosm…
sahith-narahari Jul 6, 2020
a8aa845
Resolve conflicts
sahith-narahari Jul 6, 2020
d15a511
Fix ValidateBasic test coverage
aaronc Jul 6, 2020
f2cbd95
Add test for malicious multisig
aaronc Jul 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
gocontext "context"
"fmt"

"github.com/cosmos/cosmos-sdk/codec/types"
gogogrpc "github.com/gogo/protobuf/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/encoding/proto"

"github.com/cosmos/cosmos-sdk/codec/types"
)

var _ gogogrpc.ClientConn = Context{}
Expand Down
260 changes: 219 additions & 41 deletions client/testutil/suite.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package testutil

import (
"bytes"

"github.com/cosmos/cosmos-sdk/codec/testdata"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"

"github.com/cosmos/cosmos-sdk/client"

Expand All @@ -25,86 +30,259 @@ func NewTxGeneratorTestSuite(txGenerator client.TxGenerator) *TxGeneratorTestSui
}

func (s *TxGeneratorTestSuite) TestTxBuilderGetTx() {
stdTxBuilder := s.TxGenerator.NewTxBuilder()
tx := stdTxBuilder.GetTx()
txBuilder := s.TxGenerator.NewTxBuilder()
tx := txBuilder.GetTx()
s.Require().NotNil(tx)
s.Require().Equal(len(tx.GetMsgs()), 0)
}

func (s *TxGeneratorTestSuite) TestTxBuilderSetFeeAmount() {
stdTxBuilder := s.TxGenerator.NewTxBuilder()
txBuilder := s.TxGenerator.NewTxBuilder()
feeAmount := sdk.Coins{
sdk.NewInt64Coin("atom", 20000000),
}
stdTxBuilder.SetFeeAmount(feeAmount)
feeTx := stdTxBuilder.GetTx().(sdk.FeeTx)
txBuilder.SetFeeAmount(feeAmount)
feeTx := txBuilder.GetTx()
s.Require().Equal(feeAmount, feeTx.GetFee())
}

func (s *TxGeneratorTestSuite) TestTxBuilderSetGasLimit() {
const newGas uint64 = 300000
stdTxBuilder := s.TxGenerator.NewTxBuilder()
stdTxBuilder.SetGasLimit(newGas)
feeTx := stdTxBuilder.GetTx().(sdk.FeeTx)
txBuilder := s.TxGenerator.NewTxBuilder()
txBuilder.SetGasLimit(newGas)
feeTx := txBuilder.GetTx()
s.Require().Equal(newGas, feeTx.GetGas())
}

func (s *TxGeneratorTestSuite) TestTxBuilderSetMemo() {
const newMemo string = "newfoomemo"
stdTxBuilder := s.TxGenerator.NewTxBuilder()
stdTxBuilder.SetMemo(newMemo)
txWithMemo := stdTxBuilder.GetTx().(sdk.TxWithMemo)
txBuilder := s.TxGenerator.NewTxBuilder()
txBuilder.SetMemo(newMemo)
txWithMemo := txBuilder.GetTx()
s.Require().Equal(txWithMemo.GetMemo(), newMemo)
}

func (s *TxGeneratorTestSuite) TestTxBuilderSetMsgs() {
stdTxBuilder := s.TxGenerator.NewTxBuilder()
tx := stdTxBuilder.GetTx()
err := stdTxBuilder.SetMsgs(sdk.NewTestMsg(), sdk.NewTestMsg())
s.Require().NoError(err)
s.Require().NotEqual(tx, stdTxBuilder.GetTx())
s.Require().Equal(len(stdTxBuilder.GetTx().GetMsgs()), 2)
}
_, _, addr1 := authtypes.KeyTestPubAddr()
_, _, addr2 := authtypes.KeyTestPubAddr()
msg1 := testdata.NewTestMsg(addr1)
msg2 := testdata.NewTestMsg(addr2)
msgs := []sdk.Msg{msg1, msg2}

type HasSignaturesTx interface {
GetSignatures() [][]byte
GetSigners() []sdk.AccAddress
GetPubKeys() []crypto.PubKey // If signer already has pubkey in context, this list will have nil in its place
txBuilder := s.TxGenerator.NewTxBuilder()

err := txBuilder.SetMsgs(msgs...)
s.Require().NoError(err)
tx := txBuilder.GetTx()
s.Require().Equal(msgs, tx.GetMsgs())
s.Require().Equal([]sdk.AccAddress{addr1, addr2}, tx.GetSigners())
s.Require().Equal(addr1, tx.FeePayer())
s.Require().Error(tx.ValidateBasic()) // should fail because of no signatures
}

func (s *TxGeneratorTestSuite) TestTxBuilderSetSignatures() {
priv := secp256k1.GenPrivKey()
privKey, pubkey, addr := authtypes.KeyTestPubAddr()
privKey2, pubkey2, _ := authtypes.KeyTestPubAddr()
multisigPk := multisig.NewPubKeyMultisigThreshold(2, []crypto.PubKey{pubkey, pubkey2})

stdTxBuilder := s.TxGenerator.NewTxBuilder()
tx := stdTxBuilder.GetTx()
singleSignatureData := signingtypes.SingleSignatureData{
Signature: priv.PubKey().Bytes(),
SignMode: signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
txBuilder := s.TxGenerator.NewTxBuilder()

// set test msg
msg := testdata.NewTestMsg(addr)
msigAddr := sdk.AccAddress(multisigPk.Address())
msg2 := testdata.NewTestMsg(msigAddr)
err := txBuilder.SetMsgs(msg, msg2)
s.Require().NoError(err)

// check that validation fails
s.Require().Error(txBuilder.GetTx().ValidateBasic())

signModeHandler := s.TxGenerator.SignModeHandler()
s.Require().Contains(signModeHandler.Modes(), signModeHandler.DefaultMode())

// set SignatureV2 without actual signature bytes
sigData1 := &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}
sig1 := signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1}

msigData := multisig.NewMultisig(2)
multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 0)
multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 1)
msig := signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData}

// fail validation without required signers
err = txBuilder.SetSignatures(sig1)
s.Require().NoError(err)
sigTx := txBuilder.GetTx()
s.Require().Error(sigTx.ValidateBasic())

err = txBuilder.SetSignatures(sig1, msig)
s.Require().NoError(err)
sigTx = txBuilder.GetTx()
s.Require().Len(sigTx.GetSignatures(), 2)
sigsV2, err := sigTx.GetSignaturesV2()
s.Require().NoError(err)
s.Require().Len(sigsV2, 2)
s.Require().True(sigEquals(sig1, sigsV2[0]))
s.Require().True(sigEquals(msig, sigsV2[1]))
s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners())
s.Require().NoError(sigTx.ValidateBasic())

// sign transaction
signerData := signing.SignerData{
ChainID: "test",
AccountNumber: 1,
AccountSequence: 2,
}
signBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx)
s.Require().NoError(err)
sigBz, err := privKey.Sign(signBytes)
s.Require().NoError(err)

err := stdTxBuilder.SetSignatures(signingtypes.SignatureV2{
PubKey: priv.PubKey(),
Data: &singleSignatureData,
})
sigTx := stdTxBuilder.GetTx().(HasSignaturesTx)
signerData = signing.SignerData{
ChainID: "test",
AccountNumber: 3,
AccountSequence: 4,
}
mSignBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx)
s.Require().NoError(err)
mSigBz1, err := privKey.Sign(mSignBytes)
s.Require().NoError(err)
s.Require().NotEqual(tx, stdTxBuilder.GetTx())
s.Require().Equal(sigTx.GetSignatures()[0], priv.PubKey().Bytes())
mSigBz2, err := privKey2.Sign(mSignBytes)
s.Require().NoError(err)
msigData = multisig.NewMultisig(2)
multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{
SignMode: signModeHandler.DefaultMode(), Signature: mSigBz1}, 0)
multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{
SignMode: signModeHandler.DefaultMode(), Signature: mSigBz2}, 0)

// set signature
sigData1.Signature = sigBz
sig1 = signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1}
msig = signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData}
err = txBuilder.SetSignatures(sig1, msig)
s.Require().NoError(err)
sigTx = txBuilder.GetTx()
s.Require().Len(sigTx.GetSignatures(), 2)
sigsV2, err = sigTx.GetSignaturesV2()
s.Require().NoError(err)
s.Require().Len(sigsV2, 2)
s.Require().True(sigEquals(sig1, sigsV2[0]))
s.Require().True(sigEquals(msig, sigsV2[1]))
s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners())
s.Require().NoError(sigTx.ValidateBasic())
}

func sigEquals(sig1, sig2 signingtypes.SignatureV2) bool {
if !sig1.PubKey.Equals(sig2.PubKey) {
return false
}

if sig1.Data == nil && sig2.Data == nil {
return true
}

return sigDataEquals(sig1.Data, sig2.Data)
}

func sigDataEquals(data1, data2 signingtypes.SignatureData) bool {
switch data1 := data1.(type) {
case *signingtypes.SingleSignatureData:
data2, ok := data2.(*signingtypes.SingleSignatureData)
if !ok {
return false
}

if data1.SignMode != data2.SignMode {
return false
}

return bytes.Equal(data1.Signature, data2.Signature)
case *signingtypes.MultiSignatureData:
data2, ok := data2.(*signingtypes.MultiSignatureData)
if !ok {
return false
}

if data1.BitArray.ExtraBitsStored != data2.BitArray.ExtraBitsStored {
return false
}

if !bytes.Equal(data1.BitArray.Elems, data2.BitArray.Elems) {
return false
}

if len(data1.Signatures) != len(data2.Signatures) {
return false
}

for i, s := range data1.Signatures {
if !sigDataEquals(s, data2.Signatures[i]) {
return false
}
}

return true
default:
return false
}
}

func (s *TxGeneratorTestSuite) TestTxEncodeDecode() {
_, pubkey, addr := authtypes.KeyTestPubAddr()
feeAmount := sdk.Coins{sdk.NewInt64Coin("atom", 150)}
gasLimit := uint64(50000)
memo := "foomemo"
msg := testdata.NewTestMsg(addr)
dummySig := []byte("dummySig")
sig := signingtypes.SignatureV2{
PubKey: pubkey,
Data: &signingtypes.SingleSignatureData{
SignMode: signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
Signature: dummySig,
},
}

txBuilder := s.TxGenerator.NewTxBuilder()
txBuilder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("atom", 150)})
txBuilder.SetGasLimit(50000)
txBuilder.SetMemo("foomemo")
txBuilder.SetFeeAmount(feeAmount)
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetMemo(memo)
err := txBuilder.SetMsgs(msg)
s.Require().NoError(err)
err = txBuilder.SetSignatures(sig)
s.Require().NoError(err)
tx := txBuilder.GetTx()

// Encode transaction
s.T().Log("encode transaction")
txBytes, err := s.TxGenerator.TxEncoder()(tx)
s.Require().NoError(err)
s.Require().NotNil(txBytes)

s.T().Log("decode transaction")
tx2, err := s.TxGenerator.TxDecoder()(txBytes)
s.Require().NoError(err)
s.Require().Equal(tx, tx2)
tx3, ok := tx2.(signing.SigFeeMemoTx)
s.Require().True(ok)
s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs())
s.Require().Equal(feeAmount, tx3.GetFee())
s.Require().Equal(gasLimit, tx3.GetGas())
s.Require().Equal(memo, tx3.GetMemo())
s.Require().Equal([][]byte{dummySig}, tx3.GetSignatures())
s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys())

s.T().Log("JSON encode transaction")
jsonTxBytes, err := s.TxGenerator.TxJSONEncoder()(tx)
s.Require().NoError(err)
s.Require().NotNil(jsonTxBytes)

s.T().Log("JSON decode transaction")
tx2, err = s.TxGenerator.TxJSONDecoder()(jsonTxBytes)
s.Require().NoError(err)
tx3, ok = tx2.(signing.SigFeeMemoTx)
s.Require().True(ok)
s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs())
s.Require().Equal(feeAmount, tx3.GetFee())
s.Require().Equal(gasLimit, tx3.GetGas())
s.Require().Equal(memo, tx3.GetMemo())
s.Require().Equal([][]byte{dummySig}, tx3.GetSignatures())
s.Require().Equal([]crypto.PubKey{pubkey}, tx3.GetPubKeys())
}
6 changes: 3 additions & 3 deletions client/tx/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"errors"
"testing"

"github.com/cosmos/cosmos-sdk/x/auth/signing"

"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/tests"

"github.com/cosmos/cosmos-sdk/x/auth/ante"

"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestBuildUnsignedTx(t *testing.T) {
tx, err := tx.BuildUnsignedTx(txf, msg)
require.NoError(t, err)
require.NotNil(t, tx)
require.Empty(t, tx.GetTx().(ante.SigVerifiableTx).GetSignatures())
require.Empty(t, tx.GetTx().(signing.SigVerifiableTx).GetSignatures())
}

func TestSign(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion client/tx_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type (
// signatures, and provide canonical bytes to sign over. The transaction must
// also know how to encode itself.
TxBuilder interface {
GetTx() sdk.Tx
GetTx() signing.SigFeeMemoTx
aaronc marked this conversation as resolved.
Show resolved Hide resolved

SetMsgs(msgs ...sdk.Msg) error
SetSignatures(signatures ...signingtypes.SignatureV2) error
Expand Down
Loading