github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/baseapp/baseapp_test.go (about) 1 package baseapp 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io/ioutil" 8 "math/big" 9 "os" 10 "sync" 11 "testing" 12 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 14 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/rootmulti" 15 store "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types" 16 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 17 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 18 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 19 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 20 dbm "github.com/fibonacci-chain/fbc/libs/tm-db" 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 ) 24 25 var ( 26 capKey1 = sdk.NewKVStoreKey("key1") 27 capKey2 = sdk.NewKVStoreKey("key2") 28 ) 29 30 func defaultLogger() log.Logger { 31 return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") 32 } 33 34 func newBaseApp(name string, options ...func(*BaseApp)) *BaseApp { 35 logger := defaultLogger() 36 db := dbm.NewMemDB() 37 codec := codec.New() 38 registerTestCodec(codec) 39 return NewBaseApp(name, logger, db, testTxDecoder(codec), options...) 40 } 41 42 func registerTestCodec(cdc *codec.Codec) { 43 // register Tx, Msg 44 sdk.RegisterCodec(cdc) 45 46 // register test types 47 cdc.RegisterConcrete(&txTest{}, "cosmos-sdk/baseapp/txTest", nil) 48 cdc.RegisterConcrete(&msgCounter{}, "cosmos-sdk/baseapp/msgCounter", nil) 49 cdc.RegisterConcrete(&msgCounter2{}, "cosmos-sdk/baseapp/msgCounter2", nil) 50 cdc.RegisterConcrete(&msgNoRoute{}, "cosmos-sdk/baseapp/msgNoRoute", nil) 51 } 52 53 // simple one store baseapp 54 func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp { 55 app := newBaseApp(t.Name(), options...) 56 require.Equal(t, t.Name(), app.Name()) 57 58 // no stores are mounted 59 require.Panics(t, func() { 60 app.LoadLatestVersion(capKey1) 61 }) 62 63 app.MountStores(capKey1, capKey2) 64 65 // stores are mounted 66 err := app.LoadLatestVersion(capKey1) 67 require.Nil(t, err) 68 return app 69 } 70 71 func TestMountStores(t *testing.T) { 72 app := setupBaseApp(t) 73 74 // check both stores 75 store1 := app.cms.GetCommitKVStore(capKey1) 76 require.NotNil(t, store1) 77 store2 := app.cms.GetCommitKVStore(capKey2) 78 require.NotNil(t, store2) 79 } 80 81 // Test that we can make commits and then reload old versions. 82 // Test that LoadLatestVersion actually does. 83 func TestLoadVersion(t *testing.T) { 84 logger := defaultLogger() 85 pruningOpt := SetPruning(store.PruneNothing) 86 db := dbm.NewMemDB() 87 name := t.Name() 88 app := NewBaseApp(name, logger, db, nil, pruningOpt) 89 app.InitChain(abci.RequestInitChain{}) 90 // make a cap key and mount the store 91 capKey := sdk.NewKVStoreKey(MainStoreKey) 92 app.MountStores(capKey) 93 err := app.LoadLatestVersion(capKey) // needed to make stores non-nil 94 require.Nil(t, err) 95 96 emptyCommitID := sdk.CommitID{} 97 98 // fresh store has zero/empty last commit 99 lastHeight := app.LastBlockHeight() 100 lastID := app.LastCommitID() 101 require.Equal(t, int64(0), lastHeight) 102 require.Equal(t, emptyCommitID, lastID) 103 104 // execute a block, collect commit ID 105 header := abci.Header{Height: 1} 106 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 107 res := app.Commit(abci.RequestCommit{}) 108 commitID1 := sdk.CommitID{Version: 1, Hash: res.Data} 109 110 // execute a block, collect commit ID 111 header = abci.Header{Height: 2} 112 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 113 res = app.Commit(abci.RequestCommit{}) 114 commitID2 := sdk.CommitID{Version: 2, Hash: res.Data} 115 116 // reload with LoadLatestVersion 117 app = NewBaseApp(name, logger, db, nil, pruningOpt) 118 app.MountStores(capKey) 119 err = app.LoadLatestVersion(capKey) 120 require.Nil(t, err) 121 testLoadVersionHelper(t, app, int64(2), commitID2) 122 123 // reload with LoadVersion, see if you can commit the same block and get 124 // the same result 125 app = NewBaseApp(name, logger, db, nil, pruningOpt) 126 app.MountStores(capKey) 127 err = app.LoadVersion(1, capKey) 128 require.Nil(t, err) 129 testLoadVersionHelper(t, app, int64(1), commitID1) 130 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 131 app.Commit(abci.RequestCommit{}) 132 testLoadVersionHelper(t, app, int64(2), commitID2) 133 } 134 135 func useDefaultLoader(app *BaseApp) { 136 app.SetStoreLoader(DefaultStoreLoader) 137 } 138 139 func useUpgradeLoader(upgrades *store.StoreUpgrades) func(*BaseApp) { 140 return func(app *BaseApp) { 141 app.SetStoreLoader(StoreLoaderWithUpgrade(upgrades)) 142 } 143 } 144 145 func useFileUpgradeLoader(upgradeInfoPath string) func(*BaseApp) { 146 return func(app *BaseApp) { 147 app.SetStoreLoader(UpgradeableStoreLoader(upgradeInfoPath)) 148 } 149 } 150 151 func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) { 152 rs := rootmulti.NewStore(db) 153 rs.SetPruning(store.PruneNothing) 154 key := sdk.NewKVStoreKey(storeKey) 155 rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil) 156 err := rs.LoadLatestVersion() 157 require.Nil(t, err) 158 require.Equal(t, int64(0), rs.LastCommitID().Version) 159 160 // write some data in substore 161 kv, _ := rs.GetStore(key).(store.KVStore) 162 require.NotNil(t, kv) 163 kv.Set(k, v) 164 commitID, _ := rs.CommitterCommitMap(nil) 165 require.Equal(t, int64(1), commitID.Version) 166 } 167 168 func checkStore(t *testing.T, db dbm.DB, ver int64, storeKey string, k, v []byte) { 169 rs := rootmulti.NewStore(db) 170 rs.SetPruning(store.PruneDefault) 171 key := sdk.NewKVStoreKey(storeKey) 172 rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil) 173 err := rs.LoadLatestVersion() 174 require.Nil(t, err) 175 require.Equal(t, ver, rs.LastCommitID().Version) 176 177 // query data in substore 178 kv, _ := rs.GetStore(key).(store.KVStore) 179 require.NotNil(t, kv) 180 require.Equal(t, v, kv.Get(k)) 181 } 182 183 // Test that we can make commits and then reload old versions. 184 // Test that LoadLatestVersion actually does. 185 func TestSetLoader(t *testing.T) { 186 // write a renamer to a file 187 f, err := ioutil.TempFile("", "upgrade-*.json") 188 require.NoError(t, err) 189 data := []byte(`{"renamed":[{"old_key": "bnk", "new_key": "banker"}]}`) 190 _, err = f.Write(data) 191 require.NoError(t, err) 192 configName := f.Name() 193 require.NoError(t, f.Close()) 194 195 // make sure it exists before running everything 196 _, err = os.Stat(configName) 197 require.NoError(t, err) 198 199 cases := map[string]struct { 200 setLoader func(*BaseApp) 201 origStoreKey string 202 loadStoreKey string 203 }{ 204 "don't set loader": { 205 origStoreKey: "foo", 206 loadStoreKey: "foo", 207 }, 208 "default loader": { 209 setLoader: useDefaultLoader, 210 origStoreKey: "foo", 211 loadStoreKey: "foo", 212 }, 213 "rename with inline opts": { 214 setLoader: useUpgradeLoader(&store.StoreUpgrades{ 215 Renamed: []store.StoreRename{{ 216 OldKey: "foo", 217 NewKey: "bar", 218 }}, 219 }), 220 origStoreKey: "foo", 221 loadStoreKey: "bar", 222 }, 223 "file loader with missing file": { 224 setLoader: useFileUpgradeLoader(configName + "randomchars"), 225 origStoreKey: "bnk", 226 loadStoreKey: "bnk", 227 }, 228 "file loader with existing file": { 229 setLoader: useFileUpgradeLoader(configName), 230 origStoreKey: "bnk", 231 loadStoreKey: "banker", 232 }, 233 } 234 235 k := []byte("key") 236 v := []byte("value") 237 238 for name, tc := range cases { 239 tc := tc 240 t.Run(name, func(t *testing.T) { 241 // prepare a db with some data 242 db := dbm.NewMemDB() 243 initStore(t, db, tc.origStoreKey, k, v) 244 245 // load the app with the existing db 246 opts := []func(*BaseApp){SetPruning(store.PruneNothing)} 247 if tc.setLoader != nil { 248 opts = append(opts, tc.setLoader) 249 } 250 app := NewBaseApp(t.Name(), defaultLogger(), db, nil, opts...) 251 capKey := sdk.NewKVStoreKey(MainStoreKey) 252 app.MountStores(capKey) 253 app.MountStores(sdk.NewKVStoreKey(tc.loadStoreKey)) 254 err := app.LoadLatestVersion(capKey) 255 require.Nil(t, err) 256 257 // "execute" one block 258 app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: 2}}) 259 res := app.Commit(abci.RequestCommit{}) 260 require.NotNil(t, res.Data) 261 262 // check db is properly updated 263 checkStore(t, db, 2, tc.loadStoreKey, k, v) 264 checkStore(t, db, 2, tc.loadStoreKey, []byte("foo"), nil) 265 }) 266 } 267 268 // ensure config file was deleted 269 _, err = os.Stat(configName) 270 require.True(t, os.IsNotExist(err)) 271 } 272 273 func TestAppVersionSetterGetter(t *testing.T) { 274 logger := defaultLogger() 275 pruningOpt := SetPruning(store.PruneDefault) 276 db := dbm.NewMemDB() 277 name := t.Name() 278 app := NewBaseApp(name, logger, db, nil, pruningOpt) 279 280 require.Equal(t, "", app.AppVersion()) 281 res := app.Query(abci.RequestQuery{Path: "app/version"}) 282 require.True(t, res.IsOK()) 283 require.Equal(t, "", string(res.Value)) 284 285 versionString := "1.0.0" 286 app.SetAppVersion(versionString) 287 require.Equal(t, versionString, app.AppVersion()) 288 res = app.Query(abci.RequestQuery{Path: "app/version"}) 289 require.True(t, res.IsOK()) 290 require.Equal(t, versionString, string(res.Value)) 291 } 292 293 func TestLoadVersionInvalid(t *testing.T) { 294 logger := log.NewNopLogger() 295 pruningOpt := SetPruning(store.PruneNothing) 296 db := dbm.NewMemDB() 297 name := t.Name() 298 app := NewBaseApp(name, logger, db, nil, pruningOpt) 299 app.InitChain(abci.RequestInitChain{}) 300 capKey := sdk.NewKVStoreKey(MainStoreKey) 301 app.MountStores(capKey) 302 err := app.LoadLatestVersion(capKey) 303 require.Nil(t, err) 304 305 // require error when loading an invalid version 306 err = app.LoadVersion(-1, capKey) 307 require.Error(t, err) 308 309 header := abci.Header{Height: 1} 310 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 311 res := app.Commit(abci.RequestCommit{}) 312 commitID1 := sdk.CommitID{Version: 1, Hash: res.Data} 313 314 // create a new app with the stores mounted under the same cap key 315 app = NewBaseApp(name, logger, db, nil, pruningOpt) 316 app.MountStores(capKey) 317 318 // require we can load the latest version 319 err = app.LoadVersion(1, capKey) 320 require.Nil(t, err) 321 testLoadVersionHelper(t, app, int64(1), commitID1) 322 323 // require error when loading an invalid version 324 err = app.LoadVersion(2, capKey) 325 require.Error(t, err) 326 } 327 328 func TestLoadVersionPruning(t *testing.T) { 329 logger := log.NewNopLogger() 330 pruningOptions := store.PruningOptions{ 331 KeepRecent: 2, 332 KeepEvery: 3, 333 Interval: 1, 334 MaxRetainNum: 10, 335 } 336 pruningOpt := SetPruning(pruningOptions) 337 db := dbm.NewMemDB() 338 name := t.Name() 339 app := NewBaseApp(name, logger, db, nil, pruningOpt) 340 app.InitChain(abci.RequestInitChain{}) 341 342 // make a cap key and mount the store 343 capKey := sdk.NewKVStoreKey(MainStoreKey) 344 app.MountStores(capKey) 345 err := app.LoadLatestVersion(capKey) // needed to make stores non-nil 346 require.Nil(t, err) 347 348 emptyCommitID := sdk.CommitID{} 349 350 // fresh store has zero/empty last commit 351 lastHeight := app.LastBlockHeight() 352 lastID := app.LastCommitID() 353 require.Equal(t, int64(0), lastHeight) 354 require.Equal(t, emptyCommitID, lastID) 355 356 var lastCommitID sdk.CommitID 357 358 // Commit seven blocks, of which 7 (latest) is kept in addition to 6, 5 359 // (keep recent) and 3 (keep every). 360 for i := int64(1); i <= 7; i++ { 361 app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: i}}) 362 res := app.Commit(abci.RequestCommit{}) 363 lastCommitID = sdk.CommitID{Version: i, Hash: res.Data} 364 } 365 366 for _, v := range []int64{1, 2, 4} { 367 _, err = app.cms.CacheMultiStoreWithVersion(v) 368 require.Error(t, err) 369 } 370 371 for _, v := range []int64{3, 5, 6, 7} { 372 _, err = app.cms.CacheMultiStoreWithVersion(v) 373 require.NoError(t, err) 374 } 375 376 // reload with LoadLatestVersion, check it loads last version 377 app = NewBaseApp(name, logger, db, nil, pruningOpt) 378 app.MountStores(capKey) 379 380 err = app.LoadLatestVersion(capKey) 381 require.Nil(t, err) 382 testLoadVersionHelper(t, app, int64(7), lastCommitID) 383 } 384 385 func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, expectedID sdk.CommitID) { 386 lastHeight := app.LastBlockHeight() 387 lastID := app.LastCommitID() 388 require.Equal(t, expectedHeight, lastHeight) 389 require.Equal(t, expectedID, lastID) 390 } 391 392 func TestOptionFunction(t *testing.T) { 393 logger := defaultLogger() 394 db := dbm.NewMemDB() 395 bap := NewBaseApp("starting name", logger, db, nil, testChangeNameHelper("new name")) 396 require.Equal(t, bap.name, "new name", "BaseApp should have had name changed via option function") 397 } 398 399 func testChangeNameHelper(name string) func(*BaseApp) { 400 return func(bap *BaseApp) { 401 bap.name = name 402 } 403 } 404 405 // Test that txs can be unmarshalled and read and that 406 // correct error codes are returned when not 407 func TestTxDecoder(t *testing.T) { 408 codec := codec.New() 409 registerTestCodec(codec) 410 411 app := newBaseApp(t.Name()) 412 tx := newTxCounter(1, 0) 413 txBytes := codec.MustMarshalBinaryLengthPrefixed(tx) 414 415 dTx, err := app.txDecoder(txBytes) 416 require.NoError(t, err) 417 418 cTx := dTx.(*txTest) 419 require.Equal(t, tx.Counter, cTx.Counter) 420 } 421 422 // Test that Info returns the latest committed state. 423 func TestInfo(t *testing.T) { 424 app := newBaseApp(t.Name()) 425 426 // ----- test an empty response ------- 427 reqInfo := abci.RequestInfo{} 428 res := app.Info(reqInfo) 429 430 // should be empty 431 assert.Equal(t, "", res.Version) 432 assert.Equal(t, t.Name(), res.GetData()) 433 assert.Equal(t, int64(0), res.LastBlockHeight) 434 require.Equal(t, []uint8(nil), res.LastBlockAppHash) 435 436 // ----- test a proper response ------- 437 // TODO 438 } 439 440 func TestBaseAppOptionSeal(t *testing.T) { 441 app := setupBaseApp(t) 442 443 require.Panics(t, func() { 444 app.SetName("") 445 }) 446 require.Panics(t, func() { 447 app.SetAppVersion("") 448 }) 449 require.Panics(t, func() { 450 app.SetDB(nil) 451 }) 452 require.Panics(t, func() { 453 app.SetCMS(nil) 454 }) 455 require.Panics(t, func() { 456 app.SetInitChainer(nil) 457 }) 458 require.Panics(t, func() { 459 app.SetBeginBlocker(nil) 460 }) 461 require.Panics(t, func() { 462 app.SetEndBlocker(nil) 463 }) 464 require.Panics(t, func() { 465 app.SetAnteHandler(nil) 466 }) 467 require.Panics(t, func() { 468 app.SetAddrPeerFilter(nil) 469 }) 470 require.Panics(t, func() { 471 app.SetIDPeerFilter(nil) 472 }) 473 require.Panics(t, func() { 474 app.SetFauxMerkleMode() 475 }) 476 require.Panics(t, func() { 477 app.SetRouter(NewRouter()) 478 }) 479 } 480 481 func TestSetMinGasPrices(t *testing.T) { 482 minGasPrices := sdk.DecCoins{sdk.NewInt64DecCoin("stake", 5000)} 483 app := newBaseApp(t.Name(), SetMinGasPrices(minGasPrices.String())) 484 require.Equal(t, minGasPrices, app.minGasPrices) 485 } 486 487 func TestInitChainer(t *testing.T) { 488 name := t.Name() 489 // keep the db and logger ourselves so 490 // we can reload the same app later 491 db := dbm.NewMemDB() 492 logger := defaultLogger() 493 app := NewBaseApp(name, logger, db, nil) 494 capKey := sdk.NewKVStoreKey(MainStoreKey) 495 capKey2 := sdk.NewKVStoreKey("key2") 496 app.MountStores(capKey, capKey2) 497 498 // set a value in the store on init chain 499 key, value := []byte("hello"), []byte("goodbye") 500 var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { 501 store := ctx.KVStore(capKey) 502 store.Set(key, value) 503 return abci.ResponseInitChain{} 504 } 505 506 query := abci.RequestQuery{ 507 Path: "/store/main/key", 508 Data: key, 509 } 510 511 // initChainer is nil - nothing happens 512 app.InitChain(abci.RequestInitChain{}) 513 res := app.Query(query) 514 require.Equal(t, 0, len(res.Value)) 515 516 // set initChainer and try again - should see the value 517 app.SetInitChainer(initChainer) 518 519 // stores are mounted and private members are set - sealing baseapp 520 err := app.LoadLatestVersion(capKey) // needed to make stores non-nil 521 require.Nil(t, err) 522 require.Equal(t, int64(0), app.LastBlockHeight()) 523 524 app.InitChain(abci.RequestInitChain{AppStateBytes: []byte("{}"), ChainId: "test-chain-id"}) // must have valid JSON genesis file, even if empty 525 526 // assert that chainID is set correctly in InitChain 527 chainID := app.deliverState.ctx.ChainID() 528 require.Equal(t, "test-chain-id", chainID, "ChainID in deliverState not set correctly in InitChain") 529 530 chainID = app.checkState.ctx.ChainID() 531 require.Equal(t, "test-chain-id", chainID, "ChainID in checkState not set correctly in InitChain") 532 533 app.Commit(abci.RequestCommit{}) 534 res = app.Query(query) 535 require.Equal(t, int64(1), app.LastBlockHeight()) 536 require.Equal(t, value, res.Value) 537 538 // reload app 539 app = NewBaseApp(name, logger, db, nil) 540 app.SetInitChainer(initChainer) 541 app.MountStores(capKey, capKey2) 542 err = app.LoadLatestVersion(capKey) // needed to make stores non-nil 543 require.Nil(t, err) 544 require.Equal(t, int64(1), app.LastBlockHeight()) 545 546 // ensure we can still query after reloading 547 res = app.Query(query) 548 require.Equal(t, value, res.Value) 549 550 // commit and ensure we can still query 551 header := abci.Header{Height: app.LastBlockHeight() + 1} 552 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 553 app.Commit(abci.RequestCommit{}) 554 555 res = app.Query(query) 556 require.Equal(t, value, res.Value) 557 } 558 559 // Simple tx with a list of Msgs. 560 type txTest struct { 561 sdk.BaseTx 562 563 Msgs []sdk.Msg 564 Counter int64 565 FailOnAnte bool 566 } 567 568 func (tx *txTest) setFailOnAnte(fail bool) { 569 tx.FailOnAnte = fail 570 } 571 572 func (tx *txTest) setFailOnHandler(fail bool) { 573 for i, msg := range tx.Msgs { 574 tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail} 575 } 576 } 577 578 // Implements Tx 579 func (tx *txTest) GetMsgs() []sdk.Msg { return tx.Msgs } 580 func (tx *txTest) ValidateBasic() error { return nil } 581 582 func (tx *txTest) GetFrom() string { 583 return "" 584 } 585 586 func (tx *txTest) GetSender(_ sdk.Context) string { 587 return "" 588 } 589 590 func (tx *txTest) GetNonce() uint64 { 591 return 0 592 } 593 594 func (tx *txTest) GetGasPrice() *big.Int { 595 return big.NewInt(0) 596 } 597 598 func (tx *txTest) GetTxFnSignatureInfo() ([]byte, int) { 599 return nil, 0 600 } 601 602 func (tx *txTest) GetGas() uint64 { 603 return 0 604 } 605 606 func (tx *txTest) GetType() sdk.TransactionType { 607 return sdk.UnknownType 608 } 609 610 func (tx *txTest) GetSigners() []sdk.AccAddress { 611 return nil 612 } 613 614 const ( 615 routeMsgCounter = "msgCounter" 616 routeMsgCounter2 = "msgCounter2" 617 ) 618 619 // ValidateBasic() fails on negative counters. 620 // Otherwise it's up to the handlers 621 type msgCounter struct { 622 Counter int64 623 FailOnHandler bool 624 } 625 626 // Implements Msg 627 func (msg msgCounter) Route() string { return routeMsgCounter } 628 func (msg msgCounter) Type() string { return "counter1" } 629 func (msg msgCounter) GetSignBytes() []byte { return nil } 630 func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil } 631 func (msg msgCounter) ValidateBasic() error { 632 if msg.Counter >= 0 { 633 return nil 634 } 635 return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer") 636 } 637 638 func newTxCounter(counter int64, msgCounters ...int64) *txTest { 639 msgs := make([]sdk.Msg, 0, len(msgCounters)) 640 for _, c := range msgCounters { 641 msgs = append(msgs, msgCounter{c, false}) 642 } 643 644 return &txTest{Msgs: msgs, Counter: counter, FailOnAnte: false} 645 } 646 647 // a msg we dont know how to route 648 type msgNoRoute struct { 649 msgCounter 650 } 651 652 func (tx msgNoRoute) Route() string { return "noroute" } 653 654 // a msg we dont know how to decode 655 type msgNoDecode struct { 656 msgCounter 657 } 658 659 func (tx msgNoDecode) Route() string { return routeMsgCounter } 660 661 // Another counter msg. Duplicate of msgCounter 662 type msgCounter2 struct { 663 Counter int64 664 } 665 666 // Implements Msg 667 func (msg msgCounter2) Route() string { return routeMsgCounter2 } 668 func (msg msgCounter2) Type() string { return "counter2" } 669 func (msg msgCounter2) GetSignBytes() []byte { return nil } 670 func (msg msgCounter2) GetSigners() []sdk.AccAddress { return nil } 671 func (msg msgCounter2) ValidateBasic() error { 672 if msg.Counter >= 0 { 673 return nil 674 } 675 return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer") 676 } 677 678 // amino decode 679 func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder { 680 return func(txBytes []byte, _ ...int64) (sdk.Tx, error) { 681 var tx txTest 682 if len(txBytes) == 0 { 683 return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty") 684 } 685 686 err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx) 687 if err != nil { 688 return nil, sdkerrors.ErrTxDecode 689 } 690 691 return &tx, nil 692 } 693 } 694 695 func anteHandlerTxTest(t *testing.T, capKey sdk.StoreKey, storeKey []byte) sdk.AnteHandler { 696 return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) { 697 store := ctx.KVStore(capKey) 698 txTest := tx.(*txTest) 699 700 if txTest.FailOnAnte { 701 return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure") 702 } 703 704 _, err := incrementingCounter(t, store, storeKey, txTest.Counter) 705 if err != nil { 706 return ctx, err 707 } 708 709 ctx.EventManager().EmitEvents( 710 counterEvent("ante_handler", txTest.Counter), 711 ) 712 713 return ctx, nil 714 } 715 } 716 717 func counterEvent(evType string, msgCount int64) sdk.Events { 718 return sdk.Events{ 719 sdk.NewEvent( 720 evType, 721 sdk.NewAttribute("update_counter", fmt.Sprintf("%d", msgCount)), 722 ), 723 } 724 } 725 726 func handlerMsgCounter(t *testing.T, capKey sdk.StoreKey, deliverKey []byte) sdk.Handler { 727 return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 728 store := ctx.KVStore(capKey) 729 var msgCount int64 730 731 switch m := msg.(type) { 732 case *msgCounter: 733 if m.FailOnHandler { 734 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "message handler failure") 735 } 736 737 msgCount = m.Counter 738 739 case *msgCounter2: 740 msgCount = m.Counter 741 } 742 743 return incrementingCounter(t, store, deliverKey, msgCount) 744 } 745 } 746 747 func getIntFromStore(store sdk.KVStore, key []byte) int64 { 748 bz := store.Get(key) 749 if len(bz) == 0 { 750 return 0 751 } 752 i, err := binary.ReadVarint(bytes.NewBuffer(bz)) 753 if err != nil { 754 panic(err) 755 } 756 return i 757 } 758 759 func setIntOnStore(store sdk.KVStore, key []byte, i int64) { 760 bz := make([]byte, 8) 761 n := binary.PutVarint(bz, i) 762 store.Set(key, bz[:n]) 763 } 764 765 // check counter matches what's in store. 766 // increment and store 767 func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (*sdk.Result, error) { 768 storedCounter := getIntFromStore(store, counterKey) 769 require.Equal(t, storedCounter, counter) 770 setIntOnStore(store, counterKey, counter+1) 771 return &sdk.Result{}, nil 772 } 773 774 //--------------------------------------------------------------------- 775 // Tx processing - CheckTx, DeliverTx, SimulateTx. 776 // These tests use the serialized tx as input, while most others will use the 777 // Check(), Deliver(), Simulate() methods directly. 778 // Ensure that Check/Deliver/Simulate work as expected with the store. 779 780 // Test that successive CheckTx can see each others' effects 781 // on the store within a block, and that the CheckTx state 782 // gets reset to the latest committed state during Commit 783 func TestCheckTx(t *testing.T) { 784 // This ante handler reads the key and checks that the value matches the current counter. 785 // This ensures changes to the kvstore persist across successive CheckTx. 786 counterKey := []byte("counter-key") 787 788 anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, counterKey)) } 789 routerOpt := func(bapp *BaseApp) { 790 // TODO: can remove this once CheckTx doesnt process msgs. 791 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 792 return &sdk.Result{}, nil 793 }) 794 } 795 796 app := setupBaseApp(t, anteOpt, routerOpt) 797 798 nTxs := int64(5) 799 app.InitChain(abci.RequestInitChain{}) 800 801 // Create same codec used in txDecoder 802 codec := codec.New() 803 registerTestCodec(codec) 804 805 for i := int64(0); i < nTxs; i++ { 806 tx := newTxCounter(i, 0) 807 txBytes, err := codec.MarshalBinaryLengthPrefixed(tx) 808 require.NoError(t, err) 809 r := app.CheckTx(abci.RequestCheckTx{Tx: txBytes}) 810 assert.True(t, r.IsOK(), fmt.Sprintf("%v", r)) 811 } 812 813 checkStateStore := app.checkState.ctx.KVStore(capKey1) 814 storedCounter := getIntFromStore(checkStateStore, counterKey) 815 816 // Ensure AnteHandler ran 817 require.Equal(t, nTxs, storedCounter) 818 819 // If a block is committed, CheckTx state should be reset. 820 header := abci.Header{Height: 1} 821 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 822 app.EndBlock(abci.RequestEndBlock{}) 823 app.Commit(abci.RequestCommit{}) 824 825 checkStateStore = app.checkState.ctx.KVStore(capKey1) 826 storedBytes := checkStateStore.Get(counterKey) 827 require.Nil(t, storedBytes) 828 } 829 830 // Test that successive DeliverTx can see each others' effects 831 // on the store, both within and across blocks. 832 func TestDeliverTx(t *testing.T) { 833 // test increments in the ante 834 anteKey := []byte("ante-key") 835 anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } 836 837 // test increments in the handler 838 deliverKey := []byte("deliver-key") 839 routerOpt := func(bapp *BaseApp) { 840 bapp.Router().AddRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey)) 841 } 842 843 app := setupBaseApp(t, anteOpt, routerOpt) 844 app.InitChain(abci.RequestInitChain{}) 845 846 // Create same codec used in txDecoder 847 codec := codec.New() 848 registerTestCodec(codec) 849 850 nBlocks := 3 851 txPerHeight := 5 852 853 for blockN := 0; blockN < nBlocks; blockN++ { 854 header := abci.Header{Height: int64(blockN) + 1} 855 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 856 857 for i := 0; i < txPerHeight; i++ { 858 counter := int64(blockN*txPerHeight + i) 859 tx := newTxCounter(counter, counter) 860 861 txBytes, err := codec.MarshalBinaryLengthPrefixed(tx) 862 require.NoError(t, err) 863 864 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 865 require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) 866 } 867 868 app.EndBlock(abci.RequestEndBlock{}) 869 app.Commit(abci.RequestCommit{}) 870 } 871 } 872 873 // Number of messages doesn't matter to CheckTx. 874 func TestMultiMsgCheckTx(t *testing.T) { 875 // TODO: ensure we get the same results 876 // with one message or many 877 } 878 879 // One call to DeliverTx should process all the messages, in order. 880 func TestMultiMsgDeliverTx(t *testing.T) { 881 // increment the tx counter 882 anteKey := []byte("ante-key") 883 anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } 884 885 // increment the msg counter 886 deliverKey := []byte("deliver-key") 887 deliverKey2 := []byte("deliver-key2") 888 routerOpt := func(bapp *BaseApp) { 889 bapp.Router().AddRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey)) 890 bapp.Router().AddRoute(routeMsgCounter2, handlerMsgCounter(t, capKey1, deliverKey2)) 891 } 892 893 app := setupBaseApp(t, anteOpt, routerOpt) 894 app.InitChain(abci.RequestInitChain{}) 895 // Create same codec used in txDecoder 896 codec := codec.New() 897 registerTestCodec(codec) 898 899 // run a multi-msg tx 900 // with all msgs the same route 901 902 header := abci.Header{Height: 1} 903 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 904 tx := newTxCounter(0, 0, 1, 2) 905 txBytes, err := codec.MarshalBinaryLengthPrefixed(tx) 906 require.NoError(t, err) 907 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 908 require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) 909 910 store := app.deliverState.ctx.KVStore(capKey1) 911 912 // tx counter only incremented once 913 txCounter := getIntFromStore(store, anteKey) 914 require.Equal(t, int64(1), txCounter) 915 916 // msg counter incremented three times 917 msgCounter := getIntFromStore(store, deliverKey) 918 require.Equal(t, int64(3), msgCounter) 919 920 // replace the second message with a msgCounter2 921 922 tx = newTxCounter(1, 3) 923 tx.Msgs = append(tx.Msgs, msgCounter2{0}) 924 tx.Msgs = append(tx.Msgs, msgCounter2{1}) 925 txBytes, err = codec.MarshalBinaryLengthPrefixed(tx) 926 require.NoError(t, err) 927 res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 928 require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) 929 930 store = app.deliverState.ctx.KVStore(capKey1) 931 932 // tx counter only incremented once 933 txCounter = getIntFromStore(store, anteKey) 934 require.Equal(t, int64(2), txCounter) 935 936 // original counter increments by one 937 // new counter increments by two 938 msgCounter = getIntFromStore(store, deliverKey) 939 require.Equal(t, int64(4), msgCounter) 940 msgCounter2 := getIntFromStore(store, deliverKey2) 941 require.Equal(t, int64(2), msgCounter2) 942 } 943 944 // Interleave calls to Check and Deliver and ensure 945 // that there is no cross-talk. Check sees results of the previous Check calls 946 // and Deliver sees that of the previous Deliver calls, but they don't see eachother. 947 func TestConcurrentCheckDeliver(t *testing.T) { 948 // TODO 949 } 950 951 // Simulate a transaction that uses gas to compute the gas. 952 // Simulate() and Query("/app/simulate", txBytes) should give 953 // the same results. 954 func TestSimulateTx(t *testing.T) { 955 gasConsumed := uint64(5) 956 957 anteOpt := func(bapp *BaseApp) { 958 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 959 newCtx = ctx 960 newCtx.SetGasMeter(sdk.NewGasMeter(gasConsumed)) 961 return 962 }) 963 } 964 965 routerOpt := func(bapp *BaseApp) { 966 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 967 ctx.GasMeter().ConsumeGas(gasConsumed, "test") 968 return &sdk.Result{}, nil 969 }) 970 } 971 972 app := setupBaseApp(t, anteOpt, routerOpt) 973 974 app.InitChain(abci.RequestInitChain{}) 975 976 // Create same codec used in txDecoder 977 cdc := codec.New() 978 registerTestCodec(cdc) 979 980 nBlocks := 4 981 for blockN := 0; blockN < nBlocks; blockN++ { 982 count := int64(blockN + 1) 983 header := abci.Header{Height: count} 984 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 985 986 tx := newTxCounter(count, count) 987 txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx) 988 require.Nil(t, err) 989 990 if blockN != 0 { 991 // simulate a message, check gas reported 992 gInfo, result, err := app.Simulate(txBytes, tx, 0, nil) 993 require.NoError(t, err) 994 require.NotNil(t, result) 995 require.Equal(t, gasConsumed, gInfo.GasUsed) 996 997 // simulate again, same result 998 gInfo, result, err = app.Simulate(txBytes, tx, 0, nil) 999 require.NoError(t, err) 1000 require.NotNil(t, result) 1001 require.Equal(t, gasConsumed, gInfo.GasUsed) 1002 1003 // simulate by calling Query with encoded tx 1004 query := abci.RequestQuery{ 1005 Path: "/app/simulate", 1006 Data: txBytes, 1007 } 1008 queryResult := app.Query(query) 1009 require.True(t, queryResult.IsOK(), queryResult.Log) 1010 1011 var simRes sdk.SimulationResponse 1012 err = codec.Cdc.UnmarshalBinaryBare(queryResult.Value, &simRes) 1013 require.NoError(t, err) 1014 require.Equal(t, gInfo, simRes.GasInfo) 1015 require.Equal(t, result.Log, simRes.Result.Log) 1016 require.Equal(t, result.Events, simRes.Result.Events) 1017 require.True(t, bytes.Equal(result.Data, simRes.Result.Data)) 1018 } 1019 app.EndBlock(abci.RequestEndBlock{}) 1020 app.Commit(abci.RequestCommit{}) 1021 } 1022 } 1023 1024 func TestRunInvalidTransaction(t *testing.T) { 1025 anteOpt := func(bapp *BaseApp) { 1026 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 1027 return 1028 }) 1029 } 1030 routerOpt := func(bapp *BaseApp) { 1031 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 1032 return &sdk.Result{}, nil 1033 }) 1034 } 1035 1036 app := setupBaseApp(t, anteOpt, routerOpt) 1037 1038 header := abci.Header{Height: 1} 1039 app.InitChain(abci.RequestInitChain{}) 1040 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1041 1042 // transaction with no messages 1043 { 1044 emptyTx := &txTest{} 1045 _, result, err := app.Deliver(emptyTx) 1046 require.Error(t, err) 1047 require.Nil(t, result) 1048 1049 space, code, _ := sdkerrors.ABCIInfo(err, false) 1050 require.EqualValues(t, sdkerrors.ErrInvalidRequest.Codespace(), space, err) 1051 require.EqualValues(t, sdkerrors.ErrInvalidRequest.ABCICode(), code, err) 1052 } 1053 1054 // transaction where ValidateBasic fails 1055 { 1056 testCases := []struct { 1057 tx *txTest 1058 fail bool 1059 }{ 1060 {newTxCounter(0, 0), false}, 1061 {newTxCounter(-1, 0), false}, 1062 {newTxCounter(100, 100), false}, 1063 {newTxCounter(100, 5, 4, 3, 2, 1), false}, 1064 1065 {newTxCounter(0, -1), true}, 1066 {newTxCounter(0, 1, -2), true}, 1067 {newTxCounter(0, 1, 2, -10, 5), true}, 1068 } 1069 1070 for _, testCase := range testCases { 1071 tx := testCase.tx 1072 _, result, err := app.Deliver(tx) 1073 1074 if testCase.fail { 1075 require.Error(t, err) 1076 1077 space, code, _ := sdkerrors.ABCIInfo(err, false) 1078 require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err) 1079 require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err) 1080 } else { 1081 require.NotNil(t, result) 1082 } 1083 } 1084 } 1085 1086 // transaction with no known route 1087 { 1088 unknownRouteTx := &txTest{Msgs: []sdk.Msg{msgNoRoute{}}, Counter: 0, FailOnAnte: false} 1089 _, result, err := app.Deliver(unknownRouteTx) 1090 require.Error(t, err) 1091 require.Nil(t, result) 1092 1093 space, code, _ := sdkerrors.ABCIInfo(err, false) 1094 require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err) 1095 require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err) 1096 1097 unknownRouteTx = &txTest{Msgs: []sdk.Msg{msgCounter{}, msgNoRoute{}}, Counter: 0, FailOnAnte: false} 1098 _, result, err = app.Deliver(unknownRouteTx) 1099 require.Error(t, err) 1100 require.Nil(t, result) 1101 1102 space, code, _ = sdkerrors.ABCIInfo(err, false) 1103 require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err) 1104 require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err) 1105 } 1106 1107 // Transaction with an unregistered message 1108 { 1109 tx := newTxCounter(0, 0) 1110 tx.Msgs = append(tx.Msgs, msgNoDecode{}) 1111 1112 // new codec so we can encode the tx, but we shouldn't be able to decode 1113 newCdc := codec.New() 1114 registerTestCodec(newCdc) 1115 newCdc.RegisterConcrete(&msgNoDecode{}, "cosmos-sdk/baseapp/msgNoDecode", nil) 1116 1117 txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx) 1118 require.NoError(t, err) 1119 1120 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1121 require.EqualValues(t, sdkerrors.ErrTxDecode.ABCICode(), res.Code) 1122 require.EqualValues(t, sdkerrors.ErrTxDecode.Codespace(), res.Codespace) 1123 } 1124 } 1125 1126 // Test that transactions exceeding gas limits fail 1127 func TestTxGasLimits(t *testing.T) { 1128 gasGranted := uint64(10) 1129 anteOpt := func(bapp *BaseApp) { 1130 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 1131 newCtx = ctx 1132 newCtx.SetGasMeter(sdk.NewGasMeter(gasGranted)) 1133 1134 // AnteHandlers must have their own defer/recover in order for the BaseApp 1135 // to know how much gas was used! This is because the GasMeter is created in 1136 // the AnteHandler, but if it panics the context won't be set properly in 1137 // runTx's recover call. 1138 defer func() { 1139 if r := recover(); r != nil { 1140 switch rType := r.(type) { 1141 case sdk.ErrorOutOfGas: 1142 err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor) 1143 default: 1144 panic(r) 1145 } 1146 } 1147 }() 1148 1149 count := tx.(*txTest).Counter 1150 newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante") 1151 1152 return newCtx, nil 1153 }) 1154 1155 } 1156 1157 routerOpt := func(bapp *BaseApp) { 1158 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 1159 count := msg.(msgCounter).Counter 1160 ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") 1161 return &sdk.Result{}, nil 1162 }) 1163 } 1164 1165 app := setupBaseApp(t, anteOpt, routerOpt) 1166 app.InitChain(abci.RequestInitChain{}) 1167 1168 header := abci.Header{Height: 1} 1169 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1170 1171 testCases := []struct { 1172 tx *txTest 1173 gasUsed uint64 1174 fail bool 1175 }{ 1176 {newTxCounter(0, 0), 0, false}, 1177 {newTxCounter(1, 1), 2, false}, 1178 {newTxCounter(9, 1), 10, false}, 1179 {newTxCounter(1, 9), 10, false}, 1180 {newTxCounter(10, 0), 10, false}, 1181 {newTxCounter(0, 10), 10, false}, 1182 {newTxCounter(0, 8, 2), 10, false}, 1183 {newTxCounter(0, 5, 1, 1, 1, 1, 1), 10, false}, 1184 {newTxCounter(0, 5, 1, 1, 1, 1), 9, false}, 1185 1186 {newTxCounter(9, 2), 11, true}, 1187 {newTxCounter(2, 9), 11, true}, 1188 {newTxCounter(9, 1, 1), 11, true}, 1189 {newTxCounter(1, 8, 1, 1), 11, true}, 1190 {newTxCounter(11, 0), 11, true}, 1191 {newTxCounter(0, 11), 11, true}, 1192 {newTxCounter(0, 5, 11), 16, true}, 1193 } 1194 1195 for i, tc := range testCases { 1196 tx := tc.tx 1197 gInfo, result, err := app.Deliver(tx) 1198 1199 // check gas used and wanted 1200 if err == nil { 1201 require.Equal(t, tc.gasUsed, gInfo.GasUsed, fmt.Sprintf("tc #%d; gas: %v, result: %v, err: %s", i, gInfo, result, err)) 1202 } 1203 1204 // check for out of gas 1205 if !tc.fail { 1206 require.NotNil(t, result, fmt.Sprintf("%d: %v, %v", i, tc, err)) 1207 } else { 1208 require.Error(t, err) 1209 require.Nil(t, result) 1210 1211 space, code, _ := sdkerrors.ABCIInfo(err, false) 1212 require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err) 1213 require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err) 1214 } 1215 } 1216 } 1217 1218 // Test that transactions exceeding gas limits fail 1219 func TestMaxBlockGasLimits(t *testing.T) { 1220 gasGranted := uint64(10) 1221 anteOpt := func(bapp *BaseApp) { 1222 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 1223 newCtx = ctx 1224 newCtx.SetGasMeter(sdk.NewGasMeter(gasGranted)) 1225 1226 defer func() { 1227 if r := recover(); r != nil { 1228 switch rType := r.(type) { 1229 case sdk.ErrorOutOfGas: 1230 err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor) 1231 default: 1232 panic(r) 1233 } 1234 } 1235 }() 1236 1237 count := tx.(*txTest).Counter 1238 newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante") 1239 1240 return 1241 }) 1242 1243 } 1244 1245 routerOpt := func(bapp *BaseApp) { 1246 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 1247 count := msg.(msgCounter).Counter 1248 ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") 1249 return &sdk.Result{}, nil 1250 }) 1251 } 1252 1253 app := setupBaseApp(t, anteOpt, routerOpt) 1254 app.InitChain(abci.RequestInitChain{ 1255 ConsensusParams: &abci.ConsensusParams{ 1256 Block: &abci.BlockParams{ 1257 MaxGas: 100, 1258 }, 1259 }, 1260 }) 1261 1262 testCases := []struct { 1263 tx *txTest 1264 numDelivers int 1265 gasUsedPerDeliver uint64 1266 fail bool 1267 failAfterDeliver int 1268 }{ 1269 {newTxCounter(0, 0), 0, 0, false, 0}, 1270 {newTxCounter(9, 1), 2, 10, false, 0}, 1271 {newTxCounter(10, 0), 3, 10, false, 0}, 1272 {newTxCounter(10, 0), 10, 10, false, 0}, 1273 {newTxCounter(2, 7), 11, 9, false, 0}, 1274 {newTxCounter(10, 0), 10, 10, false, 0}, // hit the limit but pass 1275 1276 {newTxCounter(10, 0), 11, 10, true, 10}, 1277 {newTxCounter(10, 0), 15, 10, true, 10}, 1278 {newTxCounter(9, 0), 12, 9, true, 11}, // fly past the limit 1279 } 1280 1281 for i, tc := range testCases { 1282 tx := tc.tx 1283 1284 // reset the block gas 1285 header := abci.Header{Height: app.LastBlockHeight() + 1} 1286 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1287 1288 // execute the transaction multiple times 1289 for j := 0; j < tc.numDelivers; j++ { 1290 _, result, err := app.Deliver(tx) 1291 1292 ctx := app.getState(runTxModeDeliver).ctx 1293 1294 // check for failed transactions 1295 if tc.fail && (j+1) > tc.failAfterDeliver { 1296 require.Error(t, err, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err)) 1297 require.Nil(t, result, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err)) 1298 1299 space, code, _ := sdkerrors.ABCIInfo(err, false) 1300 require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err) 1301 require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err) 1302 require.True(t, ctx.BlockGasMeter().IsOutOfGas()) 1303 } else { 1304 // check gas used and wanted 1305 blockGasUsed := ctx.BlockGasMeter().GasConsumed() 1306 expBlockGasUsed := tc.gasUsedPerDeliver * uint64(j+1) 1307 require.Equal( 1308 t, expBlockGasUsed, blockGasUsed, 1309 fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, result), 1310 ) 1311 1312 require.NotNil(t, result, fmt.Sprintf("tc #%d; currDeliver: %d, result: %v, err: %s", i, j, result, err)) 1313 require.False(t, ctx.BlockGasMeter().IsPastLimit()) 1314 } 1315 } 1316 } 1317 } 1318 1319 func TestBaseAppAnteHandler(t *testing.T) { 1320 anteKey := []byte("ante-key") 1321 anteOpt := func(bapp *BaseApp) { 1322 bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) 1323 } 1324 1325 deliverKey := []byte("deliver-key") 1326 routerOpt := func(bapp *BaseApp) { 1327 bapp.Router().AddRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey)) 1328 } 1329 1330 cdc := codec.New() 1331 app := setupBaseApp(t, anteOpt, routerOpt) 1332 1333 app.InitChain(abci.RequestInitChain{}) 1334 registerTestCodec(cdc) 1335 1336 header := abci.Header{Height: app.LastBlockHeight() + 1} 1337 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1338 1339 // execute a tx that will fail ante handler execution 1340 // 1341 // NOTE: State should not be mutated here. This will be implicitly checked by 1342 // the next txs ante handler execution (anteHandlerTxTest). 1343 tx := newTxCounter(0, 0) 1344 tx.setFailOnAnte(true) 1345 txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx) 1346 require.NoError(t, err) 1347 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1348 require.Empty(t, res.Events) 1349 require.False(t, res.IsOK(), fmt.Sprintf("%v", res)) 1350 1351 ctx := app.getState(runTxModeDeliver).ctx 1352 store := ctx.KVStore(capKey1) 1353 require.Equal(t, int64(0), getIntFromStore(store, anteKey)) 1354 1355 // execute at tx that will pass the ante handler (the checkTx state should 1356 // mutate) but will fail the message handler 1357 tx = newTxCounter(0, 0) 1358 tx.setFailOnHandler(true) 1359 1360 txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx) 1361 require.NoError(t, err) 1362 1363 res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1364 require.Empty(t, res.Events) 1365 require.False(t, res.IsOK(), fmt.Sprintf("%v", res)) 1366 1367 ctx = app.getState(runTxModeDeliver).ctx 1368 store = ctx.KVStore(capKey1) 1369 require.Equal(t, int64(1), getIntFromStore(store, anteKey)) 1370 require.Equal(t, int64(0), getIntFromStore(store, deliverKey)) 1371 1372 // execute a successful ante handler and message execution where state is 1373 // implicitly checked by previous tx executions 1374 tx = newTxCounter(1, 0) 1375 1376 txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx) 1377 require.NoError(t, err) 1378 1379 res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1380 require.NotEmpty(t, res.Events) 1381 require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) 1382 1383 ctx = app.getState(runTxModeDeliver).ctx 1384 store = ctx.KVStore(capKey1) 1385 require.Equal(t, int64(2), getIntFromStore(store, anteKey)) 1386 require.Equal(t, int64(1), getIntFromStore(store, deliverKey)) 1387 1388 // commit 1389 app.EndBlock(abci.RequestEndBlock{}) 1390 app.Commit(abci.RequestCommit{}) 1391 } 1392 1393 func TestGasConsumptionBadTx(t *testing.T) { 1394 gasWanted := uint64(5) 1395 anteOpt := func(bapp *BaseApp) { 1396 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 1397 newCtx = ctx 1398 newCtx.SetGasMeter(sdk.NewGasMeter(gasWanted)) 1399 1400 defer func() { 1401 if r := recover(); r != nil { 1402 switch rType := r.(type) { 1403 case sdk.ErrorOutOfGas: 1404 log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor) 1405 err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log) 1406 default: 1407 panic(r) 1408 } 1409 } 1410 }() 1411 1412 txTest := tx.(*txTest) 1413 newCtx.GasMeter().ConsumeGas(uint64(txTest.Counter), "counter-ante") 1414 if txTest.FailOnAnte { 1415 return newCtx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure") 1416 } 1417 1418 return 1419 }) 1420 } 1421 1422 routerOpt := func(bapp *BaseApp) { 1423 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 1424 count := msg.(msgCounter).Counter 1425 ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler") 1426 return &sdk.Result{}, nil 1427 }) 1428 } 1429 1430 cdc := codec.New() 1431 registerTestCodec(cdc) 1432 1433 app := setupBaseApp(t, anteOpt, routerOpt) 1434 app.InitChain(abci.RequestInitChain{ 1435 ConsensusParams: &abci.ConsensusParams{ 1436 Block: &abci.BlockParams{ 1437 MaxGas: 9, 1438 }, 1439 }, 1440 }) 1441 1442 app.InitChain(abci.RequestInitChain{}) 1443 1444 header := abci.Header{Height: app.LastBlockHeight() + 1} 1445 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1446 1447 tx := newTxCounter(5, 0) 1448 tx.setFailOnAnte(true) 1449 txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx) 1450 require.NoError(t, err) 1451 1452 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1453 require.False(t, res.IsOK(), fmt.Sprintf("%v", res)) 1454 1455 // require next tx to fail due to black gas limit 1456 tx = newTxCounter(5, 0) 1457 txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx) 1458 require.NoError(t, err) 1459 1460 res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1461 require.False(t, res.IsOK(), fmt.Sprintf("%v", res)) 1462 } 1463 1464 // Test that we can only query from the latest committed state. 1465 func TestQuery(t *testing.T) { 1466 key, value := []byte("hello"), []byte("goodbye") 1467 anteOpt := func(bapp *BaseApp) { 1468 bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { 1469 store := ctx.KVStore(capKey1) 1470 store.Set(key, value) 1471 return 1472 }) 1473 } 1474 1475 routerOpt := func(bapp *BaseApp) { 1476 bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 1477 store := ctx.KVStore(capKey1) 1478 store.Set(key, value) 1479 return &sdk.Result{}, nil 1480 }) 1481 } 1482 1483 app := setupBaseApp(t, anteOpt, routerOpt) 1484 1485 app.InitChain(abci.RequestInitChain{}) 1486 1487 // NOTE: "/store/key1" tells us KVStore 1488 // and the final "/key" says to use the data as the 1489 // key in the given KVStore ... 1490 query := abci.RequestQuery{ 1491 Path: "/store/key1/key", 1492 Data: key, 1493 } 1494 tx := newTxCounter(0, 0) 1495 1496 // query is empty before we do anything 1497 res := app.Query(query) 1498 require.Equal(t, 0, len(res.Value)) 1499 1500 // query is still empty after a CheckTx 1501 _, resTx, err := app.Check(tx) 1502 require.NoError(t, err) 1503 require.NotNil(t, resTx) 1504 res = app.Query(query) 1505 require.Equal(t, 0, len(res.Value)) 1506 1507 // query is still empty after a DeliverTx before we commit 1508 header := abci.Header{Height: app.LastBlockHeight() + 1} 1509 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1510 1511 _, resTx, err = app.Deliver(tx) 1512 require.NoError(t, err) 1513 require.NotNil(t, resTx) 1514 res = app.Query(query) 1515 require.Equal(t, 0, len(res.Value)) 1516 1517 // query returns correct value after Commit 1518 app.Commit(abci.RequestCommit{}) 1519 res = app.Query(query) 1520 require.Equal(t, value, res.Value) 1521 } 1522 1523 // Test p2p filter queries 1524 func TestP2PQuery(t *testing.T) { 1525 addrPeerFilterOpt := func(bapp *BaseApp) { 1526 bapp.SetAddrPeerFilter(func(addrport string) abci.ResponseQuery { 1527 require.Equal(t, "1.1.1.1:8000", addrport) 1528 return abci.ResponseQuery{Code: uint32(3)} 1529 }) 1530 } 1531 1532 idPeerFilterOpt := func(bapp *BaseApp) { 1533 bapp.SetIDPeerFilter(func(id string) abci.ResponseQuery { 1534 require.Equal(t, "testid", id) 1535 return abci.ResponseQuery{Code: uint32(4)} 1536 }) 1537 } 1538 1539 app := setupBaseApp(t, addrPeerFilterOpt, idPeerFilterOpt) 1540 1541 addrQuery := abci.RequestQuery{ 1542 Path: "/p2p/filter/addr/1.1.1.1:8000", 1543 } 1544 res := app.Query(addrQuery) 1545 require.Equal(t, uint32(3), res.Code) 1546 1547 idQuery := abci.RequestQuery{ 1548 Path: "/p2p/filter/id/testid", 1549 } 1550 res = app.Query(idQuery) 1551 require.Equal(t, uint32(4), res.Code) 1552 } 1553 1554 func TestGetMaximumBlockGas(t *testing.T) { 1555 app := setupBaseApp(t) 1556 1557 app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 0}}) 1558 require.Equal(t, uint64(0), app.getMaximumBlockGas()) 1559 1560 app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -1}}) 1561 require.Equal(t, uint64(0), app.getMaximumBlockGas()) 1562 1563 app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 5000000}}) 1564 require.Equal(t, uint64(5000000), app.getMaximumBlockGas()) 1565 1566 app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -5000000}}) 1567 require.Panics(t, func() { app.getMaximumBlockGas() }) 1568 } 1569 1570 // NOTE: represents a new custom router for testing purposes of WithRouter() 1571 type testCustomRouter struct { 1572 routes sync.Map 1573 } 1574 1575 func (rtr *testCustomRouter) AddRoute(path string, h sdk.Handler) sdk.Router { 1576 rtr.routes.Store(path, h) 1577 return rtr 1578 } 1579 1580 func (rtr *testCustomRouter) Route(ctx sdk.Context, path string) sdk.Handler { 1581 if v, ok := rtr.routes.Load(path); ok { 1582 if h, ok := v.(sdk.Handler); ok { 1583 return h 1584 } 1585 } 1586 return nil 1587 } 1588 1589 func TestWithRouter(t *testing.T) { 1590 // test increments in the ante 1591 anteKey := []byte("ante-key") 1592 anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } 1593 1594 // test increments in the handler 1595 deliverKey := []byte("deliver-key") 1596 routerOpt := func(bapp *BaseApp) { 1597 bapp.SetRouter(&testCustomRouter{routes: sync.Map{}}) 1598 bapp.Router().AddRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey)) 1599 } 1600 1601 app := setupBaseApp(t, anteOpt, routerOpt) 1602 app.InitChain(abci.RequestInitChain{}) 1603 1604 // Create same codec used in txDecoder 1605 codec := codec.New() 1606 registerTestCodec(codec) 1607 1608 nBlocks := 3 1609 txPerHeight := 5 1610 1611 for blockN := 0; blockN < nBlocks; blockN++ { 1612 header := abci.Header{Height: int64(blockN) + 1} 1613 app.BeginBlock(abci.RequestBeginBlock{Header: header}) 1614 1615 for i := 0; i < txPerHeight; i++ { 1616 counter := int64(blockN*txPerHeight + i) 1617 tx := newTxCounter(counter, counter) 1618 1619 txBytes, err := codec.MarshalBinaryLengthPrefixed(tx) 1620 require.NoError(t, err) 1621 1622 res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) 1623 require.True(t, res.IsOK(), fmt.Sprintf("%v", res)) 1624 } 1625 1626 app.EndBlock(abci.RequestEndBlock{}) 1627 app.Commit(abci.RequestCommit{}) 1628 } 1629 }