2018-01-20 20:08:00 -08:00
|
|
|
package baseapp
|
2017-12-20 17:34:51 -08:00
|
|
|
|
|
|
|
import (
|
2018-07-06 07:47:07 -07:00
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
2020-04-16 08:10:39 -07:00
|
|
|
"encoding/json"
|
2017-12-20 17:34:51 -08:00
|
|
|
"fmt"
|
2018-02-16 17:15:38 -08:00
|
|
|
"os"
|
2020-03-26 09:50:39 -07:00
|
|
|
"strings"
|
2020-01-04 11:50:38 -08:00
|
|
|
"sync"
|
2017-12-20 17:34:51 -08:00
|
|
|
"testing"
|
|
|
|
|
2020-06-04 11:48:06 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/codec/testdata"
|
|
|
|
|
2020-03-26 09:50:39 -07:00
|
|
|
"github.com/gogo/protobuf/jsonpb"
|
2017-12-20 17:34:51 -08:00
|
|
|
"github.com/stretchr/testify/assert"
|
2018-05-11 11:02:05 -07:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-06-28 17:54:47 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
2018-07-02 13:34:06 -07:00
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2019-08-02 06:20:39 -07:00
|
|
|
dbm "github.com/tendermint/tm-db"
|
2018-01-15 17:38:56 -08:00
|
|
|
|
2018-09-13 11:17:32 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2019-08-06 05:59:22 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/store/rootmulti"
|
|
|
|
store "github.com/cosmos/cosmos-sdk/store/types"
|
2018-01-15 17:38:56 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-10-10 05:46:09 -07:00
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2017-12-20 17:34:51 -08:00
|
|
|
)
|
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
var (
|
|
|
|
capKey1 = sdk.NewKVStoreKey("key1")
|
|
|
|
capKey2 = sdk.NewKVStoreKey("key2")
|
|
|
|
)
|
|
|
|
|
2020-04-16 08:10:39 -07:00
|
|
|
type paramStore struct {
|
|
|
|
db *dbm.MemDB
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *paramStore) Set(_ sdk.Context, key []byte, value interface{}) {
|
|
|
|
bz, err := json.Marshal(value)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ps.db.Set(key, bz)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *paramStore) Has(_ sdk.Context, key []byte) bool {
|
|
|
|
ok, err := ps.db.Has(key)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ps *paramStore) Get(_ sdk.Context, key []byte, ptr interface{}) {
|
|
|
|
bz, err := ps.db.Get(key)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(bz) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(bz, ptr); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 17:15:38 -08:00
|
|
|
func defaultLogger() log.Logger {
|
|
|
|
return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
|
|
|
}
|
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
func newBaseApp(name string, options ...func(*BaseApp)) *BaseApp {
|
2018-02-16 17:15:38 -08:00
|
|
|
logger := defaultLogger()
|
|
|
|
db := dbm.NewMemDB()
|
2018-09-13 11:17:32 -07:00
|
|
|
codec := codec.New()
|
2018-07-06 07:47:07 -07:00
|
|
|
registerTestCodec(codec)
|
2018-07-31 21:23:25 -07:00
|
|
|
return NewBaseApp(name, logger, db, testTxDecoder(codec), options...)
|
2018-02-16 17:15:38 -08:00
|
|
|
}
|
|
|
|
|
2018-09-13 11:17:32 -07:00
|
|
|
func registerTestCodec(cdc *codec.Codec) {
|
2018-07-06 07:47:07 -07:00
|
|
|
// register Tx, Msg
|
2018-09-13 11:17:32 -07:00
|
|
|
sdk.RegisterCodec(cdc)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// register test types
|
|
|
|
cdc.RegisterConcrete(&txTest{}, "cosmos-sdk/baseapp/txTest", nil)
|
|
|
|
cdc.RegisterConcrete(&msgCounter{}, "cosmos-sdk/baseapp/msgCounter", nil)
|
|
|
|
cdc.RegisterConcrete(&msgCounter2{}, "cosmos-sdk/baseapp/msgCounter2", nil)
|
|
|
|
cdc.RegisterConcrete(&msgNoRoute{}, "cosmos-sdk/baseapp/msgNoRoute", nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// simple one store baseapp
|
2018-07-31 21:23:25 -07:00
|
|
|
func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp {
|
|
|
|
app := newBaseApp(t.Name(), options...)
|
2018-07-06 07:47:07 -07:00
|
|
|
require.Equal(t, t.Name(), app.Name())
|
|
|
|
|
2018-11-27 00:14:22 -08:00
|
|
|
app.MountStores(capKey1, capKey2)
|
2020-04-16 08:10:39 -07:00
|
|
|
app.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
2018-02-16 16:52:07 -08:00
|
|
|
|
2018-02-27 19:23:56 -08:00
|
|
|
// stores are mounted
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Nil(t, err)
|
2018-07-31 21:23:25 -07:00
|
|
|
return app
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestMountStores(t *testing.T) {
|
2018-07-31 21:23:25 -07:00
|
|
|
app := setupBaseApp(t)
|
2018-02-27 19:23:56 -08:00
|
|
|
|
|
|
|
// check both stores
|
|
|
|
store1 := app.cms.GetCommitKVStore(capKey1)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.NotNil(t, store1)
|
2018-02-27 19:23:56 -08:00
|
|
|
store2 := app.cms.GetCommitKVStore(capKey2)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.NotNil(t, store2)
|
2018-02-16 16:52:07 -08:00
|
|
|
}
|
2018-02-26 02:59:48 -08:00
|
|
|
|
2018-02-19 10:02:04 -08:00
|
|
|
// Test that we can make commits and then reload old versions.
|
|
|
|
// Test that LoadLatestVersion actually does.
|
2018-02-16 16:52:07 -08:00
|
|
|
func TestLoadVersion(t *testing.T) {
|
2018-02-27 19:23:56 -08:00
|
|
|
logger := defaultLogger()
|
2020-02-06 12:58:32 -08:00
|
|
|
pruningOpt := SetPruning(store.PruneNothing)
|
2018-02-27 19:23:56 -08:00
|
|
|
db := dbm.NewMemDB()
|
|
|
|
name := t.Name()
|
2019-01-09 07:06:22 -08:00
|
|
|
app := NewBaseApp(name, logger, db, nil, pruningOpt)
|
2018-02-27 19:23:56 -08:00
|
|
|
|
|
|
|
// make a cap key and mount the store
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion() // needed to make stores non-nil
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Nil(t, err)
|
2018-02-27 19:23:56 -08:00
|
|
|
|
|
|
|
emptyCommitID := sdk.CommitID{}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// fresh store has zero/empty last commit
|
2018-02-27 19:23:56 -08:00
|
|
|
lastHeight := app.LastBlockHeight()
|
|
|
|
lastID := app.LastCommitID()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, int64(0), lastHeight)
|
|
|
|
require.Equal(t, emptyCommitID, lastID)
|
2018-02-27 19:23:56 -08:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// execute a block, collect commit ID
|
2018-02-27 19:23:56 -08:00
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
res := app.Commit()
|
2019-09-16 10:11:17 -07:00
|
|
|
commitID1 := sdk.CommitID{Version: 1, Hash: res.Data}
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// execute a block, collect commit ID
|
2018-06-04 21:55:02 -07:00
|
|
|
header = abci.Header{Height: 2}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
res = app.Commit()
|
2019-09-16 10:11:17 -07:00
|
|
|
commitID2 := sdk.CommitID{Version: 2, Hash: res.Data}
|
2018-02-27 19:23:56 -08:00
|
|
|
|
2018-06-04 21:55:02 -07:00
|
|
|
// reload with LoadLatestVersion
|
2019-01-09 07:06:22 -08:00
|
|
|
app = NewBaseApp(name, logger, db, nil, pruningOpt)
|
2020-04-16 08:10:39 -07:00
|
|
|
app.MountStores()
|
|
|
|
err = app.LoadLatestVersion()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Nil(t, err)
|
2018-06-04 21:55:02 -07:00
|
|
|
testLoadVersionHelper(t, app, int64(2), commitID2)
|
|
|
|
|
|
|
|
// reload with LoadVersion, see if you can commit the same block and get
|
|
|
|
// the same result
|
2019-01-09 07:06:22 -08:00
|
|
|
app = NewBaseApp(name, logger, db, nil, pruningOpt)
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadVersion(1)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Nil(t, err)
|
2018-06-04 21:55:02 -07:00
|
|
|
testLoadVersionHelper(t, app, int64(1), commitID1)
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
app.Commit()
|
|
|
|
testLoadVersionHelper(t, app, int64(2), commitID2)
|
|
|
|
}
|
2018-02-27 19:23:56 -08:00
|
|
|
|
2019-08-06 05:59:22 -07:00
|
|
|
func useDefaultLoader(app *BaseApp) {
|
|
|
|
app.SetStoreLoader(DefaultStoreLoader)
|
|
|
|
}
|
|
|
|
|
|
|
|
func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) {
|
|
|
|
rs := rootmulti.NewStore(db)
|
2020-01-22 11:52:56 -08:00
|
|
|
rs.SetPruning(store.PruneNothing)
|
2019-08-06 05:59:22 -07:00
|
|
|
key := sdk.NewKVStoreKey(storeKey)
|
|
|
|
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
|
|
|
|
err := rs.LoadLatestVersion()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, int64(0), rs.LastCommitID().Version)
|
|
|
|
|
|
|
|
// write some data in substore
|
|
|
|
kv, _ := rs.GetStore(key).(store.KVStore)
|
|
|
|
require.NotNil(t, kv)
|
|
|
|
kv.Set(k, v)
|
|
|
|
commitID := rs.Commit()
|
|
|
|
require.Equal(t, int64(1), commitID.Version)
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkStore(t *testing.T, db dbm.DB, ver int64, storeKey string, k, v []byte) {
|
|
|
|
rs := rootmulti.NewStore(db)
|
2020-06-22 13:31:33 -07:00
|
|
|
rs.SetPruning(store.PruneDefault)
|
2019-08-06 05:59:22 -07:00
|
|
|
key := sdk.NewKVStoreKey(storeKey)
|
|
|
|
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
|
|
|
|
err := rs.LoadLatestVersion()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, ver, rs.LastCommitID().Version)
|
|
|
|
|
|
|
|
// query data in substore
|
|
|
|
kv, _ := rs.GetStore(key).(store.KVStore)
|
|
|
|
require.NotNil(t, kv)
|
|
|
|
require.Equal(t, v, kv.Get(k))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we can make commits and then reload old versions.
|
|
|
|
// Test that LoadLatestVersion actually does.
|
|
|
|
func TestSetLoader(t *testing.T) {
|
|
|
|
cases := map[string]struct {
|
|
|
|
setLoader func(*BaseApp)
|
|
|
|
origStoreKey string
|
|
|
|
loadStoreKey string
|
|
|
|
}{
|
|
|
|
"don't set loader": {
|
|
|
|
origStoreKey: "foo",
|
|
|
|
loadStoreKey: "foo",
|
|
|
|
},
|
|
|
|
"default loader": {
|
|
|
|
setLoader: useDefaultLoader,
|
|
|
|
origStoreKey: "foo",
|
|
|
|
loadStoreKey: "foo",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
k := []byte("key")
|
|
|
|
v := []byte("value")
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
2019-10-17 06:47:35 -07:00
|
|
|
tc := tc
|
2019-08-06 05:59:22 -07:00
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// prepare a db with some data
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
initStore(t, db, tc.origStoreKey, k, v)
|
|
|
|
|
|
|
|
// load the app with the existing db
|
2020-01-22 11:52:56 -08:00
|
|
|
opts := []func(*BaseApp){SetPruning(store.PruneNothing)}
|
2019-08-06 05:59:22 -07:00
|
|
|
if tc.setLoader != nil {
|
|
|
|
opts = append(opts, tc.setLoader)
|
|
|
|
}
|
|
|
|
app := NewBaseApp(t.Name(), defaultLogger(), db, nil, opts...)
|
|
|
|
app.MountStores(sdk.NewKVStoreKey(tc.loadStoreKey))
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion()
|
2019-08-06 05:59:22 -07:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
// "execute" one block
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}})
|
|
|
|
res := app.Commit()
|
|
|
|
require.NotNil(t, res.Data)
|
|
|
|
|
|
|
|
// check db is properly updated
|
|
|
|
checkStore(t, db, 2, tc.loadStoreKey, k, v)
|
|
|
|
checkStore(t, db, 2, tc.loadStoreKey, []byte("foo"), nil)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-02 12:37:44 -07:00
|
|
|
func TestAppVersionSetterGetter(t *testing.T) {
|
|
|
|
logger := defaultLogger()
|
2020-06-22 13:31:33 -07:00
|
|
|
pruningOpt := SetPruning(store.PruneDefault)
|
2019-05-02 12:37:44 -07:00
|
|
|
db := dbm.NewMemDB()
|
|
|
|
name := t.Name()
|
|
|
|
app := NewBaseApp(name, logger, db, nil, pruningOpt)
|
|
|
|
|
|
|
|
require.Equal(t, "", app.AppVersion())
|
|
|
|
res := app.Query(abci.RequestQuery{Path: "app/version"})
|
|
|
|
require.True(t, res.IsOK())
|
|
|
|
require.Equal(t, "", string(res.Value))
|
|
|
|
|
|
|
|
versionString := "1.0.0"
|
|
|
|
app.SetAppVersion(versionString)
|
|
|
|
require.Equal(t, versionString, app.AppVersion())
|
|
|
|
res = app.Query(abci.RequestQuery{Path: "app/version"})
|
|
|
|
require.True(t, res.IsOK())
|
|
|
|
require.Equal(t, versionString, string(res.Value))
|
|
|
|
}
|
|
|
|
|
2019-02-05 19:11:57 -08:00
|
|
|
func TestLoadVersionInvalid(t *testing.T) {
|
|
|
|
logger := log.NewNopLogger()
|
2020-02-06 12:58:32 -08:00
|
|
|
pruningOpt := SetPruning(store.PruneNothing)
|
2019-02-05 19:11:57 -08:00
|
|
|
db := dbm.NewMemDB()
|
|
|
|
name := t.Name()
|
|
|
|
app := NewBaseApp(name, logger, db, nil, pruningOpt)
|
|
|
|
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion()
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
// require error when loading an invalid version
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadVersion(-1)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
res := app.Commit()
|
2019-09-16 10:11:17 -07:00
|
|
|
commitID1 := sdk.CommitID{Version: 1, Hash: res.Data}
|
2019-02-05 19:11:57 -08:00
|
|
|
|
|
|
|
// create a new app with the stores mounted under the same cap key
|
|
|
|
app = NewBaseApp(name, logger, db, nil, pruningOpt)
|
|
|
|
|
|
|
|
// require we can load the latest version
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadVersion(1)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Nil(t, err)
|
|
|
|
testLoadVersionHelper(t, app, int64(1), commitID1)
|
|
|
|
|
|
|
|
// require error when loading an invalid version
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadVersion(2)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2020-02-06 12:58:32 -08:00
|
|
|
func TestLoadVersionPruning(t *testing.T) {
|
|
|
|
logger := log.NewNopLogger()
|
|
|
|
pruningOptions := store.PruningOptions{
|
2020-06-22 13:31:33 -07:00
|
|
|
KeepRecent: 2,
|
|
|
|
KeepEvery: 3,
|
|
|
|
Interval: 1,
|
2020-02-06 12:58:32 -08:00
|
|
|
}
|
|
|
|
pruningOpt := SetPruning(pruningOptions)
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
name := t.Name()
|
|
|
|
app := NewBaseApp(name, logger, db, nil, pruningOpt)
|
|
|
|
|
|
|
|
// make a cap key and mount the store
|
2020-04-16 08:10:39 -07:00
|
|
|
capKey := sdk.NewKVStoreKey("key1")
|
2020-02-06 12:58:32 -08:00
|
|
|
app.MountStores(capKey)
|
2020-04-16 08:10:39 -07:00
|
|
|
|
|
|
|
err := app.LoadLatestVersion() // needed to make stores non-nil
|
2020-02-06 12:58:32 -08:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
emptyCommitID := sdk.CommitID{}
|
|
|
|
|
|
|
|
// fresh store has zero/empty last commit
|
|
|
|
lastHeight := app.LastBlockHeight()
|
|
|
|
lastID := app.LastCommitID()
|
|
|
|
require.Equal(t, int64(0), lastHeight)
|
|
|
|
require.Equal(t, emptyCommitID, lastID)
|
|
|
|
|
2020-06-22 13:31:33 -07:00
|
|
|
var lastCommitID sdk.CommitID
|
2020-02-06 12:58:32 -08:00
|
|
|
|
2020-06-22 13:31:33 -07:00
|
|
|
// Commit seven blocks, of which 7 (latest) is kept in addition to 6, 5
|
|
|
|
// (keep recent) and 3 (keep every).
|
|
|
|
for i := int64(1); i <= 7; i++ {
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: i}})
|
|
|
|
res := app.Commit()
|
|
|
|
lastCommitID = sdk.CommitID{Version: i, Hash: res.Data}
|
|
|
|
}
|
2020-02-06 12:58:32 -08:00
|
|
|
|
2020-06-22 13:31:33 -07:00
|
|
|
for _, v := range []int64{1, 2, 4} {
|
|
|
|
_, err = app.cms.CacheMultiStoreWithVersion(v)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
2020-02-06 12:58:32 -08:00
|
|
|
|
2020-06-22 13:31:33 -07:00
|
|
|
for _, v := range []int64{3, 5, 6, 7} {
|
|
|
|
_, err = app.cms.CacheMultiStoreWithVersion(v)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
2020-02-06 12:58:32 -08:00
|
|
|
|
2020-06-22 13:31:33 -07:00
|
|
|
// reload with LoadLatestVersion, check it loads last version
|
2020-02-06 12:58:32 -08:00
|
|
|
app = NewBaseApp(name, logger, db, nil, pruningOpt)
|
|
|
|
app.MountStores(capKey)
|
2020-06-22 13:31:33 -07:00
|
|
|
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadLatestVersion()
|
2020-02-06 12:58:32 -08:00
|
|
|
require.Nil(t, err)
|
2020-06-22 13:31:33 -07:00
|
|
|
testLoadVersionHelper(t, app, int64(7), lastCommitID)
|
2020-02-06 12:58:32 -08:00
|
|
|
}
|
|
|
|
|
2018-06-04 21:55:02 -07:00
|
|
|
func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, expectedID sdk.CommitID) {
|
|
|
|
lastHeight := app.LastBlockHeight()
|
|
|
|
lastID := app.LastCommitID()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, expectedHeight, lastHeight)
|
|
|
|
require.Equal(t, expectedID, lastID)
|
2018-02-17 16:13:22 -08:00
|
|
|
}
|
|
|
|
|
2018-07-10 12:10:59 -07:00
|
|
|
func TestOptionFunction(t *testing.T) {
|
|
|
|
logger := defaultLogger()
|
|
|
|
db := dbm.NewMemDB()
|
2018-07-18 16:24:16 -07:00
|
|
|
bap := NewBaseApp("starting name", logger, db, nil, testChangeNameHelper("new name"))
|
2018-07-10 12:10:59 -07:00
|
|
|
require.Equal(t, bap.name, "new name", "BaseApp should have had name changed via option function")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testChangeNameHelper(name string) func(*BaseApp) {
|
|
|
|
return func(bap *BaseApp) {
|
|
|
|
bap.name = name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-19 10:02:04 -08:00
|
|
|
// Test that txs can be unmarshalled and read and that
|
|
|
|
// correct error codes are returned when not
|
2018-02-17 16:13:22 -08:00
|
|
|
func TestTxDecoder(t *testing.T) {
|
2019-02-05 19:11:57 -08:00
|
|
|
codec := codec.New()
|
|
|
|
registerTestCodec(codec)
|
|
|
|
|
|
|
|
app := newBaseApp(t.Name())
|
|
|
|
tx := newTxCounter(1, 0)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes := codec.MustMarshalBinaryBare(tx)
|
2019-02-05 19:11:57 -08:00
|
|
|
|
|
|
|
dTx, err := app.txDecoder(txBytes)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
cTx := dTx.(txTest)
|
|
|
|
require.Equal(t, tx.Counter, cTx.Counter)
|
2018-02-17 16:13:22 -08:00
|
|
|
}
|
|
|
|
|
2018-02-19 10:02:04 -08:00
|
|
|
// Test that Info returns the latest committed state.
|
2018-02-17 16:13:22 -08:00
|
|
|
func TestInfo(t *testing.T) {
|
2018-02-19 10:02:04 -08:00
|
|
|
app := newBaseApp(t.Name())
|
|
|
|
|
|
|
|
// ----- test an empty response -------
|
|
|
|
reqInfo := abci.RequestInfo{}
|
|
|
|
res := app.Info(reqInfo)
|
|
|
|
|
|
|
|
// should be empty
|
|
|
|
assert.Equal(t, "", res.Version)
|
2018-02-26 02:59:48 -08:00
|
|
|
assert.Equal(t, t.Name(), res.GetData())
|
2018-02-19 10:02:04 -08:00
|
|
|
assert.Equal(t, int64(0), res.LastBlockHeight)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, []uint8(nil), res.LastBlockAppHash)
|
2018-02-19 10:02:04 -08:00
|
|
|
|
|
|
|
// ----- test a proper response -------
|
2018-02-17 16:13:22 -08:00
|
|
|
// TODO
|
2018-02-16 16:52:07 -08:00
|
|
|
}
|
|
|
|
|
2019-02-05 19:11:57 -08:00
|
|
|
func TestBaseAppOptionSeal(t *testing.T) {
|
|
|
|
app := setupBaseApp(t)
|
|
|
|
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetName("")
|
|
|
|
})
|
2019-05-02 12:37:44 -07:00
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetAppVersion("")
|
|
|
|
})
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetDB(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetCMS(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetInitChainer(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetBeginBlocker(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetEndBlocker(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetAnteHandler(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetAddrPeerFilter(nil)
|
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
2019-02-07 17:52:24 -08:00
|
|
|
app.SetIDPeerFilter(nil)
|
2019-02-05 19:11:57 -08:00
|
|
|
})
|
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetFauxMerkleMode()
|
|
|
|
})
|
2020-01-04 11:50:38 -08:00
|
|
|
require.Panics(t, func() {
|
|
|
|
app.SetRouter(NewRouter())
|
|
|
|
})
|
2019-02-05 19:11:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetMinGasPrices(t *testing.T) {
|
2019-02-15 07:33:23 -08:00
|
|
|
minGasPrices := sdk.DecCoins{sdk.NewInt64DecCoin("stake", 5000)}
|
2019-02-05 19:11:57 -08:00
|
|
|
app := newBaseApp(t.Name(), SetMinGasPrices(minGasPrices.String()))
|
|
|
|
require.Equal(t, minGasPrices, app.minGasPrices)
|
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-02-16 17:58:51 -08:00
|
|
|
func TestInitChainer(t *testing.T) {
|
2018-02-28 23:00:44 -08:00
|
|
|
name := t.Name()
|
2018-07-06 07:47:07 -07:00
|
|
|
// keep the db and logger ourselves so
|
|
|
|
// we can reload the same app later
|
2018-03-29 11:44:56 -07:00
|
|
|
db := dbm.NewMemDB()
|
|
|
|
logger := defaultLogger()
|
2018-07-18 16:24:16 -07:00
|
|
|
app := NewBaseApp(name, logger, db, nil)
|
2020-04-16 08:10:39 -07:00
|
|
|
capKey := sdk.NewKVStoreKey("main")
|
2018-03-29 11:44:56 -07:00
|
|
|
capKey2 := sdk.NewKVStoreKey("key2")
|
2018-11-27 00:14:22 -08:00
|
|
|
app.MountStores(capKey, capKey2)
|
2018-02-16 17:58:51 -08:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// set a value in the store on init chain
|
2018-02-16 17:58:51 -08:00
|
|
|
key, value := []byte("hello"), []byte("goodbye")
|
2018-02-17 15:10:55 -08:00
|
|
|
var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
2018-02-16 17:58:51 -08:00
|
|
|
store := ctx.KVStore(capKey)
|
|
|
|
store.Set(key, value)
|
2018-02-17 15:10:55 -08:00
|
|
|
return abci.ResponseInitChain{}
|
2018-02-16 17:58:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
query := abci.RequestQuery{
|
2018-05-10 11:20:34 -07:00
|
|
|
Path: "/store/main/key",
|
2018-02-16 17:58:51 -08:00
|
|
|
Data: key,
|
|
|
|
}
|
|
|
|
|
|
|
|
// initChainer is nil - nothing happens
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
res := app.Query(query)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, 0, len(res.Value))
|
2018-02-16 17:58:51 -08:00
|
|
|
|
|
|
|
// set initChainer and try again - should see the value
|
|
|
|
app.SetInitChainer(initChainer)
|
2018-07-31 21:23:25 -07:00
|
|
|
|
|
|
|
// stores are mounted and private members are set - sealing baseapp
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion() // needed to make stores non-nil
|
2018-07-31 21:23:25 -07:00
|
|
|
require.Nil(t, err)
|
2019-03-07 21:52:19 -08:00
|
|
|
require.Equal(t, int64(0), app.LastBlockHeight())
|
2018-07-31 21:23:25 -07:00
|
|
|
|
2018-06-27 15:45:10 -07:00
|
|
|
app.InitChain(abci.RequestInitChain{AppStateBytes: []byte("{}"), ChainId: "test-chain-id"}) // must have valid JSON genesis file, even if empty
|
|
|
|
|
|
|
|
// assert that chainID is set correctly in InitChain
|
|
|
|
chainID := app.deliverState.ctx.ChainID()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, "test-chain-id", chainID, "ChainID in deliverState not set correctly in InitChain")
|
2018-06-27 15:45:10 -07:00
|
|
|
|
|
|
|
chainID = app.checkState.ctx.ChainID()
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, "test-chain-id", chainID, "ChainID in checkState not set correctly in InitChain")
|
2018-06-27 15:45:10 -07:00
|
|
|
|
2018-02-27 20:07:54 -08:00
|
|
|
app.Commit()
|
2018-02-16 17:58:51 -08:00
|
|
|
res = app.Query(query)
|
2019-03-07 21:52:19 -08:00
|
|
|
require.Equal(t, int64(1), app.LastBlockHeight())
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, value, res.Value)
|
2018-02-28 23:00:44 -08:00
|
|
|
|
|
|
|
// reload app
|
2018-07-18 16:24:16 -07:00
|
|
|
app = NewBaseApp(name, logger, db, nil)
|
2018-07-31 21:23:25 -07:00
|
|
|
app.SetInitChainer(initChainer)
|
2018-11-27 00:14:22 -08:00
|
|
|
app.MountStores(capKey, capKey2)
|
2020-04-16 08:10:39 -07:00
|
|
|
err = app.LoadLatestVersion() // needed to make stores non-nil
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Nil(t, err)
|
2019-03-07 21:52:19 -08:00
|
|
|
require.Equal(t, int64(1), app.LastBlockHeight())
|
2018-02-28 23:00:44 -08:00
|
|
|
|
|
|
|
// ensure we can still query after reloading
|
|
|
|
res = app.Query(query)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, value, res.Value)
|
2018-02-28 23:00:44 -08:00
|
|
|
|
|
|
|
// commit and ensure we can still query
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-02-28 23:00:44 -08:00
|
|
|
app.Commit()
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2018-02-28 23:00:44 -08:00
|
|
|
res = app.Query(query)
|
2018-06-29 18:10:15 -07:00
|
|
|
require.Equal(t, value, res.Value)
|
2018-02-16 16:52:07 -08:00
|
|
|
}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Simple tx with a list of Msgs.
|
|
|
|
type txTest struct {
|
2018-11-16 10:33:47 -08:00
|
|
|
Msgs []sdk.Msg
|
|
|
|
Counter int64
|
|
|
|
FailOnAnte bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *txTest) setFailOnAnte(fail bool) {
|
|
|
|
tx.FailOnAnte = fail
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tx *txTest) setFailOnHandler(fail bool) {
|
|
|
|
for i, msg := range tx.Msgs {
|
|
|
|
tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail}
|
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2018-06-04 21:55:02 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Implements Tx
|
2019-12-27 09:57:54 -08:00
|
|
|
func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs }
|
|
|
|
func (tx txTest) ValidateBasic() error { return nil }
|
2018-06-04 21:55:02 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
const (
|
2018-10-23 12:23:55 -07:00
|
|
|
routeMsgCounter = "msgCounter"
|
|
|
|
routeMsgCounter2 = "msgCounter2"
|
2018-07-06 07:47:07 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// ValidateBasic() fails on negative counters.
|
|
|
|
// Otherwise it's up to the handlers
|
|
|
|
type msgCounter struct {
|
2018-11-16 10:33:47 -08:00
|
|
|
Counter int64
|
|
|
|
FailOnHandler bool
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
2020-06-03 12:52:05 -07:00
|
|
|
// dummy implementation of proto.Message
|
|
|
|
func (msg msgCounter) Reset() {}
|
|
|
|
func (msg msgCounter) String() string { return "TODO" }
|
|
|
|
func (msg msgCounter) ProtoMessage() {}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Implements Msg
|
2018-10-23 12:23:55 -07:00
|
|
|
func (msg msgCounter) Route() string { return routeMsgCounter }
|
|
|
|
func (msg msgCounter) Type() string { return "counter1" }
|
2018-07-09 01:47:38 -07:00
|
|
|
func (msg msgCounter) GetSignBytes() []byte { return nil }
|
|
|
|
func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil }
|
2019-12-27 09:57:54 -08:00
|
|
|
func (msg msgCounter) ValidateBasic() error {
|
2018-07-06 07:47:07 -07:00
|
|
|
if msg.Counter >= 0 {
|
|
|
|
return nil
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer")
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
func newTxCounter(counter int64, msgCounters ...int64) *txTest {
|
|
|
|
msgs := make([]sdk.Msg, 0, len(msgCounters))
|
|
|
|
for _, c := range msgCounters {
|
|
|
|
msgs = append(msgs, msgCounter{c, false})
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
|
|
|
|
return &txTest{msgs, counter, false}
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// a msg we dont know how to route
|
|
|
|
type msgNoRoute struct {
|
|
|
|
msgCounter
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:23:55 -07:00
|
|
|
func (tx msgNoRoute) Route() string { return "noroute" }
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// a msg we dont know how to decode
|
|
|
|
type msgNoDecode struct {
|
|
|
|
msgCounter
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:23:55 -07:00
|
|
|
func (tx msgNoDecode) Route() string { return routeMsgCounter }
|
2018-06-04 21:55:02 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Another counter msg. Duplicate of msgCounter
|
|
|
|
type msgCounter2 struct {
|
|
|
|
Counter int64
|
|
|
|
}
|
|
|
|
|
2020-06-03 12:52:05 -07:00
|
|
|
// dummy implementation of proto.Message
|
|
|
|
func (msg msgCounter2) Reset() {}
|
|
|
|
func (msg msgCounter2) String() string { return "TODO" }
|
|
|
|
func (msg msgCounter2) ProtoMessage() {}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Implements Msg
|
2018-10-23 12:23:55 -07:00
|
|
|
func (msg msgCounter2) Route() string { return routeMsgCounter2 }
|
|
|
|
func (msg msgCounter2) Type() string { return "counter2" }
|
2018-07-09 01:47:38 -07:00
|
|
|
func (msg msgCounter2) GetSignBytes() []byte { return nil }
|
2018-07-06 00:06:53 -07:00
|
|
|
func (msg msgCounter2) GetSigners() []sdk.AccAddress { return nil }
|
2019-12-27 09:57:54 -08:00
|
|
|
func (msg msgCounter2) ValidateBasic() error {
|
2018-07-06 07:47:07 -07:00
|
|
|
if msg.Counter >= 0 {
|
2018-06-04 21:55:02 -07:00
|
|
|
return nil
|
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer")
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// amino decode
|
2018-09-13 11:17:32 -07:00
|
|
|
func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
|
2019-12-27 09:57:54 -08:00
|
|
|
return func(txBytes []byte) (sdk.Tx, error) {
|
2018-07-06 07:47:07 -07:00
|
|
|
var tx txTest
|
|
|
|
if len(txBytes) == 0 {
|
2019-12-27 09:57:54 -08:00
|
|
|
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty")
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
err := cdc.UnmarshalBinaryBare(txBytes, &tx)
|
2018-07-06 07:47:07 -07:00
|
|
|
if err != nil {
|
2019-12-27 09:57:54 -08:00
|
|
|
return nil, sdkerrors.ErrTxDecode
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
return tx, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-17 06:47:35 -07:00
|
|
|
func anteHandlerTxTest(t *testing.T, capKey sdk.StoreKey, storeKey []byte) sdk.AnteHandler {
|
2020-06-01 21:26:13 -07:00
|
|
|
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
|
|
|
|
store := ctx.KVStore(capKey)
|
2018-11-16 10:33:47 -08:00
|
|
|
txTest := tx.(txTest)
|
|
|
|
|
|
|
|
if txTest.FailOnAnte {
|
2020-06-01 21:26:13 -07:00
|
|
|
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure")
|
2018-11-16 10:33:47 -08:00
|
|
|
}
|
|
|
|
|
2020-06-01 21:26:13 -07:00
|
|
|
_, err := incrementingCounter(t, store, storeKey, txTest.Counter)
|
2019-12-27 09:57:54 -08:00
|
|
|
if err != nil {
|
2020-06-01 21:26:13 -07:00
|
|
|
return ctx, err
|
2019-10-10 05:46:09 -07:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2020-06-01 21:26:13 -07:00
|
|
|
ctx.EventManager().EmitEvents(
|
2020-05-11 15:23:41 -07:00
|
|
|
counterEvent("ante_handler", txTest.Counter),
|
|
|
|
)
|
|
|
|
|
2020-06-01 21:26:13 -07:00
|
|
|
return ctx, nil
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 15:23:41 -07:00
|
|
|
func counterEvent(evType string, msgCount int64) sdk.Events {
|
|
|
|
return sdk.Events{
|
|
|
|
sdk.NewEvent(
|
|
|
|
evType,
|
|
|
|
sdk.NewAttribute("update_counter", fmt.Sprintf("%d", msgCount)),
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-17 06:47:35 -07:00
|
|
|
func handlerMsgCounter(t *testing.T, capKey sdk.StoreKey, deliverKey []byte) sdk.Handler {
|
2019-12-27 09:57:54 -08:00
|
|
|
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2020-05-11 15:23:41 -07:00
|
|
|
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
2018-07-06 07:47:07 -07:00
|
|
|
store := ctx.KVStore(capKey)
|
|
|
|
var msgCount int64
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
switch m := msg.(type) {
|
|
|
|
case *msgCounter:
|
2018-11-16 10:33:47 -08:00
|
|
|
if m.FailOnHandler {
|
2019-12-27 09:57:54 -08:00
|
|
|
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "message handler failure")
|
2018-11-16 10:33:47 -08:00
|
|
|
}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
msgCount = m.Counter
|
|
|
|
case *msgCounter2:
|
|
|
|
msgCount = m.Counter
|
|
|
|
}
|
2018-11-16 10:33:47 -08:00
|
|
|
|
2020-05-11 15:23:41 -07:00
|
|
|
ctx.EventManager().EmitEvents(
|
|
|
|
counterEvent(sdk.EventTypeMessage, msgCount),
|
|
|
|
)
|
|
|
|
|
|
|
|
res, err := incrementingCounter(t, store, deliverKey, msgCount)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
res.Events = ctx.EventManager().Events().ToABCIEvents()
|
|
|
|
return res, nil
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getIntFromStore(store sdk.KVStore, key []byte) int64 {
|
|
|
|
bz := store.Get(key)
|
|
|
|
if len(bz) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
i, err := binary.ReadVarint(bytes.NewBuffer(bz))
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
|
|
|
|
func setIntOnStore(store sdk.KVStore, key []byte, i int64) {
|
|
|
|
bz := make([]byte, 8)
|
|
|
|
n := binary.PutVarint(bz, i)
|
|
|
|
store.Set(key, bz[:n])
|
|
|
|
}
|
|
|
|
|
|
|
|
// check counter matches what's in store.
|
|
|
|
// increment and store
|
2019-12-27 09:57:54 -08:00
|
|
|
func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (*sdk.Result, error) {
|
2018-07-06 07:47:07 -07:00
|
|
|
storedCounter := getIntFromStore(store, counterKey)
|
|
|
|
require.Equal(t, storedCounter, counter)
|
|
|
|
setIntOnStore(store, counterKey, counter+1)
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
//---------------------------------------------------------------------
|
|
|
|
// Tx processing - CheckTx, DeliverTx, SimulateTx.
|
|
|
|
// These tests use the serialized tx as input, while most others will use the
|
|
|
|
// Check(), Deliver(), Simulate() methods directly.
|
|
|
|
// Ensure that Check/Deliver/Simulate work as expected with the store.
|
|
|
|
|
2018-02-19 10:02:04 -08:00
|
|
|
// Test that successive CheckTx can see each others' effects
|
2018-02-17 16:13:22 -08:00
|
|
|
// on the store within a block, and that the CheckTx state
|
2018-07-06 07:47:07 -07:00
|
|
|
// gets reset to the latest committed state during Commit
|
2018-02-17 16:13:22 -08:00
|
|
|
func TestCheckTx(t *testing.T) {
|
2018-07-06 07:47:07 -07:00
|
|
|
// This ante handler reads the key and checks that the value matches the current counter.
|
|
|
|
// This ensures changes to the kvstore persist across successive CheckTx.
|
|
|
|
counterKey := []byte("counter-key")
|
2018-06-04 21:55:02 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, counterKey)) }
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
|
|
|
// TODO: can remove this once CheckTx doesnt process msgs.
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2020-06-10 11:48:16 -07:00
|
|
|
}))
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
|
|
|
|
nTxs := int64(5)
|
2018-07-06 07:47:07 -07:00
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
|
2018-07-12 18:32:48 -07:00
|
|
|
// Create same codec used in txDecoder
|
2018-09-13 11:17:32 -07:00
|
|
|
codec := codec.New()
|
2018-07-12 18:32:48 -07:00
|
|
|
registerTestCodec(codec)
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
for i := int64(0); i < nTxs; i++ {
|
2020-05-11 15:23:41 -07:00
|
|
|
tx := newTxCounter(i, 0) // no messages
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := codec.MarshalBinaryBare(tx)
|
2018-07-06 07:47:07 -07:00
|
|
|
require.NoError(t, err)
|
2019-06-26 09:03:25 -07:00
|
|
|
r := app.CheckTx(abci.RequestCheckTx{Tx: txBytes})
|
2020-05-11 15:23:41 -07:00
|
|
|
require.Empty(t, r.GetEvents())
|
|
|
|
require.True(t, r.IsOK(), fmt.Sprintf("%v", r))
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
checkStateStore := app.checkState.ctx.KVStore(capKey1)
|
2018-07-06 07:47:07 -07:00
|
|
|
storedCounter := getIntFromStore(checkStateStore, counterKey)
|
|
|
|
|
|
|
|
// Ensure AnteHandler ran
|
|
|
|
require.Equal(t, nTxs, storedCounter)
|
|
|
|
|
|
|
|
// If a block is committed, CheckTx state should be reset.
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-06-04 21:55:02 -07:00
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
checkStateStore = app.checkState.ctx.KVStore(capKey1)
|
2018-07-06 07:47:07 -07:00
|
|
|
storedBytes := checkStateStore.Get(counterKey)
|
|
|
|
require.Nil(t, storedBytes)
|
2018-02-17 16:13:22 -08:00
|
|
|
}
|
|
|
|
|
2018-02-19 10:02:04 -08:00
|
|
|
// Test that successive DeliverTx can see each others' effects
|
2018-02-17 16:13:22 -08:00
|
|
|
// on the store, both within and across blocks.
|
|
|
|
func TestDeliverTx(t *testing.T) {
|
2018-07-06 07:47:07 -07:00
|
|
|
// test increments in the ante
|
|
|
|
anteKey := []byte("ante-key")
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) }
|
2018-02-17 16:13:22 -08:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// test increments in the handler
|
|
|
|
deliverKey := []byte("deliver-key")
|
2018-10-23 12:23:55 -07:00
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey))
|
|
|
|
bapp.Router().AddRoute(r)
|
2018-10-23 12:23:55 -07:00
|
|
|
}
|
2018-07-31 21:23:25 -07:00
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
2018-11-14 11:07:46 -08:00
|
|
|
app.InitChain(abci.RequestInitChain{})
|
2018-02-17 16:13:22 -08:00
|
|
|
|
2018-07-12 18:32:48 -07:00
|
|
|
// Create same codec used in txDecoder
|
2018-09-13 11:17:32 -07:00
|
|
|
codec := codec.New()
|
2018-07-12 18:32:48 -07:00
|
|
|
registerTestCodec(codec)
|
|
|
|
|
2018-02-17 16:13:22 -08:00
|
|
|
nBlocks := 3
|
2018-07-06 07:47:07 -07:00
|
|
|
txPerHeight := 5
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2018-02-17 16:13:22 -08:00
|
|
|
for blockN := 0; blockN < nBlocks; blockN++ {
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: int64(blockN) + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
|
2018-02-17 16:13:22 -08:00
|
|
|
for i := 0; i < txPerHeight; i++ {
|
2018-07-06 07:47:07 -07:00
|
|
|
counter := int64(blockN*txPerHeight + i)
|
|
|
|
tx := newTxCounter(counter, counter)
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := codec.MarshalBinaryBare(tx)
|
2018-07-06 07:47:07 -07:00
|
|
|
require.NoError(t, err)
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2018-07-06 07:47:07 -07:00
|
|
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
2020-05-11 15:23:41 -07:00
|
|
|
events := res.GetEvents()
|
|
|
|
require.Len(t, events, 3, "should contain ante handler, message type and counter events respectively")
|
|
|
|
require.Equal(t, counterEvent("ante_handler", counter).ToABCIEvents()[0], events[0], "ante handler event")
|
|
|
|
require.Equal(t, counterEvent(sdk.EventTypeMessage, counter).ToABCIEvents()[0], events[2], "msg handler update counter event")
|
2018-02-17 16:13:22 -08:00
|
|
|
}
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2018-02-17 16:13:22 -08:00
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Number of messages doesn't matter to CheckTx.
|
|
|
|
func TestMultiMsgCheckTx(t *testing.T) {
|
|
|
|
// TODO: ensure we get the same results
|
|
|
|
// with one message or many
|
|
|
|
}
|
2018-05-11 11:02:05 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// One call to DeliverTx should process all the messages, in order.
|
|
|
|
func TestMultiMsgDeliverTx(t *testing.T) {
|
|
|
|
// increment the tx counter
|
|
|
|
anteKey := []byte("ante-key")
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) }
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// increment the msg counter
|
|
|
|
deliverKey := []byte("deliver-key")
|
|
|
|
deliverKey2 := []byte("deliver-key2")
|
2018-07-31 21:23:25 -07:00
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r1 := sdk.NewRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey))
|
|
|
|
r2 := sdk.NewRoute(routeMsgCounter2, handlerMsgCounter(t, capKey1, deliverKey2))
|
|
|
|
bapp.Router().AddRoute(r1)
|
|
|
|
bapp.Router().AddRoute(r2)
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-07-12 18:32:48 -07:00
|
|
|
// Create same codec used in txDecoder
|
2018-09-13 11:17:32 -07:00
|
|
|
codec := codec.New()
|
2018-07-12 18:32:48 -07:00
|
|
|
registerTestCodec(codec)
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// run a multi-msg tx
|
2018-10-23 12:23:55 -07:00
|
|
|
// with all msgs the same route
|
2018-05-11 11:02:05 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
tx := newTxCounter(0, 0, 1, 2)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := codec.MarshalBinaryBare(tx)
|
2019-03-07 21:52:19 -08:00
|
|
|
require.NoError(t, err)
|
2019-06-26 09:03:25 -07:00
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2019-03-07 21:52:19 -08:00
|
|
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
store := app.deliverState.ctx.KVStore(capKey1)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
// tx counter only incremented once
|
|
|
|
txCounter := getIntFromStore(store, anteKey)
|
|
|
|
require.Equal(t, int64(1), txCounter)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
// msg counter incremented three times
|
|
|
|
msgCounter := getIntFromStore(store, deliverKey)
|
|
|
|
require.Equal(t, int64(3), msgCounter)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// replace the second message with a msgCounter2
|
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
tx = newTxCounter(1, 3)
|
|
|
|
tx.Msgs = append(tx.Msgs, msgCounter2{0})
|
|
|
|
tx.Msgs = append(tx.Msgs, msgCounter2{1})
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err = codec.MarshalBinaryBare(tx)
|
2019-03-07 21:52:19 -08:00
|
|
|
require.NoError(t, err)
|
2019-06-26 09:03:25 -07:00
|
|
|
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2019-03-07 21:52:19 -08:00
|
|
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
store = app.deliverState.ctx.KVStore(capKey1)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
// tx counter only incremented once
|
|
|
|
txCounter = getIntFromStore(store, anteKey)
|
|
|
|
require.Equal(t, int64(2), txCounter)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
// original counter increments by one
|
|
|
|
// new counter increments by two
|
|
|
|
msgCounter = getIntFromStore(store, deliverKey)
|
|
|
|
require.Equal(t, int64(4), msgCounter)
|
|
|
|
msgCounter2 := getIntFromStore(store, deliverKey2)
|
|
|
|
require.Equal(t, int64(2), msgCounter2)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Interleave calls to Check and Deliver and ensure
|
|
|
|
// that there is no cross-talk. Check sees results of the previous Check calls
|
|
|
|
// and Deliver sees that of the previous Deliver calls, but they don't see eachother.
|
|
|
|
func TestConcurrentCheckDeliver(t *testing.T) {
|
|
|
|
// TODO
|
|
|
|
}
|
2018-05-11 11:02:05 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
// Simulate a transaction that uses gas to compute the gas.
|
|
|
|
// Simulate() and Query("/app/simulate", txBytes) should give
|
|
|
|
// the same results.
|
|
|
|
func TestSimulateTx(t *testing.T) {
|
2018-11-19 09:13:45 -08:00
|
|
|
gasConsumed := uint64(5)
|
2018-05-11 11:02:05 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2018-07-31 21:23:25 -07:00
|
|
|
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasConsumed))
|
|
|
|
return
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2018-07-31 21:23:25 -07:00
|
|
|
ctx.GasMeter().ConsumeGas(gasConsumed, "test")
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2018-07-31 21:23:25 -07:00
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
|
2018-06-27 15:45:10 -07:00
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
|
2018-07-12 18:32:48 -07:00
|
|
|
// Create same codec used in txDecoder
|
2018-09-13 11:17:32 -07:00
|
|
|
cdc := codec.New()
|
|
|
|
registerTestCodec(cdc)
|
2018-07-12 18:32:48 -07:00
|
|
|
|
2018-05-11 11:02:05 -07:00
|
|
|
nBlocks := 3
|
|
|
|
for blockN := 0; blockN < nBlocks; blockN++ {
|
2018-07-06 07:47:07 -07:00
|
|
|
count := int64(blockN + 1)
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: count}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
tx := newTxCounter(count, count)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := cdc.MarshalBinaryBare(tx)
|
2019-02-04 15:35:12 -08:00
|
|
|
require.Nil(t, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// simulate a message, check gas reported
|
2019-12-27 09:57:54 -08:00
|
|
|
gInfo, result, err := app.Simulate(txBytes, tx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, result)
|
|
|
|
require.Equal(t, gasConsumed, gInfo.GasUsed)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// simulate again, same result
|
2019-12-27 09:57:54 -08:00
|
|
|
gInfo, result, err = app.Simulate(txBytes, tx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, result)
|
|
|
|
require.Equal(t, gasConsumed, gInfo.GasUsed)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// simulate by calling Query with encoded tx
|
2018-05-11 11:02:05 -07:00
|
|
|
query := abci.RequestQuery{
|
|
|
|
Path: "/app/simulate",
|
2018-07-06 07:47:07 -07:00
|
|
|
Data: txBytes,
|
2018-05-11 11:02:05 -07:00
|
|
|
}
|
|
|
|
queryResult := app.Query(query)
|
2018-07-06 07:47:07 -07:00
|
|
|
require.True(t, queryResult.IsOK(), queryResult.Log)
|
|
|
|
|
2020-03-19 16:03:49 -07:00
|
|
|
var simRes sdk.SimulationResponse
|
2020-03-26 09:50:39 -07:00
|
|
|
require.NoError(t, jsonpb.Unmarshal(strings.NewReader(string(queryResult.Value)), &simRes))
|
2020-03-24 15:00:22 -07:00
|
|
|
|
2020-03-19 16:03:49 -07:00
|
|
|
require.Equal(t, gInfo, simRes.GasInfo)
|
|
|
|
require.Equal(t, result.Log, simRes.Result.Log)
|
|
|
|
require.Equal(t, result.Events, simRes.Result.Events)
|
|
|
|
require.True(t, bytes.Equal(result.Data, simRes.Result.Data))
|
2020-03-24 15:00:22 -07:00
|
|
|
|
2018-05-11 11:02:05 -07:00
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-04 21:55:02 -07:00
|
|
|
func TestRunInvalidTransaction(t *testing.T) {
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2018-08-25 12:12:14 -07:00
|
|
|
return
|
|
|
|
})
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
2019-03-07 21:52:19 -08:00
|
|
|
|
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
// transaction with no messages
|
2018-07-06 07:47:07 -07:00
|
|
|
{
|
|
|
|
emptyTx := &txTest{}
|
2019-12-27 09:57:54 -08:00
|
|
|
_, result, err := app.Deliver(emptyTx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
|
|
|
space, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrInvalidRequest.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrInvalidRequest.ABCICode(), code, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
// transaction where ValidateBasic fails
|
2018-07-06 07:47:07 -07:00
|
|
|
{
|
|
|
|
testCases := []struct {
|
|
|
|
tx *txTest
|
|
|
|
fail bool
|
|
|
|
}{
|
|
|
|
{newTxCounter(0, 0), false},
|
|
|
|
{newTxCounter(-1, 0), false},
|
|
|
|
{newTxCounter(100, 100), false},
|
|
|
|
{newTxCounter(100, 5, 4, 3, 2, 1), false},
|
|
|
|
|
|
|
|
{newTxCounter(0, -1), true},
|
|
|
|
{newTxCounter(0, 1, -2), true},
|
|
|
|
{newTxCounter(0, 1, 2, -10, 5), true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
tx := testCase.tx
|
2019-12-27 09:57:54 -08:00
|
|
|
_, result, err := app.Deliver(tx)
|
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
if testCase.fail {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
space, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
} else {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.NotNil(t, result)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
// transaction with no known route
|
2018-07-06 07:47:07 -07:00
|
|
|
{
|
2018-11-16 10:33:47 -08:00
|
|
|
unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false}
|
2019-12-27 09:57:54 -08:00
|
|
|
_, result, err := app.Deliver(unknownRouteTx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
|
|
|
space, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-11-16 10:33:47 -08:00
|
|
|
unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false}
|
2019-12-27 09:57:54 -08:00
|
|
|
_, result, err = app.Deliver(unknownRouteTx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
|
|
|
space, code, _ = sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Transaction with an unregistered message
|
|
|
|
{
|
|
|
|
tx := newTxCounter(0, 0)
|
|
|
|
tx.Msgs = append(tx.Msgs, msgNoDecode{})
|
|
|
|
|
|
|
|
// new codec so we can encode the tx, but we shouldn't be able to decode
|
2018-09-13 11:17:32 -07:00
|
|
|
newCdc := codec.New()
|
2018-07-06 07:47:07 -07:00
|
|
|
registerTestCodec(newCdc)
|
|
|
|
newCdc.RegisterConcrete(&msgNoDecode{}, "cosmos-sdk/baseapp/msgNoDecode", nil)
|
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := newCdc.MarshalBinaryBare(tx)
|
2018-07-06 07:47:07 -07:00
|
|
|
require.NoError(t, err)
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2019-12-27 09:57:54 -08:00
|
|
|
require.EqualValues(t, sdkerrors.ErrTxDecode.ABCICode(), res.Code)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrTxDecode.Codespace(), res.Codespace)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2018-06-04 21:55:02 -07:00
|
|
|
}
|
|
|
|
|
2018-05-08 08:54:00 -07:00
|
|
|
// Test that transactions exceeding gas limits fail
|
|
|
|
func TestTxGasLimits(t *testing.T) {
|
2018-11-19 09:13:45 -08:00
|
|
|
gasGranted := uint64(10)
|
2018-07-31 21:23:25 -07:00
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2018-07-31 21:23:25 -07:00
|
|
|
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasGranted))
|
|
|
|
|
2019-10-10 05:46:09 -07:00
|
|
|
// AnteHandlers must have their own defer/recover in order for the BaseApp
|
|
|
|
// to know how much gas was used! This is because the GasMeter is created in
|
|
|
|
// the AnteHandler, but if it panics the context won't be set properly in
|
|
|
|
// runTx's recover call.
|
2018-07-31 21:23:25 -07:00
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
switch rType := r.(type) {
|
|
|
|
case sdk.ErrorOutOfGas:
|
2019-12-27 09:57:54 -08:00
|
|
|
err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor)
|
2018-07-31 21:23:25 -07:00
|
|
|
default:
|
|
|
|
panic(r)
|
|
|
|
}
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
2018-07-31 21:23:25 -07:00
|
|
|
}()
|
|
|
|
|
|
|
|
count := tx.(*txTest).Counter
|
2018-11-19 09:13:45 -08:00
|
|
|
newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante")
|
2019-10-10 05:46:09 -07:00
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
return newCtx, nil
|
2018-07-31 21:23:25 -07:00
|
|
|
})
|
2018-07-06 07:47:07 -07:00
|
|
|
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2018-07-31 21:23:25 -07:00
|
|
|
count := msg.(msgCounter).Counter
|
2018-11-19 09:13:45 -08:00
|
|
|
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2018-07-31 21:23:25 -07:00
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2018-07-31 21:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
2018-05-08 08:54:00 -07:00
|
|
|
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-05-08 08:54:00 -07:00
|
|
|
|
2018-07-06 07:47:07 -07:00
|
|
|
testCases := []struct {
|
|
|
|
tx *txTest
|
2018-11-19 09:13:45 -08:00
|
|
|
gasUsed uint64
|
2018-07-06 07:47:07 -07:00
|
|
|
fail bool
|
|
|
|
}{
|
|
|
|
{newTxCounter(0, 0), 0, false},
|
|
|
|
{newTxCounter(1, 1), 2, false},
|
|
|
|
{newTxCounter(9, 1), 10, false},
|
|
|
|
{newTxCounter(1, 9), 10, false},
|
|
|
|
{newTxCounter(10, 0), 10, false},
|
|
|
|
{newTxCounter(0, 10), 10, false},
|
|
|
|
{newTxCounter(0, 8, 2), 10, false},
|
|
|
|
{newTxCounter(0, 5, 1, 1, 1, 1, 1), 10, false},
|
|
|
|
{newTxCounter(0, 5, 1, 1, 1, 1), 9, false},
|
|
|
|
|
|
|
|
{newTxCounter(9, 2), 11, true},
|
|
|
|
{newTxCounter(2, 9), 11, true},
|
|
|
|
{newTxCounter(9, 1, 1), 11, true},
|
|
|
|
{newTxCounter(1, 8, 1, 1), 11, true},
|
|
|
|
{newTxCounter(11, 0), 11, true},
|
|
|
|
{newTxCounter(0, 11), 11, true},
|
|
|
|
{newTxCounter(0, 5, 11), 16, true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
|
|
|
tx := tc.tx
|
2019-12-27 09:57:54 -08:00
|
|
|
gInfo, result, err := app.Deliver(tx)
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// check gas used and wanted
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Equal(t, tc.gasUsed, gInfo.GasUsed, fmt.Sprintf("tc #%d; gas: %v, result: %v, err: %s", i, gInfo, result, err))
|
2018-07-06 07:47:07 -07:00
|
|
|
|
|
|
|
// check for out of gas
|
|
|
|
if !tc.fail {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.NotNil(t, result, fmt.Sprintf("%d: %v, %v", i, tc, err))
|
2018-07-06 07:47:07 -07:00
|
|
|
} else {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, result)
|
|
|
|
|
|
|
|
space, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err)
|
2018-07-06 07:47:07 -07:00
|
|
|
}
|
|
|
|
}
|
2018-05-08 08:54:00 -07:00
|
|
|
}
|
2018-11-13 12:12:04 -08:00
|
|
|
|
|
|
|
// Test that transactions exceeding gas limits fail
|
|
|
|
func TestMaxBlockGasLimits(t *testing.T) {
|
2018-11-20 13:16:44 -08:00
|
|
|
gasGranted := uint64(10)
|
2018-11-13 12:12:04 -08:00
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2018-11-13 12:12:04 -08:00
|
|
|
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasGranted))
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
switch rType := r.(type) {
|
|
|
|
case sdk.ErrorOutOfGas:
|
2019-10-10 05:46:09 -07:00
|
|
|
err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor)
|
2018-11-13 12:12:04 -08:00
|
|
|
default:
|
|
|
|
panic(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
count := tx.(*txTest).Counter
|
2018-11-20 13:16:44 -08:00
|
|
|
newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante")
|
2019-10-10 05:46:09 -07:00
|
|
|
|
2018-11-13 12:12:04 -08:00
|
|
|
return
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2018-11-13 12:12:04 -08:00
|
|
|
count := msg.(msgCounter).Counter
|
2018-11-20 13:16:44 -08:00
|
|
|
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2018-11-13 12:12:04 -08:00
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2018-11-13 12:12:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
2018-11-20 16:44:49 -08:00
|
|
|
app.InitChain(abci.RequestInitChain{
|
|
|
|
ConsensusParams: &abci.ConsensusParams{
|
2019-03-29 10:13:45 -07:00
|
|
|
Block: &abci.BlockParams{
|
2018-11-20 16:44:49 -08:00
|
|
|
MaxGas: 100,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2018-11-13 12:12:04 -08:00
|
|
|
|
|
|
|
testCases := []struct {
|
2018-11-13 13:01:00 -08:00
|
|
|
tx *txTest
|
|
|
|
numDelivers int
|
2018-11-20 13:16:44 -08:00
|
|
|
gasUsedPerDeliver uint64
|
2018-11-13 13:01:00 -08:00
|
|
|
fail bool
|
|
|
|
failAfterDeliver int
|
2018-11-13 12:12:04 -08:00
|
|
|
}{
|
2018-11-13 13:01:00 -08:00
|
|
|
{newTxCounter(0, 0), 0, 0, false, 0},
|
|
|
|
{newTxCounter(9, 1), 2, 10, false, 0},
|
|
|
|
{newTxCounter(10, 0), 3, 10, false, 0},
|
|
|
|
{newTxCounter(10, 0), 10, 10, false, 0},
|
|
|
|
{newTxCounter(2, 7), 11, 9, false, 0},
|
2018-11-21 21:36:12 -08:00
|
|
|
{newTxCounter(10, 0), 10, 10, false, 0}, // hit the limit but pass
|
2018-11-13 12:12:04 -08:00
|
|
|
|
2018-11-13 13:01:00 -08:00
|
|
|
{newTxCounter(10, 0), 11, 10, true, 10},
|
|
|
|
{newTxCounter(10, 0), 15, 10, true, 10},
|
2018-11-22 09:34:13 -08:00
|
|
|
{newTxCounter(9, 0), 12, 9, true, 11}, // fly past the limit
|
2018-11-13 12:12:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
|
|
|
tx := tc.tx
|
|
|
|
|
|
|
|
// reset the block gas
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-11-13 12:12:04 -08:00
|
|
|
|
|
|
|
// execute the transaction multiple times
|
2018-11-13 13:01:00 -08:00
|
|
|
for j := 0; j < tc.numDelivers; j++ {
|
2019-12-27 09:57:54 -08:00
|
|
|
_, result, err := app.Deliver(tx)
|
2018-11-13 12:12:04 -08:00
|
|
|
|
2018-11-20 23:02:15 -08:00
|
|
|
ctx := app.getState(runTxModeDeliver).ctx
|
2018-11-13 12:12:04 -08:00
|
|
|
|
2018-11-13 13:01:00 -08:00
|
|
|
// check for failed transactions
|
|
|
|
if tc.fail && (j+1) > tc.failAfterDeliver {
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Error(t, err, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err))
|
|
|
|
require.Nil(t, result, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err))
|
|
|
|
|
|
|
|
space, code, _ := sdkerrors.ABCIInfo(err, false)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err)
|
|
|
|
require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err)
|
2018-11-20 20:07:30 -08:00
|
|
|
require.True(t, ctx.BlockGasMeter().IsOutOfGas())
|
2018-11-13 13:01:00 -08:00
|
|
|
} else {
|
|
|
|
// check gas used and wanted
|
2019-12-27 09:57:54 -08:00
|
|
|
blockGasUsed := ctx.BlockGasMeter().GasConsumed()
|
2018-11-20 13:16:44 -08:00
|
|
|
expBlockGasUsed := tc.gasUsedPerDeliver * uint64(j+1)
|
2019-12-27 09:57:54 -08:00
|
|
|
require.Equal(
|
|
|
|
t, expBlockGasUsed, blockGasUsed,
|
|
|
|
fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, result),
|
|
|
|
)
|
2018-11-13 13:01:00 -08:00
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
require.NotNil(t, result, fmt.Sprintf("tc #%d; currDeliver: %d, result: %v, err: %s", i, j, result, err))
|
2018-11-20 20:07:30 -08:00
|
|
|
require.False(t, ctx.BlockGasMeter().IsPastLimit())
|
2018-11-13 13:01:00 -08:00
|
|
|
}
|
2018-11-13 12:12:04 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-19 23:58:33 -08:00
|
|
|
|
2020-06-05 09:48:18 -07:00
|
|
|
// Test custom panic handling within app.DeliverTx method
|
|
|
|
func TestCustomRunTxPanicHandler(t *testing.T) {
|
|
|
|
const customPanicMsg = "test panic"
|
|
|
|
anteErr := sdkerrors.Register("fakeModule", 100500, "fakeError")
|
|
|
|
|
|
|
|
anteOpt := func(bapp *BaseApp) {
|
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
|
|
|
panic(sdkerrors.Wrap(anteErr, "anteHandler"))
|
|
|
|
return
|
|
|
|
})
|
|
|
|
}
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2020-06-05 09:48:18 -07:00
|
|
|
return &sdk.Result{}, nil
|
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2020-06-05 09:48:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
|
|
|
|
header := abci.Header{Height: 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
|
|
|
|
app.AddRunTxRecoveryHandler(func(recoveryObj interface{}) error {
|
|
|
|
err, ok := recoveryObj.(error)
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if anteErr.Is(err) {
|
|
|
|
panic(customPanicMsg)
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Transaction should panic with custom handler above
|
|
|
|
{
|
|
|
|
tx := newTxCounter(0, 0)
|
|
|
|
|
|
|
|
require.PanicsWithValue(t, customPanicMsg, func() { app.Deliver(tx) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-16 10:33:47 -08:00
|
|
|
func TestBaseAppAnteHandler(t *testing.T) {
|
|
|
|
anteKey := []byte("ante-key")
|
|
|
|
anteOpt := func(bapp *BaseApp) {
|
|
|
|
bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
deliverKey := []byte("deliver-key")
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey))
|
|
|
|
bapp.Router().AddRoute(r)
|
2018-11-16 10:33:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
cdc := codec.New()
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
registerTestCodec(cdc)
|
2019-03-07 21:52:19 -08:00
|
|
|
|
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2018-11-16 10:33:47 -08:00
|
|
|
|
|
|
|
// execute a tx that will fail ante handler execution
|
|
|
|
//
|
|
|
|
// NOTE: State should not be mutated here. This will be implicitly checked by
|
|
|
|
// the next txs ante handler execution (anteHandlerTxTest).
|
|
|
|
tx := newTxCounter(0, 0)
|
|
|
|
tx.setFailOnAnte(true)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := cdc.MarshalBinaryBare(tx)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.NoError(t, err)
|
2019-06-26 09:03:25 -07:00
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2020-06-01 21:26:13 -07:00
|
|
|
require.Empty(t, res.Events)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
ctx := app.getState(runTxModeDeliver).ctx
|
|
|
|
store := ctx.KVStore(capKey1)
|
|
|
|
require.Equal(t, int64(0), getIntFromStore(store, anteKey))
|
|
|
|
|
|
|
|
// execute at tx that will pass the ante handler (the checkTx state should
|
|
|
|
// mutate) but will fail the message handler
|
|
|
|
tx = newTxCounter(0, 0)
|
|
|
|
tx.setFailOnHandler(true)
|
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err = cdc.MarshalBinaryBare(tx)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2020-06-01 21:26:13 -07:00
|
|
|
require.Empty(t, res.Events)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
ctx = app.getState(runTxModeDeliver).ctx
|
|
|
|
store = ctx.KVStore(capKey1)
|
|
|
|
require.Equal(t, int64(1), getIntFromStore(store, anteKey))
|
|
|
|
require.Equal(t, int64(0), getIntFromStore(store, deliverKey))
|
|
|
|
|
|
|
|
// execute a successful ante handler and message execution where state is
|
|
|
|
// implicitly checked by previous tx executions
|
|
|
|
tx = newTxCounter(1, 0)
|
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err = cdc.MarshalBinaryBare(tx)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2020-06-01 21:26:13 -07:00
|
|
|
require.NotEmpty(t, res.Events)
|
2018-11-16 10:33:47 -08:00
|
|
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
ctx = app.getState(runTxModeDeliver).ctx
|
|
|
|
store = ctx.KVStore(capKey1)
|
|
|
|
require.Equal(t, int64(2), getIntFromStore(store, anteKey))
|
|
|
|
require.Equal(t, int64(1), getIntFromStore(store, deliverKey))
|
|
|
|
|
|
|
|
// commit
|
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
}
|
2019-02-05 19:11:57 -08:00
|
|
|
|
|
|
|
func TestGasConsumptionBadTx(t *testing.T) {
|
|
|
|
gasWanted := uint64(5)
|
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2019-02-05 19:11:57 -08:00
|
|
|
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasWanted))
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
switch rType := r.(type) {
|
|
|
|
case sdk.ErrorOutOfGas:
|
|
|
|
log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor)
|
2019-10-10 05:46:09 -07:00
|
|
|
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
|
2019-02-05 19:11:57 -08:00
|
|
|
default:
|
|
|
|
panic(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
txTest := tx.(txTest)
|
|
|
|
newCtx.GasMeter().ConsumeGas(uint64(txTest.Counter), "counter-ante")
|
|
|
|
if txTest.FailOnAnte {
|
2019-10-10 05:46:09 -07:00
|
|
|
return newCtx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure")
|
2019-02-05 19:11:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2019-02-05 19:11:57 -08:00
|
|
|
count := msg.(msgCounter).Counter
|
|
|
|
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2019-02-05 19:11:57 -08:00
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2019-02-05 19:11:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
cdc := codec.New()
|
|
|
|
registerTestCodec(cdc)
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
app.InitChain(abci.RequestInitChain{
|
|
|
|
ConsensusParams: &abci.ConsensusParams{
|
2019-03-29 10:13:45 -07:00
|
|
|
Block: &abci.BlockParams{
|
2019-02-05 19:11:57 -08:00
|
|
|
MaxGas: 9,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
2019-03-07 21:52:19 -08:00
|
|
|
|
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
2019-02-05 19:11:57 -08:00
|
|
|
|
|
|
|
tx := newTxCounter(5, 0)
|
|
|
|
tx.setFailOnAnte(true)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := cdc.MarshalBinaryBare(tx)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2019-02-05 19:11:57 -08:00
|
|
|
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
|
|
|
|
// require next tx to fail due to black gas limit
|
|
|
|
tx = newTxCounter(5, 0)
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err = cdc.MarshalBinaryBare(tx)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-06-26 09:03:25 -07:00
|
|
|
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
2019-02-05 19:11:57 -08:00
|
|
|
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we can only query from the latest committed state.
|
|
|
|
func TestQuery(t *testing.T) {
|
|
|
|
key, value := []byte("hello"), []byte("goodbye")
|
|
|
|
anteOpt := func(bapp *BaseApp) {
|
2019-10-10 05:46:09 -07:00
|
|
|
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
2019-02-05 19:11:57 -08:00
|
|
|
store := ctx.KVStore(capKey1)
|
|
|
|
store.Set(key, value)
|
|
|
|
return
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
2019-02-05 19:11:57 -08:00
|
|
|
store := ctx.KVStore(capKey1)
|
|
|
|
store.Set(key, value)
|
2019-12-27 09:57:54 -08:00
|
|
|
return &sdk.Result{}, nil
|
2019-02-05 19:11:57 -08:00
|
|
|
})
|
2020-06-10 11:48:16 -07:00
|
|
|
bapp.Router().AddRoute(r)
|
2019-02-05 19:11:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
|
|
|
|
// NOTE: "/store/key1" tells us KVStore
|
|
|
|
// and the final "/key" says to use the data as the
|
|
|
|
// key in the given KVStore ...
|
|
|
|
query := abci.RequestQuery{
|
|
|
|
Path: "/store/key1/key",
|
|
|
|
Data: key,
|
|
|
|
}
|
|
|
|
tx := newTxCounter(0, 0)
|
|
|
|
|
|
|
|
// query is empty before we do anything
|
|
|
|
res := app.Query(query)
|
|
|
|
require.Equal(t, 0, len(res.Value))
|
|
|
|
|
|
|
|
// query is still empty after a CheckTx
|
2019-12-27 09:57:54 -08:00
|
|
|
_, resTx, err := app.Check(tx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, resTx)
|
2019-02-05 19:11:57 -08:00
|
|
|
res = app.Query(query)
|
|
|
|
require.Equal(t, 0, len(res.Value))
|
|
|
|
|
|
|
|
// query is still empty after a DeliverTx before we commit
|
2019-03-07 21:52:19 -08:00
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
|
2019-12-27 09:57:54 -08:00
|
|
|
_, resTx, err = app.Deliver(tx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, resTx)
|
2019-02-05 19:11:57 -08:00
|
|
|
res = app.Query(query)
|
|
|
|
require.Equal(t, 0, len(res.Value))
|
|
|
|
|
|
|
|
// query returns correct value after Commit
|
|
|
|
app.Commit()
|
|
|
|
res = app.Query(query)
|
|
|
|
require.Equal(t, value, res.Value)
|
|
|
|
}
|
|
|
|
|
2020-06-04 11:48:06 -07:00
|
|
|
func TestGRPCQuery(t *testing.T) {
|
|
|
|
grpcQueryOpt := func(bapp *BaseApp) {
|
|
|
|
testdata.RegisterTestServiceServer(
|
|
|
|
bapp.GRPCQueryRouter(),
|
2020-06-08 06:41:30 -07:00
|
|
|
testdata.TestServiceImpl{},
|
2020-06-04 11:48:06 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, grpcQueryOpt)
|
|
|
|
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
header := abci.Header{Height: app.LastBlockHeight() + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
app.Commit()
|
|
|
|
|
|
|
|
req := testdata.SayHelloRequest{Name: "foo"}
|
|
|
|
reqBz, err := req.Marshal()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
reqQuery := abci.RequestQuery{
|
|
|
|
Data: reqBz,
|
|
|
|
Path: "/cosmos_sdk.codec.v1.TestService/SayHello",
|
|
|
|
}
|
|
|
|
|
|
|
|
resQuery := app.Query(reqQuery)
|
|
|
|
|
|
|
|
require.Equal(t, abci.CodeTypeOK, resQuery.Code, resQuery)
|
|
|
|
|
|
|
|
var res testdata.SayHelloResponse
|
|
|
|
err = res.Unmarshal(resQuery.Value)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "Hello foo!", res.Greeting)
|
|
|
|
}
|
|
|
|
|
2019-02-05 19:11:57 -08:00
|
|
|
// Test p2p filter queries
|
|
|
|
func TestP2PQuery(t *testing.T) {
|
|
|
|
addrPeerFilterOpt := func(bapp *BaseApp) {
|
|
|
|
bapp.SetAddrPeerFilter(func(addrport string) abci.ResponseQuery {
|
|
|
|
require.Equal(t, "1.1.1.1:8000", addrport)
|
|
|
|
return abci.ResponseQuery{Code: uint32(3)}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-07 17:52:24 -08:00
|
|
|
idPeerFilterOpt := func(bapp *BaseApp) {
|
|
|
|
bapp.SetIDPeerFilter(func(id string) abci.ResponseQuery {
|
|
|
|
require.Equal(t, "testid", id)
|
2019-02-05 19:11:57 -08:00
|
|
|
return abci.ResponseQuery{Code: uint32(4)}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-07 17:52:24 -08:00
|
|
|
app := setupBaseApp(t, addrPeerFilterOpt, idPeerFilterOpt)
|
2019-02-05 19:11:57 -08:00
|
|
|
|
|
|
|
addrQuery := abci.RequestQuery{
|
|
|
|
Path: "/p2p/filter/addr/1.1.1.1:8000",
|
|
|
|
}
|
|
|
|
res := app.Query(addrQuery)
|
|
|
|
require.Equal(t, uint32(3), res.Code)
|
|
|
|
|
2019-02-07 17:52:24 -08:00
|
|
|
idQuery := abci.RequestQuery{
|
|
|
|
Path: "/p2p/filter/id/testid",
|
2019-02-05 19:11:57 -08:00
|
|
|
}
|
2019-02-07 17:52:24 -08:00
|
|
|
res = app.Query(idQuery)
|
2019-02-05 19:11:57 -08:00
|
|
|
require.Equal(t, uint32(4), res.Code)
|
|
|
|
}
|
2019-03-07 21:52:19 -08:00
|
|
|
|
|
|
|
func TestGetMaximumBlockGas(t *testing.T) {
|
|
|
|
app := setupBaseApp(t)
|
2020-04-16 08:10:39 -07:00
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
ctx := app.NewContext(true, abci.Header{})
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2020-04-22 11:24:13 -07:00
|
|
|
app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 0}})
|
2020-04-16 08:10:39 -07:00
|
|
|
require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx))
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2020-04-22 11:24:13 -07:00
|
|
|
app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -1}})
|
2020-04-16 08:10:39 -07:00
|
|
|
require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx))
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2020-04-22 11:24:13 -07:00
|
|
|
app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 5000000}})
|
2020-04-16 08:10:39 -07:00
|
|
|
require.Equal(t, uint64(5000000), app.getMaximumBlockGas(ctx))
|
2019-03-07 21:52:19 -08:00
|
|
|
|
2020-04-22 11:24:13 -07:00
|
|
|
app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -5000000}})
|
2020-04-16 08:10:39 -07:00
|
|
|
require.Panics(t, func() { app.getMaximumBlockGas(ctx) })
|
2019-03-07 21:52:19 -08:00
|
|
|
}
|
2020-01-04 11:50:38 -08:00
|
|
|
|
|
|
|
// NOTE: represents a new custom router for testing purposes of WithRouter()
|
|
|
|
type testCustomRouter struct {
|
|
|
|
routes sync.Map
|
|
|
|
}
|
|
|
|
|
2020-06-11 08:37:23 -07:00
|
|
|
func (rtr *testCustomRouter) AddRoute(route sdk.Route) sdk.Router {
|
2020-06-10 11:48:16 -07:00
|
|
|
rtr.routes.Store(route.Path(), route.Handler())
|
2020-01-04 11:50:38 -08:00
|
|
|
return rtr
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rtr *testCustomRouter) Route(ctx sdk.Context, path string) sdk.Handler {
|
|
|
|
if v, ok := rtr.routes.Load(path); ok {
|
|
|
|
if h, ok := v.(sdk.Handler); ok {
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithRouter(t *testing.T) {
|
|
|
|
// test increments in the ante
|
|
|
|
anteKey := []byte("ante-key")
|
|
|
|
anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) }
|
|
|
|
|
|
|
|
// test increments in the handler
|
|
|
|
deliverKey := []byte("deliver-key")
|
|
|
|
routerOpt := func(bapp *BaseApp) {
|
|
|
|
bapp.SetRouter(&testCustomRouter{routes: sync.Map{}})
|
2020-06-10 11:48:16 -07:00
|
|
|
r := sdk.NewRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey))
|
|
|
|
bapp.Router().AddRoute(r)
|
2020-01-04 11:50:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
app := setupBaseApp(t, anteOpt, routerOpt)
|
|
|
|
app.InitChain(abci.RequestInitChain{})
|
|
|
|
|
|
|
|
// Create same codec used in txDecoder
|
|
|
|
codec := codec.New()
|
|
|
|
registerTestCodec(codec)
|
|
|
|
|
|
|
|
nBlocks := 3
|
|
|
|
txPerHeight := 5
|
|
|
|
|
|
|
|
for blockN := 0; blockN < nBlocks; blockN++ {
|
|
|
|
header := abci.Header{Height: int64(blockN) + 1}
|
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: header})
|
|
|
|
|
|
|
|
for i := 0; i < txPerHeight; i++ {
|
|
|
|
counter := int64(blockN*txPerHeight + i)
|
|
|
|
tx := newTxCounter(counter, counter)
|
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
txBytes, err := codec.MarshalBinaryBare(tx)
|
2020-01-04 11:50:38 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
|
|
|
|
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
|
|
|
|
}
|
|
|
|
|
|
|
|
app.EndBlock(abci.RequestEndBlock{})
|
|
|
|
app.Commit()
|
|
|
|
}
|
|
|
|
}
|