diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 4c578579b..66de2b68b 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -273,9 +273,6 @@ func TestQuizMsg(t *testing.T) { func SignCheckDeliver(t *testing.T, bapp *BasecoinApp, msg sdk.Msg, seq int64, expPass bool) { - // TODO: - var fee sdk.StdFee - // Sign the tx tx := sdk.NewStdTx(msg, fee, []sdk.StdSignature{{ PubKey: priv1.PubKey(), diff --git a/types/coin.go b/types/coin.go index ad541b99b..92871cd17 100644 --- a/types/coin.go +++ b/types/coin.go @@ -139,8 +139,14 @@ func (coins Coins) IsGTE(coinsB Coins) bool { } // IsZero returns true if there are no coins +// or all coins are zero. func (coins Coins) IsZero() bool { - return len(coins) == 0 + for _, coin := range coins { + if !coin.IsZero() { + return false + } + } + return true } // IsEqual returns true if the two sets of Coins have the same value diff --git a/x/auth/ante.go b/x/auth/ante.go index 4305929b9..2da0d9286 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -64,9 +64,12 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { // first sig pays the fees if i == 0 { - signerAcc, res = deductFees(signerAcc, fee) - if !res.IsOK() { - return ctx, res, true + // TODO: min fee + if !fee.Amount.IsZero() { + signerAcc, res = deductFees(signerAcc, fee) + if !res.IsOK() { + return ctx, res, true + } } } @@ -134,6 +137,7 @@ func processSig( func deductFees(acc sdk.Account, fee sdk.StdFee) (sdk.Account, sdk.Result) { coins := acc.GetCoins() feeAmount := fee.Amount + newCoins := coins.Minus(feeAmount) if !newCoins.IsNotNegative() { errMsg := fmt.Sprintf("%s < %s", coins, feeAmount) diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index cecc4a141..ecd222623 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -190,28 +190,38 @@ func TestAnteHandlerSequences(t *testing.T) { // Test logic around fee deduction. func TestAnteHandlerFees(t *testing.T) { - // // setup - // ms, capKey := setupMultiStore() - // mapper := NewAccountMapper(capKey, &BaseAccount{}) - // anteHandler := NewAnteHandler(mapper) - // ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) - // - // // keys and addresses - // priv1, addr1 := privAndAddr() - // priv2, addr2 := privAndAddr() - // - // // set the accounts - // acc1 := mapper.NewAccountWithAddress(ctx, addr1) - // mapper.SetAccount(ctx, acc1) - // acc2 := mapper.NewAccountWithAddress(ctx, addr2) - // mapper.SetAccount(ctx, acc2) - // - // // msg and signatures - // var tx sdk.Tx - // msg := newTestMsg(addr1) - // tx = newTestTx(ctx, msg, []crypto.PrivKey{priv1}, []int64{0}, int64(1)) + // setup + ms, capKey := setupMultiStore() + mapper := NewAccountMapper(capKey, &BaseAccount{}) + anteHandler := NewAnteHandler(mapper) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil) - // TODO + // keys and addresses + priv1, addr1 := privAndAddr() + + // set the accounts + acc1 := mapper.NewAccountWithAddress(ctx, addr1) + mapper.SetAccount(ctx, acc1) + + // msg and signatures + var tx sdk.Tx + msg := newTestMsg(addr1) + privs, seqs := []crypto.PrivKey{priv1}, []int64{0} + fee := sdk.NewStdFee(100, + sdk.Coin{"atom", 150}, + ) + + // signer does not have enough funds to pay the fee + tx = newTestTx(ctx, msg, privs, seqs, fee) + checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds) + + acc1.SetCoins(sdk.Coins{{"atom", 149}}) + mapper.SetAccount(ctx, acc1) + checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds) + + acc1.SetCoins(sdk.Coins{{"atom", 150}}) + mapper.SetAccount(ctx, acc1) + checkValidTx(t, anteHandler, ctx, tx) } func TestAnteHandlerBadSignBytes(t *testing.T) { diff --git a/x/auth/baseaccount_test.go b/x/auth/baseaccount_test.go index 85674af18..85adc8cdc 100644 --- a/x/auth/baseaccount_test.go +++ b/x/auth/baseaccount_test.go @@ -11,42 +11,106 @@ import ( wire "github.com/cosmos/cosmos-sdk/wire" ) -func TestBaseAccount(t *testing.T) { +func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.Address) { key := crypto.GenPrivKeyEd25519() pub := key.PubKey() addr := pub.Address() + return key.Wrap(), pub, addr +} + +func TestBaseAccountAddressPubKey(t *testing.T) { + _, pub1, addr1 := keyPubAddr() + _, pub2, addr2 := keyPubAddr() + acc := NewBaseAccountWithAddress(addr1) + + // check the address (set) and pubkey (not set) + assert.EqualValues(t, addr1, acc.GetAddress()) + assert.EqualValues(t, crypto.PubKey{}, acc.GetPubKey()) + + // cant override address + err := acc.SetAddress(addr2) + assert.NotNil(t, err) + assert.EqualValues(t, addr1, acc.GetAddress()) + + // set the pubkey + err = acc.SetPubKey(pub1) + assert.Nil(t, err) + assert.Equal(t, pub1, acc.GetPubKey()) + + // cant override pubkey + err = acc.SetPubKey(pub2) + assert.NotNil(t, err) + assert.Equal(t, pub1, acc.GetPubKey()) + + //------------------------------------ + + // can set address on empty account + acc2 := BaseAccount{} + err = acc2.SetAddress(addr2) + assert.Nil(t, err) + assert.EqualValues(t, addr2, acc2.GetAddress()) +} + +func TestBaseAccountCoins(t *testing.T) { + _, _, addr := keyPubAddr() + acc := NewBaseAccountWithAddress(addr) + + someCoins := sdk.Coins{{"atom", 123}, {"eth", 246}} + + err := acc.SetCoins(someCoins) + assert.Nil(t, err) + assert.Equal(t, someCoins, acc.GetCoins()) +} + +func TestBaseAccountSequence(t *testing.T) { + _, _, addr := keyPubAddr() + acc := NewBaseAccountWithAddress(addr) + + seq := int64(7) + + err := acc.SetSequence(seq) + assert.Nil(t, err) + assert.Equal(t, seq, acc.GetSequence()) +} + +func TestBaseAccountMarshal(t *testing.T) { + _, pub, addr := keyPubAddr() + acc := NewBaseAccountWithAddress(addr) + someCoins := sdk.Coins{{"atom", 123}, {"eth", 246}} seq := int64(7) - acc := NewBaseAccountWithAddress(addr) + // set everything on the account + err := acc.SetPubKey(pub) + assert.Nil(t, err) + err = acc.SetSequence(seq) + assert.Nil(t, err) + err = acc.SetCoins(someCoins) + assert.Nil(t, err) // need a codec for marshaling codec := wire.NewCodec() wire.RegisterCrypto(codec) - err := acc.SetPubKey(pub) - assert.Nil(t, err) - assert.Equal(t, pub, acc.GetPubKey()) - - assert.EqualValues(t, addr, acc.GetAddress()) - - err = acc.SetCoins(someCoins) - assert.Nil(t, err) - assert.Equal(t, someCoins, acc.GetCoins()) - - err = acc.SetSequence(seq) - assert.Nil(t, err) - assert.Equal(t, seq, acc.GetSequence()) - b, err := codec.MarshalBinary(acc) assert.Nil(t, err) - var acc2 BaseAccount + acc2 := BaseAccount{} err = codec.UnmarshalBinary(b, &acc2) assert.Nil(t, err) assert.Equal(t, acc, acc2) + // error on bad bytes acc2 = BaseAccount{} err = codec.UnmarshalBinary(b[:len(b)/2], &acc2) assert.NotNil(t, err) + +} + +func TestBaseAccountGetSet(t *testing.T) { + _, _, addr := keyPubAddr() + acc := NewBaseAccountWithAddress(addr) + + assert.Panics(t, func() { acc.Get("key") }) + assert.Panics(t, func() { acc.Set("key", "value") }) } diff --git a/x/auth/context.go b/x/auth/context.go index 90de99f78..91259d9e6 100644 --- a/x/auth/context.go +++ b/x/auth/context.go @@ -38,5 +38,9 @@ func WithSigners(ctx types.Context, accounts []types.Account) types.Context { } func GetSigners(ctx types.Context) []types.Account { - return ctx.Value(contextKeySigners).([]types.Account) + v := ctx.Value(contextKeySigners) + if v == nil { + return []types.Account{} + } + return v.([]types.Account) }