Skip to content

Commit

Permalink
Make first 2 tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
amaury1093 committed Jul 10, 2020
1 parent f208c45 commit edc3be6
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 129 deletions.
84 changes: 59 additions & 25 deletions client/tx/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/gogo/protobuf/jsonpb"
"github.com/spf13/pflag"
"github.com/tendermint/tendermint/crypto"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
Expand Down Expand Up @@ -310,6 +311,60 @@ func PrepareFactory(clientCtx client.Context, txf Factory) (Factory, error) {
return txf, nil
}

// Helper function get generate the sign bytes to be signed and signature data.
// Used in SignWithPriv and in Sign functions.
func getSignBytes(pubKey crypto.PubKey, accNum uint64, seq uint64, chainID string, txGenerator client.TxGenerator, txBuilder client.TxBuilder) (*signing.SingleSignatureData, []byte, error) {
sigData := &signing.SingleSignatureData{
SignMode: txGenerator.SignModeHandler().DefaultMode(),
Signature: nil,
}
sig := signing.SignatureV2{
PubKey: pubKey,
Data: sigData,
}

// Here, we're first setting a SignatureV2 with nil as signature, this is
// to set the SignerInfos, used to generate the sign bytes below.
err := txBuilder.SetSignatures(sig)
if err != nil {
return sigData, nil, err
}

signBytes, err := txGenerator.SignModeHandler().GetSignBytes(
txGenerator.SignModeHandler().DefaultMode(),
authsigning.SignerData{
ChainID: chainID,
AccountNumber: accNum,
AccountSequence: seq,
},
txBuilder.GetTx(),
)
if err != nil {
return sigData, nil, err
}

return sigData, signBytes, nil
}

// SignWithPriv signs a given tx with the given private key, and returns the
// corresponding SignatureV2 if the signing is successful.
func SignWithPriv(priv crypto.PrivKey, accNum uint64, seq uint64, chainID string, txGenerator client.TxGenerator, txBuilder client.TxBuilder) (signing.SignatureV2, error) {
var sigV2 signing.SignatureV2

sigData, sigBytes, err := getSignBytes(priv.PubKey(), accNum, seq, chainID, txGenerator, txBuilder)
if err != nil {
return sigV2, err
}

sigData.Signature = sigBytes
sigV2 = signing.SignatureV2{
PubKey: priv.PubKey(),
Data: sigData,
}

return sigV2, err
}

