Merge pull request #859 from cosmos/jae/fixrmssubstores

Support namespacing within RMS db
This commit is contained in:
Christopher Goes 2018-04-15 02:35:15 +02:00 committed by GitHub
commit b846559ac1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 152 additions and 197 deletions

View File

@ -2,18 +2,20 @@
## 0.15.0 (TBD) ## 0.15.0 (TBD)
FEATURES:
* Add CacheContext
* Add auto sequencing to client
BREAKING CHANGES BREAKING CHANGES
* Remove go-wire, use go-amino * Remove go-wire, use go-amino
* [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface * [store] Add `SubspaceIterator` and `ReverseSubspaceIterator` to `KVStore` interface
* [basecoin] NewBasecoinApp takes a `dbm.DB` and uses namespaced DBs for substores
FEATURES: BUG FIXES
* Add CacheContext * MountStoreWithDB without providing a custom store works.
FEATURES:
* Add auto sequencing to client
## 0.14.1 (April 9, 2018) ## 0.14.1 (April 9, 2018)

18
Gopkg.lock generated
View File

@ -215,8 +215,8 @@
[[projects]] [[projects]]
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.0" version = "v1.0.1"
[[projects]] [[projects]]
name = "github.com/spf13/viper" name = "github.com/spf13/viper"
@ -342,8 +342,8 @@
"types/priv_validator", "types/priv_validator",
"version" "version"
] ]
revision = "dcd00b0e688f133b9634aee513f8bf856e659356" revision = "d0beaba7e8a5652506a34b5fab299cc2dc274c02"
version = "v0.19.0-rc4" version = "v0.19.0"
[[projects]] [[projects]]
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
@ -360,8 +360,8 @@
"pubsub", "pubsub",
"pubsub/query" "pubsub/query"
] ]
revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c" revision = "737154202faf75c70437f59ba5303f2eb09f5636"
version = "v0.8.1" version = "0.8.2-rc1"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -377,7 +377,7 @@
"ripemd160", "ripemd160",
"salsa20/salsa" "salsa20/salsa"
] ]
revision = "b2aa35443fbc700ab74c586ae79b81c171851023" revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -424,7 +424,7 @@
branch = "master" branch = "master"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"] packages = ["googleapis/rpc/status"]
revision = "ce84044298496ef4b54b4a0a0909ba593cc60e30" revision = "51d0944304c3cbce4afe9e5247e21100037bff78"
[[projects]] [[projects]]
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
@ -459,6 +459,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "ad499422ee60cf89fd9d61e232e33d0a17f7b43e0ff7aff0c0a22949901096e8" inputs-digest = "b6b2d696a242e715ddb8b25c93b3c8f7e7cabc9292eab29dffe935eddbd35fb8"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -70,11 +70,11 @@
[[constraint]] [[constraint]]
name = "github.com/tendermint/tendermint" name = "github.com/tendermint/tendermint"
version = "0.19.0-rc4" version = "0.19.0"
[[constraint]] [[override]]
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
version = "~0.8.1" version = "~0.8.2-rc1"
[prune] [prune]
go-tests = true go-tests = true

View File

@ -71,21 +71,20 @@ func (app *BaseApp) Name() string {
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore
// Broken until #532 is implemented.
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
for _, key := range keys { for _, key := range keys {
app.MountStore(key, sdk.StoreTypeIAVL) app.MountStore(key, sdk.StoreTypeIAVL)
} }
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore, using a specified DB
func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) { func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) {
app.cms.MountStoreWithDB(key, typ, db) app.cms.MountStoreWithDB(key, typ, db)
} }
// Mount a store to the provided key in the BaseApp multistore // Mount a store to the provided key in the BaseApp multistore, using the default DB
func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
app.cms.MountStoreWithDB(key, typ, app.db) app.cms.MountStoreWithDB(key, typ, nil)
} }
// nolint - Set functions // nolint - Set functions

View File

