diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index f2a15a99f0..85ae034e25 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -9,8 +9,10 @@ import ( "github.com/pkg/errors" abci "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,6 +25,9 @@ type BaseApp struct { // Application name from abci.Info name string + // Common DB backend + db dbm.DB + // Main (uncached) state ms sdk.CommitMultiStore @@ -53,19 +58,43 @@ type BaseApp struct { var _ abci.Application = &BaseApp{} -func NewBaseApp(name string, ms sdk.CommitMultiStore) *BaseApp { - return &BaseApp{ +func NewBaseApp(name string) *BaseApp { + var baseapp = &BaseApp{ logger: makeDefaultLogger(), name: name, - ms: ms, + db: nil, + ms: nil, router: NewRouter(), } + baseapp.initDB() + baseapp.initMultiStore() + return baseapp +} + +// Create the underlying leveldb datastore which will +// persist the Merkle tree inner & leaf nodes. +func (app *BaseApp) initDB() { + db, err := dbm.NewGoLevelDB(app.name, "data") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + app.db = db +} + +func (app *BaseApp) initMultiStore() { + ms := store.NewCommitMultiStore(app.db) + app.ms = ms } func (app *BaseApp) Name() string { return app.name } +func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { + app.ms.MountStoreWithDB(key, typ, app.db) +} + func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { app.txDecoder = txDecoder } @@ -84,12 +113,12 @@ func (app *BaseApp) SetEndBlocker(...) {} func (app *BaseApp) SetInitStater(...) {} */ -func (app *BaseApp) LoadLatestVersion(mainKey sdk.SubstoreKey) error { +func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error { app.ms.LoadLatestVersion() return app.initFromStore(mainKey) } -func (app *BaseApp) LoadVersion(version int64, mainKey sdk.SubstoreKey) error { +func (app *BaseApp) LoadVersion(version int64, mainKey sdk.StoreKey) error { app.ms.LoadVersion(version) return app.initFromStore(mainKey) } @@ -105,7 +134,7 @@ func (app *BaseApp) LastBlockHeight() int64 { } // Initializes the remaining logic from app.ms. -func (app *BaseApp) initFromStore(mainKey sdk.SubstoreKey) error { +func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { lastCommitID := app.ms.LastCommitID() main := app.ms.GetKVStore(mainKey) header := abci.Header{} diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 6178faf77a..e6429a54cd 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -13,7 +13,6 @@ import ( cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" - "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -34,10 +33,10 @@ func (tx testTx) GetFeePayer() crypto.Address { return nil } func (tx testTx) GetSignatures() []sdk.StdSignature { return nil } func TestBasic(t *testing.T) { - store, storeKeys := newCommitMultiStore() // Create app. - app := NewBaseApp(t.Name(), store) + app := NewBaseApp(t.Name()) + storeKeys := createMounts(app.ms) app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, error) { var ttx testTx fromJSON(txBytes, &ttx) @@ -161,16 +160,15 @@ func fromJSON(bz []byte, ptr interface{}) { } } -// Creates a sample CommitMultiStore -func newCommitMultiStore() (sdk.CommitMultiStore, map[string]sdk.SubstoreKey) { +// Mounts stores to CommitMultiStore and returns a map of keys. +func createMounts(ms sdk.CommitMultiStore) map[string]sdk.StoreKey { dbMain := dbm.NewMemDB() dbXtra := dbm.NewMemDB() keyMain := sdk.NewKVStoreKey("main") keyXtra := sdk.NewKVStoreKey("xtra") - ms := store.NewCommitMultiStore(dbMain) // Also store rootMultiStore metadata here (it shouldn't clash) - ms.SetSubstoreLoader(keyMain, store.NewIAVLStoreLoader(dbMain, 0, 0)) - ms.SetSubstoreLoader(keyXtra, store.NewIAVLStoreLoader(dbXtra, 0, 0)) - return ms, map[string]sdk.SubstoreKey{ + ms.MountStoreWithDB(keyMain, sdk.StoreTypeIAVL, dbMain) + ms.MountStoreWithDB(keyXtra, sdk.StoreTypeIAVL, dbXtra) + return map[string]sdk.StoreKey{ "main": keyMain, "xtra": keyXtra, } diff --git a/baseapp/data/TestBasic.db/CURRENT b/baseapp/data/TestBasic.db/CURRENT new file mode 100644 index 0000000000..f60e23b00c --- /dev/null +++ b/baseapp/data/TestBasic.db/CURRENT @@ -0,0 +1 @@ +MANIFEST-000093 diff --git a/baseapp/data/TestBasic.db/LOCK b/baseapp/data/TestBasic.db/LOCK new file mode 100644 index 0000000000..e69de29bb2 diff --git a/baseapp/data/TestBasic.db/LOG b/baseapp/data/TestBasic.db/LOG new file mode 100644 index 0000000000..17b9327756 --- /dev/null +++ b/baseapp/data/TestBasic.db/LOG @@ -0,0 +1,420 @@ +=============== Jan 22, 2018 (PST) =============== +02:20:20.667917 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:20:20.669178 db@open opening +02:20:20.670364 version@stat F·[] S·0B[] Sc·[] +02:20:20.671142 db@janitor F·2 G·0 +02:20:20.671220 db@open done T·2.00865ms +=============== Jan 22, 2018 (PST) =============== +02:27:52.315693 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:27:52.318778 version@stat F·[] S·0B[] Sc·[] +02:27:52.318804 db@open opening +02:27:52.318899 journal@recovery F·1 +02:27:52.319610 journal@recovery recovering @1 +02:27:52.320363 version@stat F·[] S·0B[] Sc·[] +02:27:52.325449 db@janitor F·2 G·0 +02:27:52.325491 db@open done T·6.669068ms +=============== Jan 22, 2018 (PST) =============== +02:39:24.323804 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:39:24.327668 version@stat F·[] S·0B[] Sc·[] +02:39:24.327701 db@open opening +02:39:24.327808 journal@recovery F·1 +02:39:24.328648 journal@recovery recovering @2 +02:39:24.329207 version@stat F·[] S·0B[] Sc·[] +02:39:24.330194 db@janitor F·2 G·0 +02:39:24.330239 db@open done T·2.516353ms +=============== Jan 22, 2018 (PST) =============== +02:41:39.198692 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:41:39.203178 version@stat F·[] S·0B[] Sc·[] +02:41:39.203249 db@open opening +02:41:39.203444 journal@recovery F·1 +02:41:39.204117 journal@recovery recovering @4 +02:41:39.205805 version@stat F·[] S·0B[] Sc·[] +02:41:39.206992 db@janitor F·2 G·0 +02:41:39.207042 db@open done T·3.766041ms +=============== Jan 22, 2018 (PST) =============== +02:57:12.571189 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:57:12.573329 version@stat F·[] S·0B[] Sc·[] +02:57:12.573380 db@open opening +02:57:12.573519 journal@recovery F·1 +02:57:12.574112 journal@recovery recovering @6 +02:57:12.574817 version@stat F·[] S·0B[] Sc·[] +02:57:12.578908 db@janitor F·2 G·0 +02:57:12.578955 db@open done T·5.556429ms +=============== Jan 22, 2018 (PST) =============== +02:58:51.899628 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +02:58:51.902315 version@stat F·[] S·0B[] Sc·[] +02:58:51.902351 db@open opening +02:58:51.902471 journal@recovery F·1 +02:58:51.904243 journal@recovery recovering @8 +02:58:51.904941 version@stat F·[] S·0B[] Sc·[] +02:58:51.905884 db@janitor F·2 G·0 +02:58:51.905916 db@open done T·3.55323ms +=============== Jan 22, 2018 (PST) =============== +03:00:17.452727 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:00:17.453633 version@stat F·[] S·0B[] Sc·[] +03:00:17.453654 db@open opening +03:00:17.453738 journal@recovery F·1 +03:00:17.454316 journal@recovery recovering @10 +03:00:17.455239 version@stat F·[] S·0B[] Sc·[] +03:00:17.456169 db@janitor F·2 G·0 +03:00:17.456208 db@open done T·2.537364ms +=============== Jan 22, 2018 (PST) =============== +03:00:57.872703 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:00:57.873215 version@stat F·[] S·0B[] Sc·[] +03:00:57.873238 db@open opening +03:00:57.873328 journal@recovery F·1 +03:00:57.873907 journal@recovery recovering @12 +03:00:57.874695 version@stat F·[] S·0B[] Sc·[] +03:00:57.876608 db@janitor F·2 G·0 +03:00:57.876666 db@open done T·3.402072ms +=============== Jan 22, 2018 (PST) =============== +03:01:36.381066 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:01:36.381545 version@stat F·[] S·0B[] Sc·[] +03:01:36.381564 db@open opening +03:01:36.381635 journal@recovery F·1 +03:01:36.382594 journal@recovery recovering @14 +03:01:36.383313 version@stat F·[] S·0B[] Sc·[] +03:01:36.384570 db@janitor F·2 G·0 +03:01:36.384605 db@open done T·3.029926ms +=============== Jan 22, 2018 (PST) =============== +03:01:50.485546 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:01:50.486053 version@stat F·[] S·0B[] Sc·[] +03:01:50.486077 db@open opening +03:01:50.486165 journal@recovery F·1 +03:01:50.486683 journal@recovery recovering @16 +03:01:50.487657 version@stat F·[] S·0B[] Sc·[] +03:01:50.489725 db@janitor F·2 G·0 +03:01:50.489769 db@open done T·3.678486ms +=============== Jan 22, 2018 (PST) =============== +03:03:21.912077 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:03:21.912536 version@stat F·[] S·0B[] Sc·[] +03:03:21.912555 db@open opening +03:03:21.912621 journal@recovery F·1 +03:03:21.913109 journal@recovery recovering @18 +03:03:21.913875 version@stat F·[] S·0B[] Sc·[] +03:03:21.914859 db@janitor F·2 G·0 +03:03:21.914893 db@open done T·2.321933ms +=============== Jan 22, 2018 (PST) =============== +03:03:38.788932 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:03:38.789374 version@stat F·[] S·0B[] Sc·[] +03:03:38.789394 db@open opening +03:03:38.789469 journal@recovery F·1 +03:03:38.790271 journal@recovery recovering @20 +03:03:38.791021 version@stat F·[] S·0B[] Sc·[] +03:03:38.794175 db@janitor F·2 G·0 +03:03:38.794214 db@open done T·4.8086ms +=============== Jan 22, 2018 (PST) =============== +03:05:02.619429 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:05:02.624450 version@stat F·[] S·0B[] Sc·[] +03:05:02.624479 db@open opening +03:05:02.624587 journal@recovery F·1 +03:05:02.625197 journal@recovery recovering @22 +03:05:02.625703 version@stat F·[] S·0B[] Sc·[] +03:05:02.628444 db@janitor F·2 G·0 +03:05:02.628485 db@open done T·3.985771ms +=============== Jan 22, 2018 (PST) =============== +03:07:58.079511 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:07:58.081652 version@stat F·[] S·0B[] Sc·[] +03:07:58.081683 db@open opening +03:07:58.081791 journal@recovery F·1 +03:07:58.082336 journal@recovery recovering @24 +03:07:58.083090 version@stat F·[] S·0B[] Sc·[] +03:07:58.084133 db@janitor F·2 G·0 +03:07:58.084183 db@open done T·2.477889ms +=============== Jan 22, 2018 (PST) =============== +03:11:36.208112 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:11:36.209248 version@stat F·[] S·0B[] Sc·[] +03:11:36.209277 db@open opening +03:11:36.209375 journal@recovery F·1 +03:11:36.209819 journal@recovery recovering @26 +03:11:36.210667 version@stat F·[] S·0B[] Sc·[] +03:11:36.212096 db@janitor F·2 G·0 +03:11:36.212146 db@open done T·2.854122ms +=============== Jan 22, 2018 (PST) =============== +03:14:28.381204 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:14:28.381597 version@stat F·[] S·0B[] Sc·[] +03:14:28.381614 db@open opening +03:14:28.381679 journal@recovery F·1 +03:14:28.382166 journal@recovery recovering @28 +03:14:28.382925 version@stat F·[] S·0B[] Sc·[] +03:14:28.384890 db@janitor F·2 G·0 +03:14:28.384938 db@open done T·3.305166ms +=============== Jan 22, 2018 (PST) =============== +03:16:57.807253 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:16:57.809148 version@stat F·[] S·0B[] Sc·[] +03:16:57.809176 db@open opening +03:16:57.809276 journal@recovery F·1 +03:16:57.809798 journal@recovery recovering @30 +03:16:57.810708 version@stat F·[] S·0B[] Sc·[] +03:16:57.811999 db@janitor F·2 G·0 +03:16:57.812056 db@open done T·2.854877ms +=============== Jan 22, 2018 (PST) =============== +03:19:27.065541 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:19:27.065963 version@stat F·[] S·0B[] Sc·[] +03:19:27.065982 db@open opening +03:19:27.066064 journal@recovery F·1 +03:19:27.066462 journal@recovery recovering @32 +03:19:27.067345 version@stat F·[] S·0B[] Sc·[] +03:19:27.070968 db@janitor F·2 G·0 +03:19:27.071015 db@open done T·5.013804ms +=============== Jan 22, 2018 (PST) =============== +03:19:52.706551 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:19:52.707024 version@stat F·[] S·0B[] Sc·[] +03:19:52.707047 db@open opening +03:19:52.707126 journal@recovery F·1 +03:19:52.707560 journal@recovery recovering @34 +03:19:52.708117 version@stat F·[] S·0B[] Sc·[] +03:19:52.711284 db@janitor F·2 G·0 +03:19:52.711329 db@open done T·4.267678ms +=============== Jan 22, 2018 (PST) =============== +03:26:24.468105 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:26:24.468552 version@stat F·[] S·0B[] Sc·[] +03:26:24.468575 db@open opening +03:26:24.468656 journal@recovery F·1 +03:26:24.469267 journal@recovery recovering @36 +03:26:24.469846 version@stat F·[] S·0B[] Sc·[] +03:26:24.474595 db@janitor F·2 G·0 +03:26:24.474636 db@open done T·6.04411ms +=============== Jan 22, 2018 (PST) =============== +03:51:35.032653 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +03:51:35.042632 version@stat F·[] S·0B[] Sc·[] +03:51:35.042659 db@open opening +03:51:35.042744 journal@recovery F·1 +03:51:35.043196 journal@recovery recovering @38 +03:51:35.043841 version@stat F·[] S·0B[] Sc·[] +03:51:35.050746 db@janitor F·2 G·0 +03:51:35.050789 db@open done T·8.116551ms +=============== Jan 22, 2018 (PST) =============== +04:00:26.747278 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:00:26.752301 version@stat F·[] S·0B[] Sc·[] +04:00:26.752343 db@open opening +04:00:26.752454 journal@recovery F·1 +04:00:26.752901 journal@recovery recovering @40 +04:00:26.753349 version@stat F·[] S·0B[] Sc·[] +04:00:26.757743 db@janitor F·2 G·0 +04:00:26.757778 db@open done T·5.422834ms +=============== Jan 22, 2018 (PST) =============== +04:01:46.178175 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:01:46.178655 version@stat F·[] S·0B[] Sc·[] +04:01:46.178674 db@open opening +04:01:46.178775 journal@recovery F·1 +04:01:46.179347 journal@recovery recovering @42 +04:01:46.180154 version@stat F·[] S·0B[] Sc·[] +04:01:46.182310 db@janitor F·2 G·0 +04:01:46.182338 db@open done T·3.652952ms +=============== Jan 22, 2018 (PST) =============== +04:04:19.070666 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:04:19.072779 version@stat F·[] S·0B[] Sc·[] +04:04:19.072810 db@open opening +04:04:19.072914 journal@recovery F·1 +04:04:19.073398 journal@recovery recovering @44 +04:04:19.074134 version@stat F·[] S·0B[] Sc·[] +04:04:19.075029 db@janitor F·2 G·0 +04:04:19.075068 db@open done T·2.240164ms +=============== Jan 22, 2018 (PST) =============== +04:05:59.580740 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:05:59.581283 version@stat F·[] S·0B[] Sc·[] +04:05:59.581301 db@open opening +04:05:59.581379 journal@recovery F·1 +04:05:59.582237 journal@recovery recovering @46 +04:05:59.583953 version@stat F·[] S·0B[] Sc·[] +04:05:59.585436 db@janitor F·2 G·0 +04:05:59.585473 db@open done T·4.160567ms +=============== Jan 22, 2018 (PST) =============== +04:08:47.738599 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:08:47.739083 version@stat F·[] S·0B[] Sc·[] +04:08:47.739105 db@open opening +04:08:47.739183 journal@recovery F·1 +04:08:47.739692 journal@recovery recovering @48 +04:08:47.740466 version@stat F·[] S·0B[] Sc·[] +04:08:47.741410 db@janitor F·2 G·0 +04:08:47.741444 db@open done T·2.3276ms +=============== Jan 22, 2018 (PST) =============== +04:10:08.775252 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:10:08.775687 version@stat F·[] S·0B[] Sc·[] +04:10:08.775705 db@open opening +04:10:08.775773 journal@recovery F·1 +04:10:08.776486 journal@recovery recovering @50 +04:10:08.777122 version@stat F·[] S·0B[] Sc·[] +04:10:08.778919 db@janitor F·2 G·0 +04:10:08.778961 db@open done T·3.245071ms +=============== Jan 22, 2018 (PST) =============== +04:14:32.971220 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:14:32.971922 version@stat F·[] S·0B[] Sc·[] +04:14:32.971962 db@open opening +04:14:32.972095 journal@recovery F·1 +04:14:32.973033 journal@recovery recovering @52 +04:14:32.973725 version@stat F·[] S·0B[] Sc·[] +04:14:32.976332 db@janitor F·2 G·0 +04:14:32.976389 db@open done T·4.40961ms +=============== Jan 22, 2018 (PST) =============== +04:16:46.446923 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:16:46.447439 version@stat F·[] S·0B[] Sc·[] +04:16:46.447465 db@open opening +04:16:46.447546 journal@recovery F·1 +04:16:46.448532 journal@recovery recovering @54 +04:16:46.449082 version@stat F·[] S·0B[] Sc·[] +04:16:46.451474 db@janitor F·2 G·0 +04:16:46.451531 db@open done T·4.048125ms +=============== Jan 22, 2018 (PST) =============== +04:19:13.453357 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:19:13.453932 version@stat F·[] S·0B[] Sc·[] +04:19:13.453978 db@open opening +04:19:13.454085 journal@recovery F·1 +04:19:13.454789 journal@recovery recovering @56 +04:19:13.455675 version@stat F·[] S·0B[] Sc·[] +04:19:13.456803 db@janitor F·2 G·0 +04:19:13.456844 db@open done T·2.844553ms +=============== Jan 22, 2018 (PST) =============== +04:20:33.271529 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:20:33.271936 version@stat F·[] S·0B[] Sc·[] +04:20:33.271954 db@open opening +04:20:33.272022 journal@recovery F·1 +04:20:33.272647 journal@recovery recovering @58 +04:20:33.273143 version@stat F·[] S·0B[] Sc·[] +04:20:33.274043 db@janitor F·2 G·0 +04:20:33.274078 db@open done T·2.113985ms +=============== Jan 22, 2018 (PST) =============== +04:25:19.055938 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:25:19.056763 version@stat F·[] S·0B[] Sc·[] +04:25:19.056786 db@open opening +04:25:19.056865 journal@recovery F·1 +04:25:19.057455 journal@recovery recovering @60 +04:25:19.058377 version@stat F·[] S·0B[] Sc·[] +04:25:19.059353 db@janitor F·2 G·0 +04:25:19.059392 db@open done T·2.591721ms +=============== Jan 22, 2018 (PST) =============== +04:26:26.431263 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:26:26.431696 version@stat F·[] S·0B[] Sc·[] +04:26:26.431717 db@open opening +04:26:26.431796 journal@recovery F·1 +04:26:26.432411 journal@recovery recovering @62 +04:26:26.433010 version@stat F·[] S·0B[] Sc·[] +04:26:26.434881 db@janitor F·2 G·0 +04:26:26.434916 db@open done T·3.187393ms +=============== Jan 22, 2018 (PST) =============== +04:28:19.118769 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:28:19.122566 version@stat F·[] S·0B[] Sc·[] +04:28:19.122603 db@open opening +04:28:19.122690 journal@recovery F·1 +04:28:19.123248 journal@recovery recovering @64 +04:28:19.124085 version@stat F·[] S·0B[] Sc·[] +04:28:19.126908 db@janitor F·2 G·0 +04:28:19.126954 db@open done T·4.333898ms +=============== Jan 22, 2018 (PST) =============== +04:32:40.558885 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:32:40.561056 version@stat F·[] S·0B[] Sc·[] +04:32:40.561082 db@open opening +04:32:40.561204 journal@recovery F·1 +04:32:40.561690 journal@recovery recovering @66 +04:32:40.562239 version@stat F·[] S·0B[] Sc·[] +04:32:40.563112 db@janitor F·2 G·0 +04:32:40.563144 db@open done T·2.049673ms +=============== Jan 22, 2018 (PST) =============== +04:37:25.167274 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:37:25.167662 version@stat F·[] S·0B[] Sc·[] +04:37:25.167681 db@open opening +04:37:25.167752 journal@recovery F·1 +04:37:25.168247 journal@recovery recovering @68 +04:37:25.168861 version@stat F·[] S·0B[] Sc·[] +04:37:25.172909 db@janitor F·2 G·0 +04:37:25.172941 db@open done T·5.247885ms +=============== Jan 22, 2018 (PST) =============== +04:54:28.500444 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +04:54:28.502945 version@stat F·[] S·0B[] Sc·[] +04:54:28.502974 db@open opening +04:54:28.503070 journal@recovery F·1 +04:54:28.503627 journal@recovery recovering @70 +04:54:28.504124 version@stat F·[] S·0B[] Sc·[] +04:54:28.505062 db@janitor F·2 G·0 +04:54:28.505094 db@open done T·2.108477ms +=============== Jan 22, 2018 (PST) =============== +05:01:19.593801 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:01:19.594788 version@stat F·[] S·0B[] Sc·[] +05:01:19.594816 db@open opening +05:01:19.594915 journal@recovery F·1 +05:01:19.595496 journal@recovery recovering @72 +05:01:19.596370 version@stat F·[] S·0B[] Sc·[] +05:01:19.597244 db@janitor F·2 G·0 +05:01:19.597282 db@open done T·2.449363ms +=============== Jan 22, 2018 (PST) =============== +05:04:29.471458 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:04:29.472662 version@stat F·[] S·0B[] Sc·[] +05:04:29.472713 db@open opening +05:04:29.472793 journal@recovery F·1 +05:04:29.473425 journal@recovery recovering @74 +05:04:29.474375 version@stat F·[] S·0B[] Sc·[] +05:04:29.475638 db@janitor F·2 G·0 +05:04:29.475673 db@open done T·2.942159ms +=============== Jan 22, 2018 (PST) =============== +05:05:42.278156 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:05:42.280920 version@stat F·[] S·0B[] Sc·[] +05:05:42.280947 db@open opening +05:05:42.281037 journal@recovery F·1 +05:05:42.281647 journal@recovery recovering @76 +05:05:42.282651 version@stat F·[] S·0B[] Sc·[] +05:05:42.283610 db@janitor F·2 G·0 +05:05:42.283651 db@open done T·2.681388ms +=============== Jan 22, 2018 (PST) =============== +05:08:45.319211 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:08:45.321023 version@stat F·[] S·0B[] Sc·[] +05:08:45.321052 db@open opening +05:08:45.321146 journal@recovery F·1 +05:08:45.321705 journal@recovery recovering @78 +05:08:45.322648 version@stat F·[] S·0B[] Sc·[] +05:08:45.323706 db@janitor F·2 G·0 +05:08:45.323745 db@open done T·2.679774ms +=============== Jan 22, 2018 (PST) =============== +05:11:06.661289 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:11:06.663188 version@stat F·[] S·0B[] Sc·[] +05:11:06.663212 db@open opening +05:11:06.663295 journal@recovery F·1 +05:11:06.663847 journal@recovery recovering @80 +05:11:06.665202 version@stat F·[] S·0B[] Sc·[] +05:11:06.666547 db@janitor F·2 G·0 +05:11:06.666578 db@open done T·3.354587ms +=============== Jan 22, 2018 (PST) =============== +05:22:20.522602 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:22:20.523062 version@stat F·[] S·0B[] Sc·[] +05:22:20.523085 db@open opening +05:22:20.523167 journal@recovery F·1 +05:22:20.523757 journal@recovery recovering @82 +05:22:20.524506 version@stat F·[] S·0B[] Sc·[] +05:22:20.527683 db@janitor F·2 G·0 +05:22:20.527721 db@open done T·4.623285ms +=============== Jan 22, 2018 (PST) =============== +05:30:31.524125 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:30:31.532140 version@stat F·[] S·0B[] Sc·[] +05:30:31.532175 db@open opening +05:30:31.532272 journal@recovery F·1 +05:30:31.532768 journal@recovery recovering @84 +05:30:31.534159 version@stat F·[] S·0B[] Sc·[] +05:30:31.547317 db@janitor F·2 G·0 +05:30:31.547374 db@open done T·15.185802ms +=============== Jan 22, 2018 (PST) =============== +05:40:55.450366 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:40:55.453870 version@stat F·[] S·0B[] Sc·[] +05:40:55.453918 db@open opening +05:40:55.454007 journal@recovery F·1 +05:40:55.454895 journal@recovery recovering @86 +05:40:55.455571 version@stat F·[] S·0B[] Sc·[] +05:40:55.456543 db@janitor F·2 G·0 +05:40:55.456633 db@open done T·2.696868ms +=============== Jan 22, 2018 (PST) =============== +05:41:38.813921 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:41:38.814486 version@stat F·[] S·0B[] Sc·[] +05:41:38.814507 db@open opening +05:41:38.814578 journal@recovery F·1 +05:41:38.815205 journal@recovery recovering @88 +05:41:38.816356 version@stat F·[] S·0B[] Sc·[] +05:41:38.817324 db@janitor F·2 G·0 +05:41:38.817368 db@open done T·2.839844ms +=============== Jan 22, 2018 (PST) =============== +05:42:55.588810 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +05:42:55.590533 version@stat F·[] S·0B[] Sc·[] +05:42:55.590560 db@open opening +05:42:55.590659 journal@recovery F·1 +05:42:55.591190 journal@recovery recovering @90 +05:42:55.592176 version@stat F·[] S·0B[] Sc·[] +05:42:55.593166 db@janitor F·2 G·0 +05:42:55.593205 db@open done T·2.623485ms diff --git a/baseapp/data/TestBasic.db/MANIFEST-000093 b/baseapp/data/TestBasic.db/MANIFEST-000093 new file mode 100644 index 0000000000..3dd27a15fa Binary files /dev/null and b/baseapp/data/TestBasic.db/MANIFEST-000093 differ diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 65a73367b5..ba9c0993c3 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -19,11 +19,11 @@ type BasecoinApp struct { multiStore sdk.CommitMultiStore // The key to access the substores. - mainStoreKey *sdk.KVStoreKey - ibcStoreKey *sdk.KVStoreKey + capKeyMainStore *sdk.KVStoreKey + capKeyIBCStore *sdk.KVStoreKey - // Additional stores: - accStore sdk.AccountStore + // Object mappers : + accountMapper sdk.AccountMapper } // TODO: This should take in more configuration options. @@ -32,8 +32,8 @@ func NewBasecoinApp() *BasecoinApp { // Create and configure app. var app = &BasecoinApp{} app.initCapKeys() // ./init_capkeys.go - app.initStores() // ./init_stores.go app.initBaseApp() // ./init_baseapp.go + app.initStores() // ./init_stores.go app.initRoutes() // ./init_routes.go // TODO: Load genesis @@ -65,7 +65,7 @@ func (app *BasecoinApp) RunForever() { // Load the stores. func (app *BasecoinApp) loadStores() { - if err := app.LoadLatestVersion(app.mainStoreKey); err != nil { + if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil { fmt.Println(err) os.Exit(1) } diff --git a/examples/basecoin/app/init_baseapp.go b/examples/basecoin/app/init_baseapp.go index 0902d3adff..6fd3fb292b 100644 --- a/examples/basecoin/app/init_baseapp.go +++ b/examples/basecoin/app/init_baseapp.go @@ -6,10 +6,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" ) -// initBaseApp() happens after initCapKeys() and initStores(). -// initBaseApp() happens before initRoutes(). +// initCapKeys, initBaseApp, initStores, initRoutes. func (app *BasecoinApp) initBaseApp() { - app.BaseApp = baseapp.NewBaseApp(appName, app.multiStore) + app.BaseApp = baseapp.NewBaseApp(appName) app.initBaseAppTxDecoder() app.initBaseAppAnteHandler() } @@ -24,6 +23,6 @@ func (app *BasecoinApp) initBaseAppTxDecoder() { } func (app *BasecoinApp) initBaseAppAnteHandler() { - var authAnteHandler = auth.NewAnteHandler(app.accStore) + var authAnteHandler = auth.NewAnteHandler(app.accountMapper) app.BaseApp.SetDefaultAnteHandler(authAnteHandler) } diff --git a/examples/basecoin/app/init_capkeys.go b/examples/basecoin/app/init_capkeys.go index 94e69917fe..221565011e 100644 --- a/examples/basecoin/app/init_capkeys.go +++ b/examples/basecoin/app/init_capkeys.go @@ -4,13 +4,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// initCapKeys() happens before initStores(), initSDKApp(), and initRoutes(). +// initCapKeys, initBaseApp, initStores, initRoutes. func (app *BasecoinApp) initCapKeys() { // All top-level capabilities keys // should be constructed here. // For more information, see http://www.erights.org/elib/capability/ode/ode.pdf. - app.mainStoreKey = sdk.NewKVStoreKey("main") - app.ibcStoreKey = sdk.NewKVStoreKey("ibc") + app.capKeyMainStore = sdk.NewKVStoreKey("main") + app.capKeyIBCStore = sdk.NewKVStoreKey("ibc") } diff --git a/examples/basecoin/app/init_routes.go b/examples/basecoin/app/init_routes.go index 9da53aa34b..1e8e0a4272 100644 --- a/examples/basecoin/app/init_routes.go +++ b/examples/basecoin/app/init_routes.go @@ -4,12 +4,12 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" ) -// initRoutes() happens after initCapKeys(), initStores(), and initSDKApp(). +// initCapKeys, initBaseApp, initStores, initRoutes. func (app *BasecoinApp) initRoutes() { var router = app.BaseApp.Router() - var accStore = app.accStore + var accountMapper = app.accountMapper // All handlers must be added here. // The order matters. - router.AddRoute("bank", bank.NewHandler(accStore)) + router.AddRoute("bank", bank.NewHandler(accountMapper)) } diff --git a/examples/basecoin/app/init_stores.go b/examples/basecoin/app/init_stores.go index 8abb5919b5..dbd1d2538b 100644 --- a/examples/basecoin/app/init_stores.go +++ b/examples/basecoin/app/init_stores.go @@ -1,61 +1,38 @@ package app import ( - "fmt" - "os" - "github.com/cosmos/cosmos-sdk/examples/basecoin/types" - "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - dbm "github.com/tendermint/tmlibs/db" ) -// initStores() happens after initCapKeys(), but before initSDKApp() and initRoutes(). +// initCapKeys, initBaseApp, initStores, initRoutes. func (app *BasecoinApp) initStores() { - app.initMultiStore() - app.initAccountStore() + app.mountStores() + app.initAccountMapper() } -// Initialize root MultiStore. -func (app *BasecoinApp) initMultiStore() { +// Initialize root stores. +func (app *BasecoinApp) mountStores() { - // Create the underlying leveldb datastore which will - // persist the Merkle tree inner & leaf nodes. - db, err := dbm.NewGoLevelDB("basecoin", "basecoin-data") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - // Create CommitStoreLoader. - cacheSize := 10000 - numHistory := int64(100) - mainLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory) - ibcLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory) - - // Create MultiStore - multiStore := store.NewCommitMultiStore(db) - multiStore.SetSubstoreLoader(app.mainStoreKey, mainLoader) - multiStore.SetSubstoreLoader(app.ibcStoreKey, ibcLoader) - - // Finally, - app.multiStore = multiStore + // Create MultiStore mounts. + app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) + app.BaseApp.MountStore(app.capKeyIBCStore, sdk.StoreTypeIAVL) } -// Initialize the AccountStore, which accesses the MultiStore. -func (app *BasecoinApp) initAccountStore() { - accStore := auth.NewAccountStore( - // where accounts are persisted in the MultiStore. - app.mainStoreKey, - // prototype sdk.Account. - &types.AppAccount{}, +// Initialize the AccountMapper. +func (app *BasecoinApp) initAccountMapper() { + + var accountMapper = auth.NewAccountMapper( + app.capKeyMainStore, // target store + &types.AppAccount{}, // prototype ) - // If there are additional interfaces & concrete types that - // need to be registered w/ wire.Codec, they can be registered - // here before the accStore is sealed. - cdc := accStore.WireCodec() + // Register all interfaces and concrete types that + // implement those interfaces, here. + cdc := accountMapper.WireCodec() auth.RegisterWireBaseAccount(cdc) - app.accStore = accStore.Seal() + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() } diff --git a/examples/dummy/main.go b/examples/dummy/main.go index 95806db615..f4b343e4f8 100644 --- a/examples/dummy/main.go +++ b/examples/dummy/main.go @@ -8,42 +8,30 @@ import ( "github.com/tendermint/abci/server" crypto "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" - dbm "github.com/tendermint/tmlibs/db" bam "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" ) func main() { - db, err := dbm.NewGoLevelDB("dummy", "dummy-data") - if err != nil { - fmt.Println(err) - os.Exit(1) - } + // Capabilities key to access the main KVStore. + var capKeyMainStore = sdk.NewKVStoreKey("main") - // create CommitStoreLoader - cacheSize := 10000 - numHistory := int64(100) - loader := store.NewIAVLStoreLoader(db, cacheSize, numHistory) + // Create BaseApp. + var baseApp = bam.NewBaseApp("dummy") - // key to access the main KVStore - var mainStoreKey = sdk.NewKVStoreKey("main") - - // Create MultiStore - multiStore := store.NewCommitMultiStore(db) - multiStore.SetSubstoreLoader(mainStoreKey, loader) - - // Set everything on the baseApp and load latest - baseApp := bam.NewBaseApp("dummy", multiStore) + // Set mounts for BaseApp's MultiStore. + baseApp.MountStore(capKeyMainStore, sdk.StoreTypeIAVL) // Set Tx decoder baseApp.SetTxDecoder(decodeTx) - baseApp.Router().AddRoute("dummy", DummyHandler(mainStoreKey)) + // Set a handler Route. + baseApp.Router().AddRoute("dummy", DummyHandler(capKeyMainStore)) - if err := baseApp.LoadLatestVersion(mainStoreKey); err != nil { + // Load latest version. + if err := baseApp.LoadLatestVersion(capKeyMainStore); err != nil { fmt.Println(err) os.Exit(1) } @@ -126,7 +114,7 @@ func decodeTx(txBytes []byte) (sdk.Tx, error) { return tx, nil } -func DummyHandler(storeKey sdk.SubstoreKey) sdk.Handler { +func DummyHandler(storeKey sdk.StoreKey) sdk.Handler { return func(ctx sdk.Context, tx sdk.Tx) sdk.Result { // tx is already unmarshalled key := tx.Get("key").([]byte) diff --git a/glide.lock b/glide.lock index efe1f490b3..4b0ada82f7 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: e8435271aa9fdfc49efff9016427eca1fd6b43093a17187619360edda9f265e6 -updated: 2018-01-21T19:17:17.451995428-08:00 +updated: 2018-01-21T20:59:37.606138723-08:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -91,7 +91,7 @@ imports: subpackages: - keys - name: github.com/tendermint/go-wire - version: 0cce10e82786f2d501827fbe158747dbc4ceeb43 + version: c7801c1586f51bb28028cd420c599516d7ac9c36 subpackages: - data - name: github.com/tendermint/iavl diff --git a/store/cachekvstore.go b/store/cachekvstore.go index d2f0c10b2f..e075e7847b 100644 --- a/store/cachekvstore.go +++ b/store/cachekvstore.go @@ -35,6 +35,12 @@ func NewCacheKVStore(parent KVStore) *cacheKVStore { return ci } +// Implements Store. +func (ci *cacheKVStore) GetStoreType() StoreType { + return ci.parent.GetStoreType() +} + +// Implements KVStore. func (ci *cacheKVStore) Get(key []byte) (value []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() @@ -51,6 +57,7 @@ func (ci *cacheKVStore) Get(key []byte) (value []byte) { return value } +// Implements KVStore. func (ci *cacheKVStore) Set(key []byte, value []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() @@ -59,11 +66,13 @@ func (ci *cacheKVStore) Set(key []byte, value []byte) { ci.setCacheValue(key, value, false, true) } +// Implements KVStore. func (ci *cacheKVStore) Has(key []byte) bool { value := ci.Get(key) return value != nil } +// Implements KVStore. func (ci *cacheKVStore) Delete(key []byte) { ci.mtx.Lock() defer ci.mtx.Unlock() @@ -72,7 +81,7 @@ func (ci *cacheKVStore) Delete(key []byte) { ci.setCacheValue(key, nil, true, true) } -// Write writes pending updates to the parent database and clears the cache. +// Implements CacheKVStore. func (ci *cacheKVStore) Write() { ci.mtx.Lock() defer ci.mtx.Unlock() @@ -107,6 +116,7 @@ func (ci *cacheKVStore) Write() { //---------------------------------------- // To cache-wrap this cacheKVStore further. +// Implements CacheWrapper. func (ci *cacheKVStore) CacheWrap() CacheWrap { return NewCacheKVStore(ci) } @@ -114,10 +124,12 @@ func (ci *cacheKVStore) CacheWrap() CacheWrap { //---------------------------------------- // Iteration +// Implements KVStore. func (ci *cacheKVStore) Iterator(start, end []byte) Iterator { return ci.iterator(start, end, true) } +// Implements KVStore. func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator { return ci.iterator(start, end, false) } diff --git a/store/cachekvstore_test.go b/store/cachekvstore_test.go index 2564427dba..e29cd6156a 100644 --- a/store/cachekvstore_test.go +++ b/store/cachekvstore_test.go @@ -10,7 +10,7 @@ import ( ) func newCacheKVStore() CacheKVStore { - mem := dbm.NewMemDB() + mem := dbStoreAdapter{dbm.NewMemDB()} return NewCacheKVStore(mem) } @@ -18,7 +18,7 @@ func keyFmt(i int) []byte { return bz(cmn.Fmt("key%0.8d", i)) } func valFmt(i int) []byte { return bz(cmn.Fmt("value%0.8d", i)) } func TestCacheKVStore(t *testing.T) { - mem := dbm.NewMemDB() + mem := dbStoreAdapter{dbm.NewMemDB()} st := NewCacheKVStore(mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -61,7 +61,7 @@ func TestCacheKVStore(t *testing.T) { } func TestCacheKVStoreNested(t *testing.T) { - mem := dbm.NewMemDB() + mem := dbStoreAdapter{dbm.NewMemDB()} st := NewCacheKVStore(mem) // set. check its there on st and not on mem. diff --git a/store/cachemultistore.go b/store/cachemultistore.go index 3396a68f6e..176f8dbbfe 100644 --- a/store/cachemultistore.go +++ b/store/cachemultistore.go @@ -1,5 +1,9 @@ package store +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + //---------------------------------------- // cacheMultiStore @@ -7,20 +11,18 @@ package store // Implements MultiStore. type cacheMultiStore struct { db CacheKVStore - nextVersion int64 lastCommitID CommitID - substores map[SubstoreKey]CacheWrap + stores map[StoreKey]CacheWrap } func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore { cms := cacheMultiStore{ - db: NewCacheKVStore(rms.db), - nextVersion: rms.nextVersion, + db: NewCacheKVStore(dbStoreAdapter{rms.db}), lastCommitID: rms.lastCommitID, - substores: make(map[SubstoreKey]CacheWrap, len(rms.substores)), + stores: make(map[StoreKey]CacheWrap, len(rms.stores)), } - for key, substore := range rms.substores { - cms.substores[key] = substore.CacheWrap() + for key, store := range rms.stores { + cms.stores[key] = store.CacheWrap() } return cms } @@ -28,50 +30,49 @@ func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore { func newCacheMultiStoreFromCMS(cms cacheMultiStore) cacheMultiStore { cms2 := cacheMultiStore{ db: NewCacheKVStore(cms.db), - nextVersion: cms.nextVersion, lastCommitID: cms.lastCommitID, - substores: make(map[SubstoreKey]CacheWrap, len(cms.substores)), + stores: make(map[StoreKey]CacheWrap, len(cms.stores)), } - for key, substore := range cms.substores { - cms2.substores[key] = substore.CacheWrap() + for key, store := range cms.stores { + cms2.stores[key] = store.CacheWrap() } return cms2 } -// Implements CacheMultiStore +// Implements Store. +func (cms cacheMultiStore) GetStoreType() StoreType { + return sdk.StoreTypeMulti +} + +// Implements MultiStore. func (cms cacheMultiStore) LastCommitID() CommitID { return cms.lastCommitID } -// Implements CacheMultiStore -func (cms cacheMultiStore) NextVersion() int64 { - return cms.nextVersion -} - -// Implements CacheMultiStore +// Implements CacheMultiStore. func (cms cacheMultiStore) Write() { cms.db.Write() - for _, substore := range cms.substores { - substore.Write() + for _, store := range cms.stores { + store.Write() } } -// Implements CacheMultiStore +// Implements CacheWrapper. func (cms cacheMultiStore) CacheWrap() CacheWrap { return cms.CacheMultiStore().(CacheWrap) } -// Implements CacheMultiStore +// Implements MultiStore. func (cms cacheMultiStore) CacheMultiStore() CacheMultiStore { return newCacheMultiStoreFromCMS(cms) } -// Implements CacheMultiStore -func (cms cacheMultiStore) GetStore(key SubstoreKey) interface{} { - return cms.substores[key] +// Implements MultiStore. +func (cms cacheMultiStore) GetStore(key StoreKey) Store { + return cms.stores[key].(Store) } -// Implements CacheMultiStore -func (cms cacheMultiStore) GetKVStore(key SubstoreKey) KVStore { - return cms.substores[key].(KVStore) +// Implements MultiStore. +func (cms cacheMultiStore) GetKVStore(key StoreKey) KVStore { + return cms.stores[key].(KVStore) } diff --git a/store/dbstoreadapter.go b/store/dbstoreadapter.go new file mode 100644 index 0000000000..a1b580fd47 --- /dev/null +++ b/store/dbstoreadapter.go @@ -0,0 +1,23 @@ +package store + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + dbm "github.com/tendermint/tmlibs/db" +) + +type dbStoreAdapter struct { + dbm.DB +} + +// Implements Store. +func (_ dbStoreAdapter) GetStoreType() StoreType { + return sdk.StoreTypeDB +} + +// Implements KVStore. +func (dsa dbStoreAdapter) CacheWrap() CacheWrap { + return NewCacheKVStore(dsa) +} + +// dbm.DB implements KVStore so we can CacheKVStore it. +var _ KVStore = dbStoreAdapter{dbm.DB(nil)} diff --git a/store/iavlstore.go b/store/iavlstore.go index c349358c7b..59b5209548 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -1,38 +1,29 @@ package store import ( + "fmt" "sync" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" + + sdk "github.com/cosmos/cosmos-sdk/types" ) -// iavlStoreLoader contains info on what store we want to load from -type iavlStoreLoader struct { - db dbm.DB - cacheSize int - numHistory int64 -} +const ( + defaultIAVLCacheSize = 10000 + defaultIAVLNumHistory = 1<<53 - 1 // DEPRECATED +) -// NewIAVLStoreLoader returns a CommitStoreLoader that returns an iavlStore -func NewIAVLStoreLoader(db dbm.DB, cacheSize int, numHistory int64) CommitStoreLoader { - l := iavlStoreLoader{ - db: db, - cacheSize: cacheSize, - numHistory: numHistory, - } - return l.Load -} - -// Load implements CommitLoader. -func (isl iavlStoreLoader) Load(id CommitID) (CommitStore, error) { - tree := iavl.NewVersionedTree(isl.db, isl.cacheSize) - err := tree.Load() +func LoadIAVLStore(db dbm.DB, id CommitID) (CommitStore, error) { + tree := iavl.NewVersionedTree(db, defaultIAVLCacheSize) + fmt.Println("LoadIAVLStore Version ", id.Version) + err := tree.LoadVersion(id.Version) if err != nil { return nil, err } - store := newIAVLStore(tree, isl.numHistory) + store := newIAVLStore(tree, defaultIAVLNumHistory) return store, nil } @@ -61,7 +52,7 @@ func newIAVLStore(tree *iavl.VersionedTree, numHistory int64) *iavlStore { return st } -// Commit persists the store. +// Implements Committer. func (st *iavlStore) Commit() CommitID { // Save a new version. @@ -83,45 +74,58 @@ func (st *iavlStore) Commit() CommitID { } } -// CacheWrap implements KVStore. +// Implements Committer. +func (st *iavlStore) LastCommitID() CommitID { + return CommitID{ + Version: st.tree.Version64(), + Hash: st.tree.Hash(), + } +} + +// Implements Store. +func (st *iavlStore) GetStoreType() StoreType { + return sdk.StoreTypeIAVL +} + +// Implements Store. func (st *iavlStore) CacheWrap() CacheWrap { return NewCacheKVStore(st) } -// Set implements KVStore. +// Implements KVStore. func (st *iavlStore) Set(key, value []byte) { st.tree.Set(key, value) } -// Get implements KVStore. +// Implements KVStore. func (st *iavlStore) Get(key []byte) (value []byte) { _, v := st.tree.Get(key) return v } -// Has implements KVStore. +// Implements KVStore. func (st *iavlStore) Has(key []byte) (exists bool) { return st.tree.Has(key) } -// Delete implements KVStore. +// Implements KVStore. func (st *iavlStore) Delete(key []byte) { st.tree.Remove(key) } -// Iterator implements KVStore. +// Implements KVStore. func (st *iavlStore) Iterator(start, end []byte) Iterator { return newIAVLIterator(st.tree.Tree(), start, end, true) } -// ReverseIterator implements IterKVStore. +// Implements IterKVStore. func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { return newIAVLIterator(st.tree.Tree(), start, end, false) } //---------------------------------------- -// Implements Iterator +// Implements Iterator. type iavlIterator struct { // Underlying store tree *iavl.Tree @@ -192,12 +196,12 @@ func (iter *iavlIterator) initRoutine() { close(iter.initCh) } -// Domain implements Iterator +// Implements Iterator. func (iter *iavlIterator) Domain() (start, end []byte) { return iter.start, iter.end } -// Valid implements Iterator +// Implements Iterator. func (iter *iavlIterator) Valid() bool { iter.waitInit() iter.mtx.Lock() @@ -206,7 +210,7 @@ func (iter *iavlIterator) Valid() bool { return !iter.invalid } -// Next implements Iterator +// Implements Iterator. func (iter *iavlIterator) Next() { iter.waitInit() iter.mtx.Lock() @@ -216,7 +220,7 @@ func (iter *iavlIterator) Next() { iter.receiveNext() } -// Key implements Iterator +// Implements Iterator. func (iter *iavlIterator) Key() []byte { iter.waitInit() iter.mtx.Lock() @@ -226,7 +230,7 @@ func (iter *iavlIterator) Key() []byte { return iter.key } -// Value implements Iterator +// Implements Iterator. func (iter *iavlIterator) Value() []byte { iter.waitInit() iter.mtx.Lock() @@ -236,7 +240,7 @@ func (iter *iavlIterator) Value() []byte { return iter.value } -// Close implements Iterator +// Implements Iterator. func (iter *iavlIterator) Close() { close(iter.quitCh) } diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index ccac1145e2..80731c24ee 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -40,20 +40,6 @@ func newTree(t *testing.T, db dbm.DB) (*iavl.VersionedTree, CommitID) { return tree, CommitID{ver, hash} } -func TestIAVLStoreLoader(t *testing.T) { - db := dbm.NewMemDB() - _, id := newTree(t, db) - - iavlLoader := NewIAVLStoreLoader(db, cacheSize, numHistory) - commitStore, err := iavlLoader(id) - assert.Nil(t, err) - - id2 := commitStore.Commit() - - assert.Equal(t, id.Hash, id2.Hash) - assert.Equal(t, id.Version+1, id2.Version) -} - func TestIAVLStoreGetSetHasDelete(t *testing.T) { db := dbm.NewMemDB() tree, _ := newTree(t, db) diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 1acd0da1a4..67582d331c 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -6,11 +6,13 @@ import ( dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/merkle" "golang.org/x/crypto/ripemd160" + + sdk "github.com/cosmos/cosmos-sdk/types" ) const ( - latestVersionKey = "s/latest" - commitStateKeyFmt = "s/%d" // s/ + latestVersionKey = "s/latest" + commitInfoKeyFmt = "s/%d" // s/ ) // rootMultiStore is composed of many CommitStores. @@ -19,10 +21,9 @@ const ( // Implements MultiStore. type rootMultiStore struct { db dbm.DB - nextVersion int64 lastCommitID CommitID - storeLoaders map[SubstoreKey]CommitStoreLoader - substores map[SubstoreKey]CommitStore + storesParams map[StoreKey]storeParams + stores map[StoreKey]CommitStore } var _ CommitMultiStore = (*rootMultiStore)(nil) @@ -30,26 +31,33 @@ var _ CommitMultiStore = (*rootMultiStore)(nil) func NewCommitMultiStore(db dbm.DB) *rootMultiStore { return &rootMultiStore{ db: db, - nextVersion: 0, - storeLoaders: make(map[SubstoreKey]CommitStoreLoader), - substores: make(map[SubstoreKey]CommitStore), + storesParams: make(map[StoreKey]storeParams), + stores: make(map[StoreKey]CommitStore), } } +// Implements Store. +func (rs *rootMultiStore) GetStoreType() StoreType { + return sdk.StoreTypeMulti +} + // Implements CommitMultiStore. -func (rs *rootMultiStore) SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) { +func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) { if key == nil { - panic("SetSubstoreLoader() key cannot be nil") + panic("MountIAVLStore() key cannot be nil") } - if _, ok := rs.storeLoaders[key]; ok { - panic(fmt.Sprintf("rootMultiStore duplicate substore key", key)) + if _, ok := rs.storesParams[key]; ok { + panic(fmt.Sprintf("rootMultiStore duplicate store key", key)) + } + rs.storesParams[key] = storeParams{ + db: db, + typ: typ, } - rs.storeLoaders[key] = loader } // Implements CommitMultiStore. -func (rs *rootMultiStore) GetSubstore(key SubstoreKey) CommitStore { - return rs.substores[key] +func (rs *rootMultiStore) GetCommitStore(key StoreKey) CommitStore { + return rs.stores[key] } // Implements CommitMultiStore. @@ -63,85 +71,71 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { // Special logic for version 0 if ver == 0 { - for key, storeLoader := range rs.storeLoaders { - store, err := storeLoader(CommitID{}) + for key, storeParams := range rs.storesParams { + id := CommitID{} + store, err := rs.loadCommitStoreFromParams(id, storeParams) if err != nil { return fmt.Errorf("Failed to load rootMultiStore: %v", err) } - rs.substores[key] = store + rs.stores[key] = store } - rs.nextVersion = 1 rs.lastCommitID = CommitID{} return nil } // Otherwise, version is 1 or greater - // Get commitState - state, err := getCommitState(rs.db, ver) + // Get commitInfo + cInfo, err := getCommitInfo(rs.db, ver) if err != nil { return err } - // Load each Substore - var newSubstores = make(map[SubstoreKey]CommitStore) - for _, store := range state.Substores { - key, commitID := rs.nameToKey(store.Name), store.CommitID - storeLoader := rs.storeLoaders[key] - if storeLoader == nil { - return fmt.Errorf("Failed to load rootMultiStore substore %v for commitID %v: %v", key, commitID, err) - } - store, err := storeLoader(commitID) + // Load each Store + var newStores = make(map[StoreKey]CommitStore) + for _, storeInfo := range cInfo.StoreInfos { + key, commitID := rs.nameToKey(storeInfo.Name), storeInfo.Core.CommitID + storeParams := rs.storesParams[key] + store, err := rs.loadCommitStoreFromParams(commitID, storeParams) if err != nil { return fmt.Errorf("Failed to load rootMultiStore: %v", err) } - newSubstores[key] = store + newStores[key] = store } // If any CommitStoreLoaders were not used, return error. - for key := range rs.storeLoaders { - if _, ok := newSubstores[key]; !ok { + for key := range rs.storesParams { + if _, ok := newStores[key]; !ok { return fmt.Errorf("Unused CommitStoreLoader: %v", key) } } // Success. - rs.nextVersion = ver + 1 - rs.lastCommitID = state.CommitID() - rs.substores = newSubstores + rs.lastCommitID = cInfo.CommitID() + rs.stores = newStores return nil } -func (rs *rootMultiStore) nameToKey(name string) SubstoreKey { - for key, _ := range rs.storeLoaders { - if key.Name() == name { - return key - } - } - panic("Unknown name " + name) -} - //---------------------------------------- // +CommitStore // Implements CommitStore. func (rs *rootMultiStore) Commit() CommitID { - // Commit substores. - version := rs.nextVersion - state := commitSubstores(version, rs.substores) + // Commit stores. + version := rs.lastCommitID.Version + 1 + commitInfo := commitStores(version, rs.stores) - // Need to update self state atomically. + // Need to update atomically. batch := rs.db.NewBatch() - setCommitState(batch, version, state) + setCommitInfo(batch, version, commitInfo) setLatestVersion(batch, version) batch.Write() // Prepare for next version. - rs.nextVersion = version + 1 commitID := CommitID{ Version: version, - Hash: state.Hash(), + Hash: commitInfo.Hash(), } rs.lastCommitID = commitID return commitID @@ -160,77 +154,112 @@ func (rs *rootMultiStore) LastCommitID() CommitID { return rs.lastCommitID } -// Implements MultiStore. -// NOTE: Returns 0 unless LoadVersion() or LoadLatestVersion() is called. -func (rs *rootMultiStore) NextVersion() int64 { - return rs.nextVersion -} - // Implements MultiStore. func (rs *rootMultiStore) CacheMultiStore() CacheMultiStore { return newCacheMultiStoreFromRMS(rs) } // Implements MultiStore. -func (rs *rootMultiStore) GetStore(key SubstoreKey) interface{} { - return rs.substores[key] +func (rs *rootMultiStore) GetStore(key StoreKey) Store { + return rs.stores[key] } // Implements MultiStore. -func (rs *rootMultiStore) GetKVStore(key SubstoreKey) KVStore { - return rs.substores[key].(KVStore) +func (rs *rootMultiStore) GetKVStore(key StoreKey) KVStore { + return rs.stores[key].(KVStore) } //---------------------------------------- -// commitState -// NOTE: Keep commitState a simple immutable struct. -type commitState struct { +func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) { + db := rs.db + if params.db != nil { + db = params.db + } + switch params.typ { + case sdk.StoreTypeMulti: + panic("recursive MultiStores not yet supported") + // TODO: id? + // return NewCommitMultiStore(db, id) + case sdk.StoreTypeIAVL: + store, err = LoadIAVLStore(db, id) + return + case sdk.StoreTypeDB: + panic("dbm.DB is not a CommitStore") + default: + panic(fmt.Sprintf("unrecognized store type %v", params.typ)) + } +} + +func (rs *rootMultiStore) nameToKey(name string) StoreKey { + for key, _ := range rs.storesParams { + if key.Name() == name { + return key + } + } + panic("Unknown name " + name) +} + +//---------------------------------------- +// storeParams + +type storeParams struct { + db dbm.DB + typ StoreType +} + +//---------------------------------------- +// commitInfo + +// NOTE: Keep commitInfo a simple immutable struct. +type commitInfo struct { // Version Version int64 - // Substore info for - Substores []substore + // Store info for + StoreInfos []storeInfo } -// Hash returns the simple merkle root hash of the substores sorted by name. -func (cs commitState) Hash() []byte { - // TODO cache to cs.hash []byte - m := make(map[string]merkle.Hasher, len(cs.Substores)) - for _, substore := range cs.Substores { - m[substore.Name] = substore +// Hash returns the simple merkle root hash of the stores sorted by name. +func (ci commitInfo) Hash() []byte { + // TODO cache to ci.hash []byte + m := make(map[string]merkle.Hasher, len(ci.StoreInfos)) + for _, storeInfo := range ci.StoreInfos { + m[storeInfo.Name] = storeInfo } return merkle.SimpleHashFromMap(m) } -func (cs commitState) CommitID() CommitID { +func (ci commitInfo) CommitID() CommitID { return CommitID{ - Version: cs.Version, - Hash: cs.Hash(), + Version: ci.Version, + Hash: ci.Hash(), } } //---------------------------------------- -// substore state +// storeInfo -// substore contains the name and core reference for an underlying store. -// It is the leaf of the rootMultiStores top level simple merkle tree. -type substore struct { +// storeInfo contains the name and core reference for an +// underlying store. It is the leaf of the rootMultiStores top +// level simple merkle tree. +type storeInfo struct { Name string - substoreCore + Core storeCore } -type substoreCore struct { +type storeCore struct { + // StoreType StoreType CommitID CommitID // ... maybe add more state } // Implements merkle.Hasher. -func (sw substore) Hash() []byte { +func (si storeInfo) Hash() []byte { // Doesn't write Name, since merkle.SimpleHashFromMap() will // include them via the keys. - bz, _ := cdc.MarshalBinary(sw.substoreCore) // Does not error + bz, _ := cdc.MarshalBinary(si.Core) // Does not error hasher := ripemd160.New() hasher.Write(bz) return hasher.Sum(nil) @@ -258,52 +287,53 @@ func setLatestVersion(batch dbm.Batch, version int64) { batch.Set([]byte(latestVersionKey), latestBytes) } -// Commits each substore and returns a new commitState. -func commitSubstores(version int64, substoresMap map[SubstoreKey]CommitStore) commitState { - substores := make([]substore, 0, len(substoresMap)) +// Commits each store and returns a new commitInfo. +func commitStores(version int64, storeMap map[StoreKey]CommitStore) commitInfo { + storeInfos := make([]storeInfo, 0, len(storeMap)) - for key, store := range substoresMap { + for key, store := range storeMap { // Commit commitID := store.Commit() // Record CommitID - substore := substore{} - substore.Name = key.Name() - substore.CommitID = commitID - substores = append(substores, substore) + si := storeInfo{} + si.Name = key.Name() + si.Core.CommitID = commitID + // si.Core.StoreType = store.GetStoreType() + storeInfos = append(storeInfos, si) } - return commitState{ - Version: version, - Substores: substores, + return commitInfo{ + Version: version, + StoreInfos: storeInfos, } } -// Gets commitState from disk. -func getCommitState(db dbm.DB, ver int64) (commitState, error) { +// Gets commitInfo from disk. +func getCommitInfo(db dbm.DB, ver int64) (commitInfo, error) { // Get from DB. - commitStateKey := fmt.Sprintf(commitStateKeyFmt, ver) - stateBytes := db.Get([]byte(commitStateKey)) - if stateBytes == nil { - return commitState{}, fmt.Errorf("Failed to get rootMultiStore: no data") + cInfoKey := fmt.Sprintf(commitInfoKeyFmt, ver) + cInfoBytes := db.Get([]byte(cInfoKey)) + if cInfoBytes == nil { + return commitInfo{}, fmt.Errorf("Failed to get rootMultiStore: no data") } // Parse bytes. - var state commitState - err := cdc.UnmarshalBinary(stateBytes, &state) + var cInfo commitInfo + err := cdc.UnmarshalBinary(cInfoBytes, &cInfo) if err != nil { - return commitState{}, fmt.Errorf("Failed to get rootMultiStore: %v", err) + return commitInfo{}, fmt.Errorf("Failed to get rootMultiStore: %v", err) } - return state, nil + return cInfo, nil } -// Set a commit state for given version. -func setCommitState(batch dbm.Batch, version int64, state commitState) { - stateBytes, err := cdc.MarshalBinary(state) +// Set a commitInfo for given version. +func setCommitInfo(batch dbm.Batch, version int64, cInfo commitInfo) { + cInfoBytes, err := cdc.MarshalBinary(cInfo) if err != nil { panic(err) } - commitStateKey := fmt.Sprintf(commitStateKeyFmt, version) - batch.Set([]byte(commitStateKey), stateBytes) + cInfoKey := fmt.Sprintf(commitInfoKeyFmt, version) + batch.Set([]byte(cInfoKey), cInfoBytes) } diff --git a/store/rootmultistore_test.go b/store/rootmultistore_test.go index 632ea66cfa..99e9050628 100644 --- a/store/rootmultistore_test.go +++ b/store/rootmultistore_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/merkle" @@ -13,7 +12,7 @@ import ( func TestMultistoreCommitLoad(t *testing.T) { db := dbm.NewMemDB() - store := newMultiStoreWithLoaders(db) + store := newMultiStoreWithMounts(db) err := store.LoadLatestVersion() assert.Nil(t, err) @@ -30,7 +29,7 @@ func TestMultistoreCommitLoad(t *testing.T) { } // Load the latest multistore again and check version - store = newMultiStoreWithLoaders(db) + store = newMultiStoreWithMounts(db) err = store.LoadLatestVersion() assert.Nil(t, err) commitID = getExpectedCommitID(store, nCommits) @@ -43,7 +42,7 @@ func TestMultistoreCommitLoad(t *testing.T) { // Load an older multistore and check version ver := nCommits - 1 - store = newMultiStoreWithLoaders(db) + store = newMultiStoreWithMounts(db) err = store.LoadVersion(ver) assert.Nil(t, err) commitID = getExpectedCommitID(store, ver) @@ -56,7 +55,7 @@ func TestMultistoreCommitLoad(t *testing.T) { // XXX: confirm old commit is overwritten and // we have rolled back LatestVersion - store = newMultiStoreWithLoaders(db) + store = newMultiStoreWithMounts(db) err = store.LoadLatestVersion() assert.Nil(t, err) commitID = getExpectedCommitID(store, ver+1) @@ -66,21 +65,18 @@ func TestMultistoreCommitLoad(t *testing.T) { //----------------------------------------------------------------------- // utils -func newMultiStoreWithLoaders(db dbm.DB) *rootMultiStore { +func newMultiStoreWithMounts(db dbm.DB) *rootMultiStore { store := NewCommitMultiStore(db) - storeLoaders := map[SubstoreKey]CommitStoreLoader{ - sdk.NewKVStoreKey("store1"): newMockCommitStore, - sdk.NewKVStoreKey("store2"): newMockCommitStore, - sdk.NewKVStoreKey("store3"): newMockCommitStore, - } - for key, loader := range storeLoaders { - store.SetSubstoreLoader(key, loader) - } + store.MountStoreWithDB( + sdk.NewKVStoreKey("store1"), sdk.StoreTypeIAVL, db) + store.MountStoreWithDB( + sdk.NewKVStoreKey("store2"), sdk.StoreTypeIAVL, db) + store.MountStoreWithDB( + sdk.NewKVStoreKey("store3"), sdk.StoreTypeIAVL, db) return store } func checkStore(t *testing.T, store *rootMultiStore, expect, got CommitID) { - assert.EqualValues(t, expect.Version+1, store.NextVersion()) assert.Equal(t, expect, got) assert.Equal(t, expect, store.LastCommitID()) @@ -89,42 +85,21 @@ func checkStore(t *testing.T, store *rootMultiStore, expect, got CommitID) { func getExpectedCommitID(store *rootMultiStore, ver int64) CommitID { return CommitID{ Version: ver, - Hash: hashStores(store.substores), + Hash: hashStores(store.stores), } } -func hashStores(stores map[SubstoreKey]CommitStore) []byte { +func hashStores(stores map[StoreKey]CommitStore) []byte { m := make(map[string]merkle.Hasher, len(stores)) for key, store := range stores { name := key.Name() - m[name] = substore{ + m[name] = storeInfo{ Name: name, - substoreCore: substoreCore{ - CommitID: store.Commit(), + Core: storeCore{ + CommitID: store.LastCommitID(), + // StoreType: store.GetStoreType(), }, } } return merkle.SimpleHashFromMap(m) } - -//----------------------------------------------------------------------- -// mockCommitStore - -var _ CommitStore = (*mockCommitStore)(nil) - -type mockCommitStore struct { - id CommitID -} - -func newMockCommitStore(id CommitID) (CommitStore, error) { - return &mockCommitStore{id}, nil -} - -func (cs *mockCommitStore) Commit() CommitID { - return cs.id -} -func (cs *mockCommitStore) CacheWrap() CacheWrap { - cs2 := *cs - return &cs2 -} -func (cs *mockCommitStore) Write() {} diff --git a/store/types.go b/store/types.go index db946f2e2b..e6946fb4d5 100644 --- a/store/types.go +++ b/store/types.go @@ -5,16 +5,17 @@ import ( ) // Import cosmos-sdk/types/store.go for convenience. +type Store = types.Store type MultiStore = types.MultiStore type CacheMultiStore = types.CacheMultiStore type CommitStore = types.CommitStore type Committer = types.Committer type CommitMultiStore = types.CommitMultiStore -type CommitStoreLoader = types.CommitStoreLoader type KVStore = types.KVStore type Iterator = types.Iterator type CacheKVStore = types.CacheKVStore type CacheWrapper = types.CacheWrapper type CacheWrap = types.CacheWrap type CommitID = types.CommitID -type SubstoreKey = types.SubstoreKey +type StoreKey = types.StoreKey +type StoreType = types.StoreType diff --git a/types/account.go b/types/account.go index c79454924c..d2dd9df6cf 100644 --- a/types/account.go +++ b/types/account.go @@ -23,12 +23,10 @@ type Account interface { Set(key interface{}, value interface{}) error } -// AccountStore indexes accounts by address. -type AccountStore interface { +// AccountMapper stores and retrieves accounts from stores +// retrieved from the context. +type AccountMapper interface { NewAccountWithAddress(ctx Context, addr crypto.Address) Account GetAccount(ctx Context, addr crypto.Address) Account SetAccount(ctx Context, acc Account) } - -// new(AccountStoreKey) is a capabilities key. -type AccountStoreKey struct{} diff --git a/types/context.go b/types/context.go index eaef3f76c8..9a5122c132 100644 --- a/types/context.go +++ b/types/context.go @@ -60,7 +60,7 @@ func (c Context) Value(key interface{}) interface{} { } // KVStore fetches a KVStore from the MultiStore. -func (c Context) KVStore(key SubstoreKey) KVStore { +func (c Context) KVStore(key StoreKey) KVStore { return c.multiStore().GetKVStore(key) } @@ -83,7 +83,7 @@ func (c Context) WithProtoMsg(key interface{}, value proto.Message) Context { return c.withValue(key, value) } -func (c Context) WithMultiStore(key SubstoreKey, ms MultiStore) Context { +func (c Context) WithMultiStore(key StoreKey, ms MultiStore) Context { return c.withValue(key, ms) } diff --git a/types/store.go b/types/store.go index a17f703b6c..f9e8c912a3 100644 --- a/types/store.go +++ b/types/store.go @@ -8,18 +8,28 @@ import ( // NOTE: These are implemented in cosmos-sdk/store. +type Store interface { + GetStoreType() StoreType + CacheWrapper +} + +// Something that can persist to disk. +type Committer interface { + Commit() CommitID + LastCommitID() CommitID +} + +// Stores of MultiStore must implement CommitStore. +type CommitStore interface { + Committer + Store +} + //---------------------------------------- // MultiStore type MultiStore interface { - - // Last commit, or the zero CommitID. - // If not zero, CommitID.Version is NextVersion()-1. - LastCommitID() CommitID - - // Current version being worked on now, not yet committed. - // Should be greater than 0. - NextVersion() int64 + Store // Cache wrap MultiStore. // NOTE: Caller should probably not call .Write() on each, but @@ -27,8 +37,8 @@ type MultiStore interface { CacheMultiStore() CacheMultiStore // Convenience for fetching substores. - GetStore(SubstoreKey) interface{} - GetKVStore(SubstoreKey) KVStore + GetStore(StoreKey) Store + GetKVStore(StoreKey) KVStore } // From MultiStore.CacheMultiStore().... @@ -37,50 +47,34 @@ type CacheMultiStore interface { Write() // Writes operations to underlying KVStore } -// Substores of MultiStore must implement CommitStore. -type CommitStore interface { - Committer - CacheWrapper -} - -// A non-cache store that can commit (persist) and get a Merkle root. -type Committer interface { - Commit() CommitID -} - // A non-cache MultiStore. type CommitMultiStore interface { - CommitStore + Committer MultiStore - // Add a substore loader. - // Panics on a nil key. - SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) + // Mount a store of type. + MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB) - // Gets the substore, which is a CommitSubstore. // Panics on a nil key. - GetSubstore(key SubstoreKey) CommitStore + GetCommitStore(key StoreKey) CommitStore - // Load the latest persisted version. - // Called once after all calls to SetSubstoreLoader are complete. + // Load the latest persisted version. Called once after all + // calls to Mount*Store() are complete. LoadLatestVersion() error - // Load a specific persisted version. When you load an old version, or - // when the last commit attempt didn't complete, the next commit after - // loading must be idempotent (return the same commit id). Otherwise the - // behavior is undefined. + // Load a specific persisted version. When you load an old + // version, or when the last commit attempt didn't complete, + // the next commit after loading must be idempotent (return the + // same commit id). Otherwise the behavior is undefined. LoadVersion(ver int64) error } -// These must be added to the MultiStore before calling LoadVersion() or -// LoadLatest(). -type CommitStoreLoader func(id CommitID) (CommitStore, error) - //---------------------------------------- // KVStore // KVStore is a simple interface to get/set data type KVStore interface { + Store // Get returns nil iff key doesn't exist. Panics on nil key. Get(key []byte) []byte @@ -112,17 +106,17 @@ type KVStore interface { } -// dbm.DB implements KVStore so we can CacheKVStore it. -var _ KVStore = dbm.DB(nil) - // Alias iterator to db's Iterator for convenience. type Iterator = dbm.Iterator -// CacheKVStore cache-wraps a KVStore. After calling .Write() on the -// CacheKVStore, all previously created CacheKVStores on the object expire. +// CacheKVStore cache-wraps a KVStore. After calling .Write() on +// the CacheKVStore, all previously created CacheKVStores on the +// object expire. type CacheKVStore interface { KVStore - Write() // Writes operations to underlying KVStore + + // Writes operations to underlying KVStore + Write() } //---------------------------------------- @@ -166,13 +160,23 @@ func (cid CommitID) String() string { return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version) } +//---------------------------------------- +// Store types + +type StoreType int + +const ( + StoreTypeMulti StoreType = iota + StoreTypeDB + StoreTypeIAVL +) + //---------------------------------------- // Keys for accessing substores -// SubstoreKey is a key used to index substores. -type SubstoreKey interface { +// StoreKey is a key used to index stores in a MultiStore. +type StoreKey interface { Name() string - String() string } diff --git a/x/auth/ante.go b/x/auth/ante.go index 312f204708..c84394138e 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -4,7 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func NewAnteHandler(store sdk.AccountStore) sdk.AnteHandler { +func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { return func( ctx sdk.Context, tx sdk.Tx, ) (newCtx sdk.Context, res sdk.Result, abort bool) { @@ -13,7 +13,7 @@ func NewAnteHandler(store sdk.AccountStore) sdk.AnteHandler { // This is done first because it only // requires fetching 1 account. payerAddr := tx.GetFeePayer() - payerAcc := store.GetAccount(ctx, payerAddr) + payerAcc := accountMapper.GetAccount(ctx, payerAddr) if payerAcc == nil { return ctx, sdk.Result{ Code: 1, // TODO @@ -42,7 +42,7 @@ func NewAnteHandler(store sdk.AccountStore) sdk.AnteHandler { // Check each nonce and sig. for i, sig := range signatures { - var signerAcc = store.GetAccount(ctx, signerAddrs[i]) + var signerAcc = accountMapper.GetAccount(ctx, signerAddrs[i]) signerAccs[i] = signerAcc // If no pubkey, set pubkey. @@ -72,7 +72,7 @@ func NewAnteHandler(store sdk.AccountStore) sdk.AnteHandler { } // Save the account. - store.SetAccount(ctx, signerAcc) + accountMapper.SetAccount(ctx, signerAcc) } ctx = WithSigners(ctx, signerAccs) diff --git a/x/auth/context.go b/x/auth/context.go index ea96443fc9..90de99f783 100644 --- a/x/auth/context.go +++ b/x/auth/context.go @@ -8,13 +8,13 @@ import ( Usage: -var accountStore types.AccountStore +var accounts types.AccountMapper // Fetch all signer accounts. addrs := tx.GetSigners() signers := make([]types.Account, len(addrs)) for i, addr := range addrs { - acc := accountStore.GetAccount(ctx) + acc := accounts.GetAccount(ctx) signers[i] = acc } ctx = auth.SetSigners(ctx, signers) diff --git a/x/auth/mapper.go b/x/auth/mapper.go new file mode 100644 index 0000000000..dd2b0ffc12 --- /dev/null +++ b/x/auth/mapper.go @@ -0,0 +1,154 @@ +package auth + +import ( + "fmt" + "reflect" + + crypto "github.com/tendermint/go-crypto" + wire "github.com/tendermint/go-wire" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Implements sdk.AccountMapper. +// This AccountMapper encodes/decodes accounts using the +// go-wire (binary) encoding/decoding library. +type accountMapper struct { + + // The (unexposed) key used to access the store from the Context. + key sdk.StoreKey + + // The prototypical sdk.Account concrete type. + proto sdk.Account + + // The wire codec for binary encoding/decoding of accounts. + cdc *wire.Codec +} + +// NewAccountMapper returns a new sdk.AccountMapper that +// uses go-wire to (binary) encode and decode concrete sdk.Accounts. +func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper { + cdc := wire.NewCodec() + return accountMapper{ + key: key, + proto: proto, + cdc: cdc, + } +} + +// Returns the go-wire codec. You may need to register interfaces +// and concrete types here, if your app's sdk.Account +// implementation includes interface fields. +// NOTE: It is not secure to expose the codec, so check out +// .Seal(). +func (am accountMapper) WireCodec() *wire.Codec { + return am.cdc +} + +// Returns a "sealed" accountMapper. +// The codec is not accessible from a sealedAccountMapper. +func (am accountMapper) Seal() sealedAccountMapper { + return sealedAccountMapper{am} +} + +// Implements sdk.AccountMapper. +func (am accountMapper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) sdk.Account { + acc := am.clonePrototype() + acc.SetAddress(addr) + return acc +} + +// Implements sdk.AccountMapper. +func (am accountMapper) GetAccount(ctx sdk.Context, addr crypto.Address) sdk.Account { + store := ctx.KVStore(am.key) + bz := store.Get(addr) + if bz == nil { + return nil + } + acc := am.decodeAccount(bz) + return acc +} + +// Implements sdk.AccountMapper. +func (am accountMapper) SetAccount(ctx sdk.Context, acc sdk.Account) { + addr := acc.GetAddress() + store := ctx.KVStore(am.key) + bz := am.encodeAccount(acc) + store.Set(addr, bz) +} + +//---------------------------------------- +// misc. + +func (am accountMapper) clonePrototypePtr() interface{} { + protoRt := reflect.TypeOf(am.proto) + if protoRt.Kind() == reflect.Ptr { + protoErt := protoRt.Elem() + if protoErt.Kind() != reflect.Struct { + panic("accountMapper requires a struct proto sdk.Account, or a pointer to one") + } + protoRv := reflect.New(protoErt) + return protoRv.Interface() + } else { + protoRv := reflect.New(protoRt) + return protoRv.Interface() + } +} + +// Creates a new struct (or pointer to struct) from am.proto. +func (am accountMapper) clonePrototype() sdk.Account { + protoRt := reflect.TypeOf(am.proto) + if protoRt.Kind() == reflect.Ptr { + protoCrt := protoRt.Elem() + if protoCrt.Kind() != reflect.Struct { + panic("accountMapper requires a struct proto sdk.Account, or a pointer to one") + } + protoRv := reflect.New(protoCrt) + clone, ok := protoRv.Interface().(sdk.Account) + if !ok { + panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) + } + return clone + } else { + protoRv := reflect.New(protoRt).Elem() + clone, ok := protoRv.Interface().(sdk.Account) + if !ok { + panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) + } + return clone + } +} + +func (am accountMapper) encodeAccount(acc sdk.Account) []byte { + bz, err := am.cdc.MarshalBinary(acc) + if err != nil { + panic(err) + } + return bz +} + +func (am accountMapper) decodeAccount(bz []byte) sdk.Account { + accPtr := am.clonePrototypePtr() + err := am.cdc.UnmarshalBinary(bz, accPtr) + if err != nil { + panic(err) + } + if reflect.ValueOf(am.proto).Kind() == reflect.Ptr { + return reflect.ValueOf(accPtr).Interface().(sdk.Account) + } else { + return reflect.ValueOf(accPtr).Elem().Interface().(sdk.Account) + } +} + +//---------------------------------------- +// sealedAccountMapper + +type sealedAccountMapper struct { + accountMapper +} + +// There's no way for external modules to mutate the +// sam.accountMapper.ctx from here, even with reflection. +func (sam sealedAccountMapper) WireCodec() *wire.Codec { + panic("accountMapper is sealed") +} diff --git a/x/auth/store.go b/x/auth/store.go deleted file mode 100644 index 2487ac1582..0000000000 --- a/x/auth/store.go +++ /dev/null @@ -1,154 +0,0 @@ -package auth - -import ( - "fmt" - "reflect" - - crypto "github.com/tendermint/go-crypto" - wire "github.com/tendermint/go-wire" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// Implements sdk.AccountStore. -// This AccountStore encodes/decodes accounts using the -// go-wire (binary) encoding/decoding library. -type accountStore struct { - - // The (unexposed) key used to access the store from the Context. - key sdk.SubstoreKey - - // The prototypical sdk.Account concrete type. - proto sdk.Account - - // The wire codec for binary encoding/decoding of accounts. - cdc *wire.Codec -} - -// NewAccountStore returns a new sdk.AccountStore that -// uses go-wire to (binary) encode and decode concrete sdk.Accounts. -func NewAccountStore(key sdk.SubstoreKey, proto sdk.Account) accountStore { - cdc := wire.NewCodec() - return accountStore{ - key: key, - proto: proto, - cdc: cdc, - } -} - -// Returns the go-wire codec. You may need to register interfaces -// and concrete types here, if your app's sdk.Account -// implementation includes interface fields. -// NOTE: It is not secure to expose the codec, so check out -// .Seal(). -func (as accountStore) WireCodec() *wire.Codec { - return as.cdc -} - -// Returns a "sealed" accountStore. -// The codec is not accessible from a sealedAccountStore -func (as accountStore) Seal() sealedAccountStore { - return sealedAccountStore{as} -} - -// Implements sdk.AccountStore. -func (as accountStore) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) sdk.Account { - acc := as.clonePrototype() - acc.SetAddress(addr) - return acc -} - -// Implements sdk.AccountStore. -func (as accountStore) GetAccount(ctx sdk.Context, addr crypto.Address) sdk.Account { - store := ctx.KVStore(as.key) - bz := store.Get(addr) - if bz == nil { - return nil - } - acc := as.decodeAccount(bz) - return acc -} - -// Implements sdk.AccountStore. -func (as accountStore) SetAccount(ctx sdk.Context, acc sdk.Account) { - addr := acc.GetAddress() - store := ctx.KVStore(as.key) - bz := as.encodeAccount(acc) - store.Set(addr, bz) -} - -//---------------------------------------- -// misc. - -func (as accountStore) clonePrototypePtr() interface{} { - protoRt := reflect.TypeOf(as.proto) - if protoRt.Kind() == reflect.Ptr { - protoErt := protoRt.Elem() - if protoErt.Kind() != reflect.Struct { - panic("AccountStore requires a struct proto sdk.Account, or a pointer to one") - } - protoRv := reflect.New(protoErt) - return protoRv.Interface() - } else { - protoRv := reflect.New(protoRt) - return protoRv.Interface() - } -} - -// Creates a new struct (or pointer to struct) from as.proto. -func (as accountStore) clonePrototype() sdk.Account { - protoRt := reflect.TypeOf(as.proto) - if protoRt.Kind() == reflect.Ptr { - protoCrt := protoRt.Elem() - if protoCrt.Kind() != reflect.Struct { - panic("AccountStore requires a struct proto sdk.Account, or a pointer to one") - } - protoRv := reflect.New(protoCrt) - clone, ok := protoRv.Interface().(sdk.Account) - if !ok { - panic(fmt.Sprintf("AccountStore requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) - } - return clone - } else { - protoRv := reflect.New(protoRt).Elem() - clone, ok := protoRv.Interface().(sdk.Account) - if !ok { - panic(fmt.Sprintf("AccountStore requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt)) - } - return clone - } -} - -func (as accountStore) encodeAccount(acc sdk.Account) []byte { - bz, err := as.cdc.MarshalBinary(acc) - if err != nil { - panic(err) - } - return bz -} - -func (as accountStore) decodeAccount(bz []byte) sdk.Account { - accPtr := as.clonePrototypePtr() - err := as.cdc.UnmarshalBinary(bz, accPtr) - if err != nil { - panic(err) - } - if reflect.ValueOf(as.proto).Kind() == reflect.Ptr { - return reflect.ValueOf(accPtr).Interface().(sdk.Account) - } else { - return reflect.ValueOf(accPtr).Elem().Interface().(sdk.Account) - } -} - -//---------------------------------------- -// sealedAccountStore - -type sealedAccountStore struct { - accountStore -} - -// There's no way for external modules to mutate the -// sas.accountStore.ctx from here, even with reflection. -func (sas sealedAccountStore) WireCodec() *wire.Codec { - panic("accountStore is sealed") -} diff --git a/x/bank/handler.go b/x/bank/handler.go index 63198cb6e1..10c4520dea 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -6,16 +6,16 @@ import ( ) // Handle all "bank" type messages. -func NewHandler(accStore sdk.AccountStore) sdk.Handler { +func NewHandler(am sdk.AccountMapper) sdk.Handler { return func(ctx sdk.Context, tx sdk.Tx) sdk.Result { - cs := CoinStore{accStore} + cm := CoinMapper{am} msg := tx.(sdk.Msg) switch msg := msg.(type) { case SendMsg: - return handleSendMsg(ctx, cs, msg) + return handleSendMsg(ctx, cm, msg) case IssueMsg: - return handleIssueMsg(ctx, cs, msg) + return handleIssueMsg(ctx, cm, msg) default: return sdk.Result{ Code: 1, // TODO @@ -27,11 +27,11 @@ func NewHandler(accStore sdk.AccountStore) sdk.Handler { } // Handle SendMsg. -func handleSendMsg(ctx sdk.Context, cs CoinStore, msg SendMsg) sdk.Result { +func handleSendMsg(ctx sdk.Context, cm CoinMapper, msg SendMsg) sdk.Result { // NOTE: totalIn == totalOut should already have been checked for _, in := range msg.Inputs { - _, err := cs.SubtractCoins(ctx, in.Address, in.Coins) + _, err := cm.SubtractCoins(ctx, in.Address, in.Coins) if err != nil { return sdk.Result{ Code: 1, // TODO @@ -40,7 +40,7 @@ func handleSendMsg(ctx sdk.Context, cs CoinStore, msg SendMsg) sdk.Result { } for _, out := range msg.Outputs { - _, err := cs.AddCoins(ctx, out.Address, out.Coins) + _, err := cm.AddCoins(ctx, out.Address, out.Coins) if err != nil { return sdk.Result{ Code: 1, // TODO @@ -52,6 +52,6 @@ func handleSendMsg(ctx sdk.Context, cs CoinStore, msg SendMsg) sdk.Result { } // Handle IssueMsg. -func handleIssueMsg(ctx sdk.Context, cs CoinStore, msg IssueMsg) sdk.Result { +func handleIssueMsg(ctx sdk.Context, cm CoinMapper, msg IssueMsg) sdk.Result { panic("not implemented yet") } diff --git a/x/bank/store.go b/x/bank/mapper.go similarity index 56% rename from x/bank/store.go rename to x/bank/mapper.go index b28013ac7a..5567fd8ac1 100644 --- a/x/bank/store.go +++ b/x/bank/mapper.go @@ -7,14 +7,14 @@ import ( crypto "github.com/tendermint/go-crypto" ) -// CoinStore manages transfers between accounts -type CoinStore struct { - store sdk.AccountStore +// CoinMapper manages transfers between accounts +type CoinMapper struct { + am sdk.AccountMapper } // SubtractCoins subtracts amt from the coins at the addr. -func (cs CoinStore) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, error) { - acc := cs.store.GetAccount(ctx, addr) +func (cm CoinMapper) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, error) { + acc := cm.am.GetAccount(ctx, addr) if acc == nil { return amt, fmt.Errorf("Sending account (%s) does not exist", addr) } @@ -26,21 +26,21 @@ func (cs CoinStore) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk. } acc.SetCoins(newCoins) - cs.store.SetAccount(ctx, acc) + cm.am.SetAccount(ctx, acc) return newCoins, nil } // AddCoins adds amt to the coins at the addr. -func (cs CoinStore) AddCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, error) { - acc := cs.store.GetAccount(ctx, addr) +func (cm CoinMapper) AddCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, error) { + acc := cm.am.GetAccount(ctx, addr) if acc == nil { - acc = cs.store.NewAccountWithAddress(ctx, addr) + acc = cm.am.NewAccountWithAddress(ctx, addr) } coins := acc.GetCoins() newCoins := coins.Plus(amt) acc.SetCoins(newCoins) - cs.store.SetAccount(ctx, acc) + cm.am.SetAccount(ctx, acc) return newCoins, nil }