// Sign signs a given tx with the provided name and passphrase. If the Factory's
// Keybase is not set, a new one will be created based on the client's backend.
// The bytes signed over are canconical. The resulting signature will be set on
Expand All @@ -318,7 +373,7 @@ func PrepareFactory(clientCtx client.Context, txf Factory) (Factory, error) {
//
// Note, It is assumed the Factory has the necessary fields set that are required
// by the CanonicalSignBytes call.
func Sign(txf Factory, name string, tx client.TxBuilder) error {
func Sign(txf Factory, name string, txBuilder client.TxBuilder) error {
if txf.keybase == nil {
return errors.New("keybase must be set prior to signing a transaction")
}
Expand All @@ -334,30 +389,9 @@ func Sign(txf Factory, name string, tx client.TxBuilder) error {
return err
}

// Here, we're first setting a SignatureV2 with nil as signature, this is
// to set the SignerInfos.
pubKey := key.GetPubKey()
sigData := &signing.SingleSignatureData{
SignMode: signMode,
Signature: nil,
}
sig := signing.SignatureV2{
PubKey: pubKey,
Data: sigData,
}
err = tx.SetSignatures(sig)
if err != nil {
return err
}

signBytes, err := txf.txGenerator.SignModeHandler().GetSignBytes(
signMode,
authsigning.SignerData{
ChainID: txf.chainID,
AccountNumber: txf.accountNumber,
AccountSequence: txf.sequence,
}, tx.GetTx(),
)
sigData, signBytes, err := getSignBytes(pubKey, txf.accountNumber, txf.sequence, txf.chainID, txf.txGenerator, txBuilder)
if err != nil {
return err
}
Expand All @@ -369,14 +403,14 @@ func Sign(txf Factory, name string, tx client.TxBuilder) error {
}

sigData.Signature = sigBytes
sig = signing.SignatureV2{
sig := signing.SignatureV2{
PubKey: pubKey,
Data: sigData,
}

// And here the tx is populated with the correct signature in
// SingleSignatureData
return tx.SetSignatures(sig)
return txBuilder.SetSignatures(sig)
}

// GasEstimateResponse defines a response definition for tx gas estimation.
Expand Down
112 changes: 61 additions & 51 deletions x/auth/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"testing"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec/testdata"
"github.com/cosmos/cosmos-sdk/simapp"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
Expand All @@ -21,6 +23,7 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)

Expand Down Expand Up @@ -49,56 +52,71 @@ func setupTxBuilder() (client.Context, client.TxBuilder) {
return clientCtx, txBuilder
}

// TestAccount represents an account used in the tests below
type TestAccount struct {
priv crypto.PrivKey
acc types.AccountI
}

// Create `numAccs` accounts, and return all relevant information about them.
func createTestAccounts(numAccs int, app *simapp.SimApp, ctx sdk.Context, t *testing.T) []TestAccount {
var accounts []TestAccount

for i := 0; i < numAccs; i++ {
priv, _, addr := types.KeyTestPubAddr()
acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
err := acc.SetAccountNumber(uint64(i))
require.NoError(t, err)
app.AccountKeeper.SetAccount(ctx, acc)
app.BankKeeper.SetBalances(ctx, acc.GetAddress(), types.NewTestCoins())

accounts = append(accounts, TestAccount{priv, acc})

}

return accounts
}

// Helper function to create a tx given multiple inputs.
func createTestTx(privs []crypto.PrivKey, accNums []uint64, seqs []uint64, ctx sdk.Context, txGenerator client.TxGenerator, txBuilder client.TxBuilder, t *testing.T) xauthsigning.SigFeeMemoTx {
var sigsV2 []signing.SignatureV2
for i, priv := range privs {
sigV2, err := tx.SignWithPriv(priv, accNums[i], seqs[i], ctx.ChainID(), txGenerator, txBuilder)
require.NoError(t, err)

sigsV2 = append(sigsV2, sigV2)
}
txBuilder.SetSignatures(sigsV2...)

return txBuilder.GetTx()
}

// Test that simulate transaction accurately estimates gas cost
func TestSimulateGasCost(t *testing.T) {
// setup
app, ctx := createTestApp(true)
ctx = ctx.WithBlockHeight(1)
anteHandler := ante.NewAnteHandler(app.AccountKeeper, app.BankKeeper, *app.IBCKeeper, ante.DefaultSigVerificationGasConsumer, types.LegacyAminoJSONHandler{})

// keys and addresses
priv1, _, addr1 := types.KeyTestPubAddr()
priv2, _, addr2 := types.KeyTestPubAddr()
priv3, _, addr3 := types.KeyTestPubAddr()

// set the accounts
acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
require.NoError(t, acc1.SetAccountNumber(0))
app.AccountKeeper.SetAccount(ctx, acc1)
err := app.BankKeeper.SetBalances(ctx, acc1.GetAddress(), types.NewTestCoins())
require.NoError(t, err)
acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
require.NoError(t, acc2.SetAccountNumber(1))
app.AccountKeeper.SetAccount(ctx, acc2)
err = app.BankKeeper.SetBalances(ctx, acc2.GetAddress(), types.NewTestCoins())
require.NoError(t, err)
acc3 := app.AccountKeeper.NewAccountWithAddress(ctx, addr3)
require.NoError(t, acc3.SetAccountNumber(2))
app.AccountKeeper.SetAccount(ctx, acc3)
err = app.BankKeeper.SetBalances(ctx, acc3.GetAddress(), types.NewTestCoins())
require.NoError(t, err)

accounts := createTestAccounts(3, app, ctx, t)
clientCtx, txBuilder := setupTxBuilder()

// set up msgs and fee
msg1 := testdata.NewTestMsg(addr1, addr2)
msg2 := testdata.NewTestMsg(addr3, addr1)
msg3 := testdata.NewTestMsg(addr2, addr3)
msg1 := testdata.NewTestMsg(accounts[0].acc.GetAddress(), accounts[1].acc.GetAddress())
msg2 := testdata.NewTestMsg(accounts[2].acc.GetAddress(), accounts[0].acc.GetAddress())
msg3 := testdata.NewTestMsg(accounts[1].acc.GetAddress(), accounts[2].acc.GetAddress())
txBuilder.SetMsgs(msg1, msg2, msg3)

// signers in order. seqs are all 0 because it is in genesis block
privs, accNums, seqs := []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
privs, accNums, seqs := []crypto.PrivKey{accounts[0].priv, accounts[1].priv, accounts[2].priv}, []uint64{0, 1, 2}, []uint64{0, 0, 0}

// Round 1: tx with 150atom
fee := types.NewTestStdFee()
txBuilder.SetFeeAmount(fee.GetAmount())
// Sign
sigsV2, err := types.NewTestTx2(ctx, clientCtx.TxGenerator, txBuilder, privs, accNums, seqs)
require.NoError(t, err)
txBuilder.SetSignatures(sigsV2...)
tx := createTestTx(privs, accNums, seqs, ctx, clientCtx.TxGenerator, txBuilder, t)
println(tx.GetFee())
// Run ante handler
cc, _ := ctx.CacheContext()
newCtx, err := anteHandler(cc, txBuilder.GetTx(), true)
newCtx, err := anteHandler(cc, tx, true)
require.Nil(t, err, "transaction failed on simulate mode")

// Increment seqs, as anteHandler calls IncrementSequenceDecorator
Expand All @@ -110,11 +128,9 @@ func TestSimulateGasCost(t *testing.T) {
// Round 2: update tx with exact simulated gas estimate
txBuilder.SetGasLimit(fee.Gas)
// Sign
sigsV2, err = types.NewTestTx2(newCtx, clientCtx.TxGenerator, txBuilder, privs, accNums, seqs)
require.NoError(t, err)
txBuilder.SetSignatures(sigsV2...)
tx = createTestTx(privs, accNums, seqs, newCtx, clientCtx.TxGenerator, txBuilder, t)
// Run ante handler
_, err = anteHandler(newCtx, txBuilder.GetTx(), false)
_, err = anteHandler(newCtx, tx, false)
require.Nil(t, err, "transaction failed with gas estimate")
}

Expand All @@ -140,38 +156,32 @@ func TestAnteHandlerSigErrors(t *testing.T) {

// test no signatures
privs, accNums, seqs := []crypto.PrivKey{}, []uint64{}, []uint64{}
sigsV2, err := types.NewTestTx2(ctx, clientCtx.TxGenerator, txBuilder, privs, accNums, seqs)
require.NoError(t, err)
txBuilder.SetSignatures(sigsV2...)
tx := createTestTx(privs, accNums, seqs, ctx, clientCtx.TxGenerator, txBuilder, t)

// tx.GetSigners returns addresses in correct order: addr1, addr2, addr3
expectedSigners := []sdk.AccAddress{addr1, addr2, addr3}
stdTx := txBuilder.GetTx().(types.StdTx)
stdTx := tx.(types.StdTx)
require.Equal(t, expectedSigners, stdTx.GetSigners())

// Check no signatures fails
checkInvalidTx(t, anteHandler, ctx, txBuilder.GetTx(), false, sdkerrors.ErrNoSignatures)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrNoSignatures)

// test num sigs dont match GetSigners
privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0}
sigsV2, err = types.NewTestTx2(ctx, clientCtx.TxGenerator, txBuilder, privs, accNums, seqs)
require.NoError(t, err)
txBuilder.SetSignatures(sigsV2...)
checkInvalidTx(t, anteHandler, ctx, txBuilder.GetTx(), false, sdkerrors.ErrUnauthorized)
tx = createTestTx(privs, accNums, seqs, ctx, clientCtx.TxGenerator, txBuilder, t)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)

// test an unrecognized account
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
sigsV2, err = types.NewTestTx2(ctx, clientCtx.TxGenerator, txBuilder, privs, accNums, seqs)
require.NoError(t, err)
txBuilder.SetSignatures(sigsV2...)
checkInvalidTx(t, anteHandler, ctx, txBuilder.GetTx(), false, sdkerrors.ErrUnknownAddress)
tx = createTestTx(privs, accNums, seqs, ctx, clientCtx.TxGenerator, txBuilder, t)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress)