@ -35,15 +35,12 @@ func TestMountStores(t *testing.T) {
// make some cap keys // make some cap keys
capKey1 := sdk.NewKVStoreKey("key1") capKey1 := sdk.NewKVStoreKey("key1")
db1 := dbm.NewMemDB()
capKey2 := sdk.NewKVStoreKey("key2") capKey2 := sdk.NewKVStoreKey("key2")
db2 := dbm.NewMemDB()
// no stores are mounted // no stores are mounted
assert.Panics(t, func() { app.LoadLatestVersion(capKey1) }) assert.Panics(t, func() { app.LoadLatestVersion(capKey1) })
app.MountStoreWithDB(capKey1, sdk.StoreTypeIAVL, db1) app.MountStoresIAVL(capKey1, capKey2)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
// stores are mounted // stores are mounted
err := app.LoadLatestVersion(capKey1) err := app.LoadLatestVersion(capKey1)
@ -155,11 +152,8 @@ func TestInitChainer(t *testing.T) {
// NOTE/TODO: mounting multiple stores is broken // NOTE/TODO: mounting multiple stores is broken
// see https://github.com/cosmos/cosmos-sdk/issues/532 // see https://github.com/cosmos/cosmos-sdk/issues/532
capKey := sdk.NewKVStoreKey("main") capKey := sdk.NewKVStoreKey("main")
db1 := dbm.NewMemDB()
capKey2 := sdk.NewKVStoreKey("key2") capKey2 := sdk.NewKVStoreKey("key2")
db2 := dbm.NewMemDB() app.MountStoresIAVL(capKey, capKey2)
app.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db1)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
assert.Nil(t, err) assert.Nil(t, err)
@ -191,8 +185,7 @@ func TestInitChainer(t *testing.T) {
// reload app // reload app
app = NewBaseApp(name, logger, db) app = NewBaseApp(name, logger, db)
app.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db1) app.MountStoresIAVL(capKey, capKey2)
app.MountStoreWithDB(capKey2, sdk.StoreTypeIAVL, db2)
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
assert.Nil(t, err) assert.Nil(t, err)
app.SetInitChainer(initChainer) app.SetInitChainer(initChainer)

View File

@ -333,13 +333,8 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
// logger = log.NewFilter(logger, log.AllowError()) // logger = log.NewFilter(logger, log.AllowError())
privValidatorFile := config.PrivValidatorFile() privValidatorFile := config.PrivValidatorFile()
privVal := pvm.LoadOrGenFilePV(privValidatorFile) privVal := pvm.LoadOrGenFilePV(privValidatorFile)
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), app := bapp.NewBasecoinApp(logger, db)
"acc": dbm.NewMemDB(),
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
app := bapp.NewBasecoinApp(logger, dbs)
cdc = bapp.MakeCodec() // XXX cdc = bapp.MakeCodec() // XXX
genesisFile := config.GenesisFile() genesisFile := config.GenesisFile()

View File

@ -64,7 +64,7 @@ func GetChainHeight() (int64, error) {
if err != nil { if err != nil {
return -1, err return -1, err
} }
height := status.LatestBlockHeight height := status.SyncInfo.LatestBlockHeight
return height, nil return height, nil
} }

View File

@ -77,7 +77,7 @@ func NodeSyncingRequestHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
syncing := status.Syncing syncing := status.SyncInfo.Syncing
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))

View File

@ -28,29 +28,11 @@ var (
// TODO: distinguish from basecoin // TODO: distinguish from basecoin
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dataDir := filepath.Join(rootDir, "data") dataDir := filepath.Join(rootDir, "data")
dbMain, err := dbm.NewGoLevelDB("gaia", dataDir) db, err := dbm.NewGoLevelDB("gaia", dataDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) bapp := app.NewBasecoinApp(logger, db)
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("gaia-ibc", dataDir)
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("gaia-staking", dataDir)
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewBasecoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -22,7 +22,7 @@ The SDK distinguishes between transactions (Tx) and messages
Users can create messages containing arbitrary information by Users can create messages containing arbitrary information by
implementing the `Msg` interface: implementing the `Msg` interface:
```golang ```go
type Msg interface { type Msg interface {
// Return the message type. // Return the message type.
@ -68,7 +68,7 @@ but this is mostly for convenience and not type-safe.
For instance, the `Basecoin` message types are defined in `x/bank/tx.go`: For instance, the `Basecoin` message types are defined in `x/bank/tx.go`:
```golang ```go
type SendMsg struct { type SendMsg struct {
Inputs []Input `json:"inputs"` Inputs []Input `json:"inputs"`
Outputs []Output `json:"outputs"` Outputs []Output `json:"outputs"`
@ -82,7 +82,7 @@ type IssueMsg struct {
Each specifies the addresses that must sign the message: Each specifies the addresses that must sign the message:
```golang ```go
func (msg SendMsg) GetSigners() []sdk.Address { func (msg SendMsg) GetSigners() []sdk.Address {
addrs := make([]sdk.Address, len(msg.Inputs)) addrs := make([]sdk.Address, len(msg.Inputs))
for i, in := range msg.Inputs { for i, in := range msg.Inputs {
@ -100,7 +100,7 @@ func (msg IssueMsg) GetSigners() []sdk.Address {
A transaction is a message with additional information for authentication: A transaction is a message with additional information for authentication:
```golang ```go
type Tx interface { type Tx interface {
GetMsg() Msg GetMsg() Msg
@ -120,7 +120,7 @@ The `tx.GetSignatures()` method returns a list of signatures, which must match
the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in
a standard form: a standard form:
```golang ```go
type StdSignature struct { type StdSignature struct {
crypto.PubKey // optional crypto.PubKey // optional
crypto.Signature crypto.Signature
@ -146,7 +146,7 @@ to return this.
The standard way to create a transaction from a message is to use the `StdTx`: The standard way to create a transaction from a message is to use the `StdTx`:
```golang ```go
type StdTx struct { type StdTx struct {
Msg Msg
Signatures []StdSignature Signatures []StdSignature
@ -164,7 +164,7 @@ When initializing an application, a developer must specify a `TxDecoder`
function which determines how an arbitrary byte array should be unmarshalled function which determines how an arbitrary byte array should be unmarshalled
into a `Tx`: into a `Tx`:
```golang ```go
type TxDecoder func(txBytes []byte) (Tx, error) type TxDecoder func(txBytes []byte) (Tx, error)
``` ```
@ -177,7 +177,7 @@ relevant types to be registered ahead of type. Registration happens on a
For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg` For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg`
types: types:
```golang ```go
cdc.RegisterInterface((*sdk.Msg)(nil), nil) cdc.RegisterInterface((*sdk.Msg)(nil), nil)
cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil) cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil)
cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil) cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil)
@ -189,21 +189,58 @@ same prefix-bytes, regardless of what interface it is satisfying. For more
details, see the [go-amino documentation](https://github.com/tendermint/go-amino/blob/develop). details, see the [go-amino documentation](https://github.com/tendermint/go-amino/blob/develop).
## MultiStore ## Storage
### MultiStore is like a filesystem ### MultiStore
### Mounting an IAVLStore
MultiStore is like a root filesystem of an operating system, except
all the entries are fully Merkleized. You mount onto a MultiStore
any number of Stores. Currently only KVStores are supported, but in
the future we may support more kinds of stores, such as a HeapStore
or a NDStore for multidimensional storage.
The MultiStore as well as all mounted stores provide caching (aka
cache-wrapping) for intermediate state (aka software transactional
memory) during the execution of transactions. In the case of the
KVStore, this also works for iterators. For example, after running
the app's AnteHandler, the MultiStore is cache-wrapped (and each
store is also cache-wrapped) so that should processing of the
transaction fail, at least the transaction fees are paid and
sequence incremented.
The MultiStore as well as all stores support (or will support)
historical state pruning and snapshotting and various kinds of
queries with proofs.
### KVStore
Here we'll focus on the IAVLStore, which is a kind of KVStore.
IAVLStore is a fast balanced dynamic Merkle store that also supports
iteration, and of course cache-wrapping, state pruning, and various
queries with proofs, such as proofs of existence, absence, range,
and so on.
Here's how you mount them to a MultiStore.
```go
mainDB, catDB := dbm.NewMemDB(), dbm.NewMemDB()
fooKey := sdk.NewKVStoreKey("foo")
barKey := sdk.NewKVStoreKey("bar")
catKey := sdk.NewKVStoreKey("cat")
ms := NewCommitMultiStore(mainDB)
ms.MountStoreWithDB(fooKey, sdk.StoreTypeIAVL, nil)
ms.MountStoreWithDB(barKey, sdk.StoreTypeIAVL, nil)
ms.MountStoreWithDB(catKey, sdk.StoreTypeIAVL, catDB)
``` ```
TODO:
- IAVLStore: Fast balanced dynamic Merkle store. In the example above, all IAVL nodes (inner and leaf) will be stored
- supports iteration. in mainDB with the prefix of "s/k:foo/" and "s/k:bar/" respectively,
- MultiStore: multiple Merkle tree backends in a single store thus sharing the mainDB. All IAVL nodes (inner and leaf) for the
- allows using Ethereum Patricia Trie and Tendermint IAVL in same app cat KVStore are stored separately in catDB with the prefix of
- Provide caching for intermediate state during execution of blocks and transactions (including for iteration) "s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to
- Historical state pruning and snapshotting. disambiguate store items from other items of non-storage concern.
- Query proofs (existence, absence, range, etc.) on current and retained historical state.
```
## Context ## Context
@ -223,7 +260,7 @@ Many methods on SDK objects receive a context as the first argument.
Transaction processing in the SDK is defined through `Handler` functions: Transaction processing in the SDK is defined through `Handler` functions:
```golang ```go
type Handler func(ctx Context, tx Tx) Result type Handler func(ctx Context, tx Tx) Result
``` ```
@ -237,7 +274,7 @@ to a particular store (or two or more). Access to stores is managed using
capabilities keys and mappers. When a handler is initialized, it is passed a capabilities keys and mappers. When a handler is initialized, it is passed a
key or mapper that gives it access to the relevant stores. key or mapper that gives it access to the relevant stores.
```golang ```go
// File: cosmos-sdk/examples/basecoin/app/init_stores.go // File: cosmos-sdk/examples/basecoin/app/init_stores.go
app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL)
app.accountMapper = auth.NewAccountMapper( app.accountMapper = auth.NewAccountMapper(

View File

@ -38,14 +38,14 @@ type BasecoinApp struct {
accountMapper sdk.AccountMapper accountMapper sdk.AccountMapper
} }
func NewBasecoinApp(logger log.Logger, dbs map[string]dbm.DB) *BasecoinApp { func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
// Create app-level codec for txs and accounts. // Create app-level codec for txs and accounts.
var cdc = MakeCodec() var cdc = MakeCodec()
// Create your application object. // Create your application object.
var app = &BasecoinApp{ var app = &BasecoinApp{
BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), BaseApp: bam.NewBaseApp(appName, logger, db),
cdc: cdc, cdc: cdc,
capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyMainStore: sdk.NewKVStoreKey("main"),
capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyAccountStore: sdk.NewKVStoreKey("acc"),
@ -72,12 +72,7 @@ func NewBasecoinApp(logger log.Logger, dbs map[string]dbm.DB) *BasecoinApp {
// Initialize BaseApp. // Initialize BaseApp.
app.SetTxDecoder(app.txDecoder) app.SetTxDecoder(app.txDecoder)
app.SetInitChainer(app.initChainer) app.SetInitChainer(app.initChainer)
app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"])
app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"])
app.MountStoreWithDB(app.capKeyStakingStore, sdk.StoreTypeIAVL, dbs["staking"])
// NOTE: Broken until #532 lands
//app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper))
err := app.LoadLatestVersion(app.capKeyMainStore) err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil { if err != nil {

View File

@ -85,20 +85,15 @@ var (
} }
) )
func loggerAndDBs() (log.Logger, map[string]dbm.DB) { func loggerAndDB() (log.Logger, dbm.DB) {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), return logger, db
"acc": dbm.NewMemDB(),
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
return logger, dbs
} }
func newBasecoinApp() *BasecoinApp { func newBasecoinApp() *BasecoinApp {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
return NewBasecoinApp(logger, dbs) return NewBasecoinApp(logger, db)
} }
func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error { func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
@ -142,8 +137,8 @@ func TestMsgs(t *testing.T) {
} }
func TestSortGenesis(t *testing.T) { func TestSortGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewBasecoinApp(logger, dbs) bapp := NewBasecoinApp(logger, db)
// Note the order: the coins are unsorted! // Note the order: the coins are unsorted!
coinDenom1, coinDenom2 := "foocoin", "barcoin" coinDenom1, coinDenom2 := "foocoin", "barcoin"
@ -184,8 +179,8 @@ func TestSortGenesis(t *testing.T) {
} }
func TestGenesis(t *testing.T) { func TestGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewBasecoinApp(logger, dbs) bapp := NewBasecoinApp(logger, db)
// Construct some genesis bytes to reflect basecoin/types/AppAccount // Construct some genesis bytes to reflect basecoin/types/AppAccount
pk := crypto.GenPrivKeyEd25519().PubKey() pk := crypto.GenPrivKeyEd25519().PubKey()
@ -207,7 +202,7 @@ func TestGenesis(t *testing.T) {
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
// reload app and ensure the account is still there // reload app and ensure the account is still there
bapp = NewBasecoinApp(logger, dbs) bapp = NewBasecoinApp(logger, db)
ctx = bapp.BaseApp.NewContext(true, abci.Header{}) ctx = bapp.BaseApp.NewContext(true, abci.Header{})
res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address) res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)

View File

@ -27,29 +27,11 @@ var (
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dataDir := filepath.Join(rootDir, "data") dataDir := filepath.Join(rootDir, "data")
dbMain, err := dbm.NewGoLevelDB("basecoin", dataDir) db, err := dbm.NewGoLevelDB("basecoin", dataDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("basecoin-acc", dataDir) bapp := app.NewBasecoinApp(logger, db)
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("basecoin-ibc", dataDir)
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("basecoin-staking", dataDir)
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewBasecoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -42,14 +42,14 @@ type DemocoinApp struct {
accountMapper sdk.AccountMapper accountMapper sdk.AccountMapper
} }
func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp { func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
// Create app-level codec for txs and accounts. // Create app-level codec for txs and accounts.
var cdc = MakeCodec() var cdc = MakeCodec()
// Create your application object. // Create your application object.
var app = &DemocoinApp{ var app = &DemocoinApp{
BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), BaseApp: bam.NewBaseApp(appName, logger, db),
cdc: cdc, cdc: cdc,
capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyMainStore: sdk.NewKVStoreKey("main"),
capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyAccountStore: sdk.NewKVStoreKey("acc"),
@ -82,13 +82,7 @@ func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp {
// Initialize BaseApp. // Initialize BaseApp.
app.SetTxDecoder(app.txDecoder) app.SetTxDecoder(app.txDecoder)
app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper)) app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper))
app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"])
app.MountStoreWithDB(app.capKeyPowStore, sdk.StoreTypeIAVL, dbs["pow"])
app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"])
app.MountStoreWithDB(app.capKeyStakingStore, sdk.StoreTypeIAVL, dbs["staking"])
// NOTE: Broken until #532 lands
//app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper))
err := app.LoadLatestVersion(app.capKeyMainStore) err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil { if err != nil {

View File

@ -67,21 +67,15 @@ var (
} }
) )
func loggerAndDBs() (log.Logger, map[string]dbm.DB) { func loggerAndDB() (log.Logger, dbm.DB) {
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
dbs := map[string]dbm.DB{ db := dbm.NewMemDB()
"main": dbm.NewMemDB(), return logger, db
"acc": dbm.NewMemDB(),
"pow": dbm.NewMemDB(),
"ibc": dbm.NewMemDB(),
"staking": dbm.NewMemDB(),
}
return logger, dbs
} }
func newDemocoinApp() *DemocoinApp { func newDemocoinApp() *DemocoinApp {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
return NewDemocoinApp(logger, dbs) return NewDemocoinApp(logger, db)
} }
//_______________________________________________________________________ //_______________________________________________________________________
@ -123,8 +117,8 @@ func TestMsgs(t *testing.T) {
} }
func TestGenesis(t *testing.T) { func TestGenesis(t *testing.T) {
logger, dbs := loggerAndDBs() logger, db := loggerAndDB()
bapp := NewDemocoinApp(logger, dbs) bapp := NewDemocoinApp(logger, db)
// Construct some genesis bytes to reflect democoin/types/AppAccount // Construct some genesis bytes to reflect democoin/types/AppAccount
pk := crypto.GenPrivKeyEd25519().PubKey() pk := crypto.GenPrivKeyEd25519().PubKey()
@ -157,7 +151,7 @@ func TestGenesis(t *testing.T) {
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)
// reload app and ensure the account is still there // reload app and ensure the account is still there
bapp = NewDemocoinApp(logger, dbs) bapp = NewDemocoinApp(logger, db)
ctx = bapp.BaseApp.NewContext(true, abci.Header{}) ctx = bapp.BaseApp.NewContext(true, abci.Header{})
res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address) res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
assert.Equal(t, acc, res1) assert.Equal(t, acc, res1)

View File

@ -47,34 +47,11 @@ func defaultAppState(args []string, addr sdk.Address, coinDenom string) (json.Ra
} }
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
dbMain, err := dbm.NewGoLevelDB("democoin", filepath.Join(rootDir, "data")) db, err := dbm.NewGoLevelDB("democoin", filepath.Join(rootDir, "data"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbAcc, err := dbm.NewGoLevelDB("democoin-acc", filepath.Join(rootDir, "data")) bapp := app.NewDemocoinApp(logger, db)
if err != nil {
return nil, err
}
dbPow, err := dbm.NewGoLevelDB("democoin-pow", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbIBC, err := dbm.NewGoLevelDB("democoin-ibc", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbStaking, err := dbm.NewGoLevelDB("democoin-staking", filepath.Join(rootDir, "data"))
if err != nil {
return nil, err
}
dbs := map[string]dbm.DB{
"main": dbMain,
"acc": dbAcc,
"pow": dbPow,
"ibc": dbIBC,
"staking": dbStaking,
}
bapp := app.NewDemocoinApp(logger, dbs)
return bapp, nil return bapp, nil
} }

View File

@ -56,8 +56,9 @@ func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.D
panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key)) panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key))
} }
rs.storesParams[key] = storeParams{ rs.storesParams[key] = storeParams{
db: db, key: key,
typ: typ, typ: typ,
db: db,
} }
rs.keysByName[key.Name()] = key rs.keysByName[key.Name()] = key
} }
@ -244,9 +245,11 @@ func parsePath(path string) (storeName string, subpath string, err sdk.Error) {
//---------------------------------------- //----------------------------------------
func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) { func (rs *rootMultiStore) loadCommitStoreFromParams(id CommitID, params storeParams) (store CommitStore, err error) {
db := rs.db var db dbm.DB
if params.db != nil { if params.db != nil {
db = params.db db = dbm.NewPrefixDB(params.db, []byte("s/_/"))
} else {
db = dbm.NewPrefixDB(rs.db, []byte("s/k:"+params.key.Name()+"/"))
} }
switch params.typ { switch params.typ {
case sdk.StoreTypeMulti: case sdk.StoreTypeMulti:
@ -276,6 +279,7 @@ func (rs *rootMultiStore) nameToKey(name string) StoreKey {
// storeParams // storeParams
type storeParams struct { type storeParams struct {
key StoreKey
db dbm.DB db dbm.DB
typ StoreType typ StoreType
} }
@ -375,10 +379,11 @@ func commitStores(version int64, storeMap map[StoreKey]CommitStore) commitInfo {
storeInfos = append(storeInfos, si) storeInfos = append(storeInfos, si)
} }
return commitInfo{ ci := commitInfo{
Version: version, Version: version,
StoreInfos: storeInfos, StoreInfos: storeInfos,
} }
return ci
} }
// Gets commitInfo from disk. // Gets commitInfo from disk.

View File

@ -11,17 +11,22 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
const useDebugDB = false
func TestMultistoreCommitLoad(t *testing.T) { func TestMultistoreCommitLoad(t *testing.T) {
db := dbm.NewMemDB() var db dbm.DB = dbm.NewMemDB()
if useDebugDB {
db = dbm.NewDebugDB("CMS", db)
}
store := newMultiStoreWithMounts(db) store := newMultiStoreWithMounts(db)
err := store.LoadLatestVersion() err := store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
// new store has empty last commit // New store has empty last commit.
commitID := CommitID{} commitID := CommitID{}
checkStore(t, store, commitID, commitID) checkStore(t, store, commitID, commitID)
// make sure we can get stores by name // Make sure we can get stores by name.
s1 := store.getStoreByName("store1") s1 := store.getStoreByName("store1")
assert.NotNil(t, s1) assert.NotNil(t, s1)
s3 := store.getStoreByName("store3") s3 := store.getStoreByName("store3")
@ -29,7 +34,7 @@ func TestMultistoreCommitLoad(t *testing.T) {
s77 := store.getStoreByName("store77") s77 := store.getStoreByName("store77")
assert.Nil(t, s77) assert.Nil(t, s77)
// make a few commits and check them // Make a few commits and check them.
nCommits := int64(3) nCommits := int64(3)
for i := int64(0); i < nCommits; i++ { for i := int64(0); i < nCommits; i++ {
commitID = store.Commit() commitID = store.Commit()
@ -37,19 +42,19 @@ func TestMultistoreCommitLoad(t *testing.T) {
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
} }
// Load the latest multistore again and check version // Load the latest multistore again and check version.
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadLatestVersion() err = store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
commitID = getExpectedCommitID(store, nCommits) commitID = getExpectedCommitID(store, nCommits)
checkStore(t, store, commitID, commitID) checkStore(t, store, commitID, commitID)
// commit and check version // Commit and check version.
commitID = store.Commit() commitID = store.Commit()
expectedCommitID := getExpectedCommitID(store, nCommits+1) expectedCommitID := getExpectedCommitID(store, nCommits+1)
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
// Load an older multistore and check version // Load an older multistore and check version.
ver := nCommits - 1 ver := nCommits - 1
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadVersion(ver) err = store.LoadVersion(ver)
@ -62,8 +67,8 @@ func TestMultistoreCommitLoad(t *testing.T) {
expectedCommitID = getExpectedCommitID(store, ver+1) expectedCommitID = getExpectedCommitID(store, ver+1)
checkStore(t, store, expectedCommitID, commitID) checkStore(t, store, expectedCommitID, commitID)
// XXX: confirm old commit is overwritten and // XXX: confirm old commit is overwritten and we have rolled back
// we have rolled back LatestVersion // LatestVersion
store = newMultiStoreWithMounts(db) store = newMultiStoreWithMounts(db)
err = store.LoadLatestVersion() err = store.LoadLatestVersion()
assert.Nil(t, err) assert.Nil(t, err)
@ -104,23 +109,23 @@ func TestMultiStoreQuery(t *testing.T) {
cid := multi.Commit() cid := multi.Commit()
// make sure we can get by name // Make sure we can get by name.
garbage := multi.getStoreByName("bad-name") garbage := multi.getStoreByName("bad-name")
assert.Nil(t, garbage) assert.Nil(t, garbage)
// set and commit data in one store // Set and commit data in one store.
store1 := multi.getStoreByName("store1").(KVStore) store1 := multi.getStoreByName("store1").(KVStore)
store1.Set(k, v) store1.Set(k, v)
// and another // ... and another.
store2 := multi.getStoreByName("store2").(KVStore) store2 := multi.getStoreByName("store2").(KVStore)
store2.Set(k2, v2) store2.Set(k2, v2)
// commit the multistore // Commit the multistore.
cid = multi.Commit() cid = multi.Commit()
ver := cid.Version ver := cid.Version
// bad path // Test bad path.
query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} query := abci.RequestQuery{Path: "/key", Data: k, Height: ver}
qres := multi.Query(query) qres := multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
@ -129,25 +134,25 @@ func TestMultiStoreQuery(t *testing.T) {
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
// invalid store name // Test invalid store name.
query.Path = "/garbage/key" query.Path = "/garbage/key"
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code) assert.Equal(t, uint32(sdk.CodeUnknownRequest), qres.Code)
// valid query with data // Test valid query with data.
query.Path = "/store1/key" query.Path = "/store1/key"
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
assert.Equal(t, v, qres.Value) assert.Equal(t, v, qres.Value)
// valid but empty // Test valid but empty query.
query.Path = "/store2/key" query.Path = "/store2/key"
query.Prove = true query.Prove = true
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
assert.Nil(t, qres.Value) assert.Nil(t, qres.Value)
// store2 data // Test store2 data.
query.Data = k2 query.Data = k2
qres = multi.Query(query) qres = multi.Query(query)
assert.Equal(t, uint32(sdk.CodeOK), qres.Code) assert.Equal(t, uint32(sdk.CodeOK), qres.Code)

View File

@ -9,7 +9,7 @@ const Maj = "0"
const Min = "15" const Min = "15"
const Fix = "0" const Fix = "0"
const Version = "0.15.0-rc1" const Version = "0.15.0-rc0"
// GitCommit set by build flags // GitCommit set by build flags
var GitCommit = "" var GitCommit = ""