// save the first account, but second is still unrecognized
acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
app.AccountKeeper.SetAccount(ctx, acc1)
err = app.BankKeeper.SetBalances(ctx, addr1, fee.Amount)
err := app.BankKeeper.SetBalances(ctx, addr1, fee.Amount)
require.NoError(t, err)
checkInvalidTx(t, anteHandler, ctx, txBuilder.GetTx(), false, sdkerrors.ErrUnknownAddress)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress)
}

// Test logic around account number checking with one signer and many signers.
Expand Down
53 changes: 0 additions & 53 deletions x/auth/types/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"

"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)

func NewTestStdFee() StdFee {
Expand Down Expand Up @@ -47,56 +44,6 @@ func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums
return tx
}

// TODO Rename to NewTestTx
// TODO Is this impl better than using TxFactory?
func NewTestTx2(ctx sdk.Context, txGenerator client.TxGenerator, txBuilder client.TxBuilder, privs []crypto.PrivKey, accNums []uint64, seqs []uint64) ([]signing.SignatureV2, error) {
var sigsV2 []signing.SignatureV2

for i, priv := range privs {
sigData := &signing.SingleSignatureData{
SignMode: txGenerator.SignModeHandler().DefaultMode(),
Signature: nil,
}
sig := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: sigData,
}

err := txBuilder.SetSignatures(sig)
if err != nil {
return nil, err
}

signBytes, err := txGenerator.SignModeHandler().GetSignBytes(
txGenerator.SignModeHandler().DefaultMode(),
authsigning.SignerData{
ChainID: ctx.ChainID(),
AccountNumber: accNums[i],
AccountSequence: seqs[i],
},
txBuilder.GetTx(),
)
if err != nil {
return nil, err
}

sigBytes, err := priv.Sign(signBytes)
if err != nil {
return nil, err
}

sigData.Signature = sigBytes
sig = signing.SignatureV2{
PubKey: priv.PubKey(),
Data: sigData,
}

sigsV2 = append(sigsV2, sig)
}

return sigsV2, nil
}

func NewTestTxWithMemo(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []uint64, seqs []uint64, fee StdFee, memo string) sdk.Tx {
sigs := make([]StdSignature, len(privs))
for i, priv := range privs {
Expand Down

0 comments on commit edc3be6

Please sign in to comment.