From 3acc94e7cd5b1308d4e80f06a1aad55291085cf5 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 21 Dec 2017 20:19:44 -0800 Subject: [PATCH 1/6] WIP: Fixing App to compile --- app/app.go | 219 ++++++++++++++++----------------------------------- app/query.go | 54 +++++++++++++ 2 files changed, 122 insertions(+), 151 deletions(-) create mode 100644 app/query.go diff --git a/app/app.go b/app/app.go index 75867f791551..39803d8df72d 100644 --- a/app/app.go +++ b/app/app.go @@ -8,10 +8,9 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" abci "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" - sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/types" ) const mainKeyHeader = "header" @@ -24,16 +23,16 @@ type App struct { name string // DeliverTx (main) state - store MultiStore + store types.MultiStore // CheckTx state - storeCheck CacheMultiStore + storeCheck types.CacheMultiStore // Current block header header *abci.Header // Handler for CheckTx and DeliverTx. - handler sdk.Handler + handler types.Handler // Cached validator changes from DeliverTx valUpdates []abci.Validator @@ -48,17 +47,17 @@ func NewApp(name string) *App { } } -func (app *App) SetStore(store MultiStore) { +func (app *App) SetStore(store types.MultiStore) { app.store = store } -func (app *App) SetHandler(handler Handler) { +func (app *App) SetHandler(handler types.Handler) { app.handler = handler } func (app *App) LoadLatestVersion() error { store := app.store - store.LoadLastVersion() + store.LoadLatestVersion() return app.initFromStore() } @@ -108,41 +107,44 @@ func (app *App) initFromStore() error { //---------------------------------------- -// DeliverTx - ABCI - dispatches to the handler -func (app *App) DeliverTx(txBytes []byte) abci.ResponseDeliverTx { - - // Initialize arguments to Handler. - var isCheckTx = false - var ctx = sdk.NewContext(app.header, isCheckTx, txBytes) - var store = app.store - var tx Tx = nil // nil until a decorator parses one. +// Implements ABCI +func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { - // Run the handler. - var result = app.handler(ctx, app.store, tx) + lastCommitID := app.store.LastCommitID() - // After-handler hooks. - if result.Code == abci.CodeType_OK { - app.valUpdates = append(app.valUpdates, result.ValUpdate) - } else { - // Even though the Code is not OK, there will be some side effects, - // like those caused by fee deductions or sequence incrementations. + return abci.ResponseInfo{ + Data: app.Name, + LastBlockHeight: lastCommitID.Version, + LastBlockAppHash: lastCommitID.Hash, } +} - // Tell the blockchain engine (i.e. Tendermint). - return abci.ResponseDeliverTx{ - Code: result.Code, - Data: result.Data, - Log: result.Log, - Tags: result.Tags, - } +// Implements ABCI +func (app *App) SetOption(req abci.RequestSetOption) abci.ResponseSetOption { + return "Not Implemented" +} + +// Implements ABCI +func (app *App) InitChain(req abci.RequestInitChain) abci.ResponseInitChain { + // TODO: Use req.Validators +} + +// Implements ABCI +func (app *App) Query(req abci.RequestQuery) abci.ResponseQuery { + // TODO: See app/query.go +} + +// Implements ABCI +func (app *App) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock { + app.header = req.Header } -// CheckTx - ABCI - dispatches to the handler +// Implements ABCI func (app *App) CheckTx(txBytes []byte) abci.ResponseCheckTx { // Initialize arguments to Handler. var isCheckTx = true - var ctx = sdk.NewContext(app.header, isCheckTx, txBytes) + var ctx = types.NewContext(app.header, isCheckTx, txBytes) var store = app.store var tx Tx = nil // nil until a decorator parses one. @@ -160,81 +162,45 @@ func (app *App) CheckTx(txBytes []byte) abci.ResponseCheckTx { } } -// Info - ABCI -func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { +// Implements ABCI +func (app *App) DeliverTx(txBytes []byte) abci.ResponseDeliverTx { - lastCommitID := app.store.LastCommitID() + // Initialize arguments to Handler. + var isCheckTx = false + var ctx = types.NewContext(app.header, isCheckTx, txBytes) + var store = app.store + var tx Tx = nil // nil until a decorator parses one. - return abci.ResponseInfo{ - Data: app.Name, - LastBlockHeight: lastCommitID.Version, - LastBlockAppHash: lastCommitID.Hash, + // Run the handler. + var result = app.handler(ctx, app.store, tx) + + // After-handler hooks. + if result.Code == abci.CodeType_OK { + app.valUpdates = append(app.valUpdates, result.ValUpdate) + } else { + // Even though the Code is not OK, there will be some side effects, + // like those caused by fee deductions or sequence incrementations. } -} -// SetOption - ABCI -func (app *App) SetOption(key string, value string) string { - return "Not Implemented" + // Tell the blockchain engine (i.e. Tendermint). + return abci.ResponseDeliverTx{ + Code: result.Code, + Data: result.Data, + Log: result.Log, + Tags: result.Tags, + } } -// Query - ABCI -func (app *App) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { - /* - XXX Make this work with MultiStore. - XXX It will require some interfaces updates in store/types.go. - - if len(reqQuery.Data) == 0 { - resQuery.Log = "Query cannot be zero length" - resQuery.Code = abci.CodeType_EncodingError - return - } - - // set the query response height to current - tree := app.state.Committed() - - height := reqQuery.Height - if height == 0 { - // TODO: once the rpc actually passes in non-zero - // heights we can use to query right after a tx - // we must retrun most recent, even if apphash - // is not yet in the blockchain - - withProof := app.CommittedHeight() - 1 - if tree.Tree.VersionExists(withProof) { - height = withProof - } else { - height = app.CommittedHeight() - } - } - resQuery.Height = height - - switch reqQuery.Path { - case "/store", "/key": // Get by key - key := reqQuery.Data // Data holds the key bytes - resQuery.Key = key - if reqQuery.Prove { - value, proof, err := tree.GetVersionedWithProof(key, height) - if err != nil { - resQuery.Log = err.Error() - break - } - resQuery.Value = value - resQuery.Proof = proof.Bytes() - } else { - value := tree.Get(key) - resQuery.Value = value - } - - default: - resQuery.Code = abci.CodeType_UnknownRequest - resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path) - } - return - */ +// Implements ABCI +func (app *App) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { + // XXX Update to res.Updates. + res.ValidatorUpdates = app.valUpdates + app.valUpdates = nil + return } -// Commit implements abci.Application -func (app *App) Commit() (res abci.Result) { +// Implements ABCI +func (app *App) Commit() (res abci.ResponseCommit) { commitID := app.store.Commit() app.logger.Debug("Commit synced", "commit", commitID, @@ -242,22 +208,8 @@ func (app *App) Commit() (res abci.Result) { return abci.NewResultOK(hash, "") } -// InitChain - ABCI -func (app *App) InitChain(req abci.RequestInitChain) {} - -// BeginBlock - ABCI -func (app *App) BeginBlock(req abci.RequestBeginBlock) { - app.header = req.Header -} - -// EndBlock - ABCI -// Returns a list of all validator changes made in this block -func (app *App) EndBlock(height uint64) (res abci.ResponseEndBlock) { - // XXX Update to res.Updates. - res.Diffs = app.valUpdates - app.valUpdates = nil - return -} +//---------------------------------------- +// Misc. // Return index of list with validator of same PubKey, or -1 if no match func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { @@ -275,38 +227,3 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { func makeDefaultLogger() log.Logger { return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") } - -// InitState - used to setup state (was SetOption) -// to be call from setting up the genesis file -func (app *InitApp) InitState(module, key, value string) error { - state := app.Append() - logger := app.Logger().With("module", module, "key", key) - - if module == sdk.ModuleNameBase { - if key == sdk.ChainKey { - app.info.SetChainID(state, value) - return nil - } - logger.Error("Invalid genesis option") - return fmt.Errorf("Unknown base option: %s", key) - } - - log, err := app.initState.InitState(logger, state, module, key, value) - if err != nil { - logger.Error("Invalid genesis option", "err", err) - } else { - logger.Info(log) - } - return err -} - -// InitChain - ABCI - sets the initial validators -func (app *InitApp) InitChain(req abci.RequestInitChain) { - // return early if no InitValidator registered - if app.initVals == nil { - return - } - - logger, store := app.Logger(), app.Append() - app.initVals.InitValidators(logger, store, req.Validators) -} diff --git a/app/query.go b/app/query.go new file mode 100644 index 000000000000..908a551ea5f1 --- /dev/null +++ b/app/query.go @@ -0,0 +1,54 @@ +package app + +/* + XXX Make this work with MultiStore. + XXX It will require some interfaces updates in store/types.go. + + if len(reqQuery.Data) == 0 { + resQuery.Log = "Query cannot be zero length" + resQuery.Code = abci.CodeType_EncodingError + return + } + + // set the query response height to current + tree := app.state.Committed() + + height := reqQuery.Height + if height == 0 { + // TODO: once the rpc actually passes in non-zero + // heights we can use to query right after a tx + // we must retrun most recent, even if apphash + // is not yet in the blockchain + + withProof := app.CommittedHeight() - 1 + if tree.Tree.VersionExists(withProof) { + height = withProof + } else { + height = app.CommittedHeight() + } + } + resQuery.Height = height + + switch reqQuery.Path { + case "/store", "/key": // Get by key + key := reqQuery.Data // Data holds the key bytes + resQuery.Key = key + if reqQuery.Prove { + value, proof, err := tree.GetVersionedWithProof(key, height) + if err != nil { + resQuery.Log = err.Error() + break + } + resQuery.Value = value + resQuery.Proof = proof.Bytes() + } else { + value := tree.Get(key) + resQuery.Value = value + } + + default: + resQuery.Code = abci.CodeType_UnknownRequest + resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path) + } + return +*/ From 623e77d5a2a45ff318afcb576349c7f572007523 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 21 Dec 2017 23:30:14 -0800 Subject: [PATCH 2/6] Context is more immutable --- types/context.go | 98 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/types/context.go b/types/context.go index d0730748f3f6..4a2296ecd16a 100644 --- a/types/context.go +++ b/types/context.go @@ -2,10 +2,46 @@ package types import ( "context" + "github.com/golang/protobuf/proto" abci "github.com/tendermint/abci/types" ) +/* + +A note on Context security: + +The intent of Context is for it to be an immutable object that can be cloned +and updated cheaply with WithValue() and passed forward to the next decorator +or handler. For example, + +```golang +func Decorator(ctx Context, ms MultiStore, tx Tx, next Handler) Result { + + // Clone and update context with new kv pair. + ctx2 := ctx.WithValueSDK(key, value) + + // Call the next decorator/handler. + res := next(ctx2, ms, tx) + + // At this point, while `ctx` and `ctx2`'s shallow values haven't changed, + // it's possible that slices or addressable struct fields have been + // modified by the call to `next(...)`. + // + // This is generally undesirable because it prevents a decorator from + // rolling back all side effects--which is the intent of immutable + // `Context`s and store cache-wraps. +} +``` + +While well-written decorators wouldn't mutate any mutable context values, a malicious or buggy plugin can create unwanted side-effects, so it is highly advised for users of Context to only set immutable values. To help enforce this contract, we require values to be certain primitive types, or a Cloner. + +*/ + +type Cloner interface { + Clone() interface{} // deep copy +} + type Context struct { context.Context // Don't add any other fields here, @@ -13,9 +49,7 @@ type Context struct { } func NewContext(header abci.Header, isCheckTx bool, txBytes []byte) Context { - c := Context{ - Context: context.Background(), - } + c := Context{context.Background()} c = c.setBlockHeader(header) c = c.setBlockHeight(header.Height) c = c.setChainID(header.ChainID) @@ -24,16 +58,47 @@ func NewContext(header abci.Header, isCheckTx bool, txBytes []byte) Context { return c } -// The original context.Context API. -func (c Context) WithValue(key interface{}, value interface{}) context.Context { - return context.WithValue(c.Context, key, value) +func (c Context) Value(key interface{}) interface{} { + value := c.Context.Value(key) + if cloner, ok := value.(Cloner); ok { + return cloner.Clone() + } + if message, ok := value.(proto.Message); ok { + return proto.Clone(message) + } + return value +} + +func (c Context) WithValue(key interface{}, value Cloner) Context { + return c.withValue(key, value) } -// Like WithValue() but retains this API. -func (c Context) WithValueSDK(key interface{}, value interface{}) Context { - return Context{ - Context: context.WithValue(c.Context, key, value), - } +func (c Context) WithValueProto(key interface{}, value proto.Message) Context { + return c.withValue(key, value) +} + +func (c Context) WithValueString(key interface{}, value string) Context { + return c.withValue(key, value) +} + +func (c Context) WithValueInt32(key interface{}, value int32) Context { + return c.withValue(key, value) +} + +func (c Context) WithValueUint32(key interface{}, value uint32) Context { + return c.withValue(key, value) +} + +func (c Context) WithValueUint64(key interface{}, value uint64) Context { + return c.withValue(key, value) +} + +func (c Context) WithValueUnsafe(key interface{}, value interface{}) Context { + return c.withValue(key, value) +} + +func (c Context) withValue(key interface{}, value interface{}) Context { + return Context{context.WithValue(c.Context, key, value)} } //---------------------------------------- @@ -71,25 +136,26 @@ func (c Context) TxBytes() []byte { // Unexposed to prevent overriding. func (c Context) setBlockHeader(header abci.Header) Context { - return c.WithValueSDK(contextKeyBlockHeader, header) + var _ proto.Message = header // for cloning. + return c.withValue(contextKeyBlockHeader, header) } // Unexposed to prevent overriding. func (c Context) setBlockHeight(height int64) Context { - return c.WithValueSDK(contextKeyBlockHeight, height) + return c.withValue(contextKeyBlockHeight, height) } // Unexposed to prevent overriding. func (c Context) setChainID(chainID string) Context { - return c.WithValueSDK(contextKeyChainID, chainID) + return c.withValue(contextKeyChainID, chainID) } // Unexposed to prevent overriding. func (c Context) setIsCheckTx(isCheckTx bool) Context { - return c.WithValueSDK(contextKeyIsCheckTx, isCheckTx) + return c.withValue(contextKeyIsCheckTx, isCheckTx) } // Unexposed to prevent overriding. func (c Context) setTxBytes(txBytes []byte) Context { - return c.WithValueSDK(contextKeyTxBytes, txBytes) + return c.withValue(contextKeyTxBytes, txBytes) } From e308810a510421dd0b8ec0f1764ea158e7abd845 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 21 Dec 2017 23:30:44 -0800 Subject: [PATCH 3/6] WIP app.go... --- app/app.go | 60 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/app/app.go b/app/app.go index 39803d8df72d..6f107f2b7cd1 100644 --- a/app/app.go +++ b/app/app.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/types" ) -const mainKeyHeader = "header" +var mainHeaderKey = "header" // App - The ABCI application type App struct { @@ -22,12 +22,15 @@ type App struct { // App name from abci.Info name string - // DeliverTx (main) state - store types.MultiStore + // Main (uncached) state + store types.CommitMultiStore - // CheckTx state + // CheckTx state, a cache-wrap of store. storeCheck types.CacheMultiStore + // DeliverTx state, a cache-wrap of store. + storeDeliver types.CacheMultiStore + // Current block header header *abci.Header @@ -47,7 +50,11 @@ func NewApp(name string) *App { } } -func (app *App) SetStore(store types.MultiStore) { +func (app *App) Name() string { + return app.name +} + +func (app *App) SetCommitStore(store types.CommitMultiStore) { app.store = store } @@ -73,33 +80,34 @@ func (app *App) initFromStore() error { lastCommitID := store.LastCommitID() main := store.GetKVStore("main") header := (*abci.Header)(nil) - storeCheck := store.CacheMultiStore() // Main store should exist. if store.GetKVStore("main") == nil { return errors.New("App expects MultiStore with 'main' KVStore") } - // If we've committed before, we expect main://. + // If we've committed before, we expect main://. if !lastCommitID.IsZero() { - headerBytes, ok := main.Get(mainKeyHeader) - if !ok { - errStr := fmt.Sprintf("Version > 0 but missing key %s", mainKeyHeader) + headerBytes := main.Get(mainHeaderKey) + if len(headerBytes) == 0 { + errStr := fmt.Sprintf("Version > 0 but missing key %s", mainHeaderKey) return errors.New(errStr) } - err = proto.Unmarshal(headerBytes, header) + err := proto.Unmarshal(headerBytes, header) if err != nil { return errors.Wrap(err, "Failed to parse Header") } - if header.Height != lastCommitID.Version { - errStr := fmt.Sprintf("Expected main://%s.Height %v but got %v", mainKeyHeader, version, headerHeight) + lastVersion := lastCommitID.Version + if header.Height != lastVersion { + errStr := fmt.Sprintf("Expected main://%s.Height %v but got %v", mainHeaderKey, lastVersion, header.Height) return errors.New(errStr) } } // Set App state. app.header = header - app.storeCheck = app.store.CacheMultiStore() + app.storeCheck = nil + app.storeDeliver = nil app.valUpdates = nil return nil @@ -113,34 +121,40 @@ func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { lastCommitID := app.store.LastCommitID() return abci.ResponseInfo{ - Data: app.Name, + Data: app.name, LastBlockHeight: lastCommitID.Version, LastBlockAppHash: lastCommitID.Hash, } } // Implements ABCI -func (app *App) SetOption(req abci.RequestSetOption) abci.ResponseSetOption { - return "Not Implemented" +func (app *App) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOption) { + // TODO: Implement + return } // Implements ABCI -func (app *App) InitChain(req abci.RequestInitChain) abci.ResponseInitChain { +func (app *App) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { // TODO: Use req.Validators + return } // Implements ABCI -func (app *App) Query(req abci.RequestQuery) abci.ResponseQuery { +func (app *App) Query(req abci.RequestQuery) (res abci.ResponseQuery) { // TODO: See app/query.go + return } // Implements ABCI -func (app *App) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock { +func (app *App) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { app.header = req.Header + app.storeDeliver = app.store.CacheMultiStore() + app.storeCheck = app.store.CacheMultiStore() + return } // Implements ABCI -func (app *App) CheckTx(txBytes []byte) abci.ResponseCheckTx { +func (app *App) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) { // Initialize arguments to Handler. var isCheckTx = true @@ -163,7 +177,7 @@ func (app *App) CheckTx(txBytes []byte) abci.ResponseCheckTx { } // Implements ABCI -func (app *App) DeliverTx(txBytes []byte) abci.ResponseDeliverTx { +func (app *App) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { // Initialize arguments to Handler. var isCheckTx = false @@ -193,7 +207,6 @@ func (app *App) DeliverTx(txBytes []byte) abci.ResponseDeliverTx { // Implements ABCI func (app *App) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { - // XXX Update to res.Updates. res.ValidatorUpdates = app.valUpdates app.valUpdates = nil return @@ -201,6 +214,7 @@ func (app *App) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { // Implements ABCI func (app *App) Commit() (res abci.ResponseCommit) { + app.storeDeliver.Write() commitID := app.store.Commit() app.logger.Debug("Commit synced", "commit", commitID, From e7b38b3fb91925017d58309841bb023b4c50c5f2 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 22 Dec 2017 00:23:37 -0800 Subject: [PATCH 4/6] ABCI w/ more non-nullable fields --- glide.lock | 2 +- types/context.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 956fbaa6927b..bb1cdd8cbb2a 100644 --- a/glide.lock +++ b/glide.lock @@ -112,7 +112,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: e4b9f1abe794a2117a59738a1294e09b46d0fa00 + version: 4274f8eca234325d2fbc9a434f9bc099bd2c40d4 subpackages: - client - example/dummy diff --git a/types/context.go b/types/context.go index 4a2296ecd16a..037535c28586 100644 --- a/types/context.go +++ b/types/context.go @@ -136,7 +136,7 @@ func (c Context) TxBytes() []byte { // Unexposed to prevent overriding. func (c Context) setBlockHeader(header abci.Header) Context { - var _ proto.Message = header // for cloning. + var _ proto.Message = &header // for cloning. return c.withValue(contextKeyBlockHeader, header) } From ab2cef884df3a120458217c6e6f91c78e93e1425 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 25 Dec 2017 00:57:07 -0800 Subject: [PATCH 5/6] Move Coins to types --- {x/coin => types}/coin.go | 13 +++++++++---- {x/coin => types}/coin_test.go | 2 +- x/coin/types.go | 6 ------ x/{coin => coinstore}/_attic/bench_test.go | 0 x/{coin => coinstore}/_attic/handler.go | 0 x/{coin => coinstore}/_attic/handler_test.go | 0 x/{coin => coinstore}/_attic/helper.go | 0 x/{coin => coinstore}/_attic/ibc_test.go | 0 x/{coin => coinstore}/_attic/store.go | 0 x/{coin => coinstore}/commands/query.go | 0 x/{coin => coinstore}/commands/tx.go | 0 x/{coin => coinstore}/decorator.go | 0 x/{coin => coinstore}/errors.go | 0 x/{coin => coinstore}/genesis.go | 3 ++- x/{coin => coinstore}/rest/handlers.go | 0 x/{coin => coinstore}/tx.go | 19 ++++++++++--------- x/{coin => coinstore}/tx_test.go | 0 x/{coin => coinstore}/utils.go | 0 18 files changed, 22 insertions(+), 21 deletions(-) rename {x/coin => types}/coin.go (97%) rename {x/coin => types}/coin_test.go (99%) delete mode 100644 x/coin/types.go rename x/{coin => coinstore}/_attic/bench_test.go (100%) rename x/{coin => coinstore}/_attic/handler.go (100%) rename x/{coin => coinstore}/_attic/handler_test.go (100%) rename x/{coin => coinstore}/_attic/helper.go (100%) rename x/{coin => coinstore}/_attic/ibc_test.go (100%) rename x/{coin => coinstore}/_attic/store.go (100%) rename x/{coin => coinstore}/commands/query.go (100%) rename x/{coin => coinstore}/commands/tx.go (100%) rename x/{coin => coinstore}/decorator.go (100%) rename x/{coin => coinstore}/errors.go (100%) rename x/{coin => coinstore}/genesis.go (93%) rename x/{coin => coinstore}/rest/handlers.go (100%) rename x/{coin => coinstore}/tx.go (89%) rename x/{coin => coinstore}/tx_test.go (100%) rename x/{coin => coinstore}/utils.go (100%) diff --git a/x/coin/coin.go b/types/coin.go similarity index 97% rename from x/coin/coin.go rename to types/coin.go index 7c3af50d7fda..30e96b295088 100644 --- a/x/coin/coin.go +++ b/types/coin.go @@ -1,12 +1,9 @@ -package coin +package types import ( "fmt" "sort" - "strconv" "strings" - - "github.com/pkg/errors" ) // Coin hold some amount of one currency @@ -200,3 +197,11 @@ var _ sort.Interface = Coins{} // Sort is a helper function to sort the set of coins inplace func (coins Coins) Sort() { sort.Sort(coins) } + +//---------------------------------------- +// Misc + +type Coinser interface { + GetCoins() Coins + SetCoins(Coins) +} diff --git a/x/coin/coin_test.go b/types/coin_test.go similarity index 99% rename from x/coin/coin_test.go rename to types/coin_test.go index 0cb2b4f21b4b..bf651c50dee6 100644 --- a/x/coin/coin_test.go +++ b/types/coin_test.go @@ -1,4 +1,4 @@ -package coin +package types import ( "testing" diff --git a/x/coin/types.go b/x/coin/types.go deleted file mode 100644 index 5da29b465d4f..000000000000 --- a/x/coin/types.go +++ /dev/null @@ -1,6 +0,0 @@ -package coin - -type Coinser interface { - GetCoins() Coins - SetCoins(Coins) -} diff --git a/x/coin/_attic/bench_test.go b/x/coinstore/_attic/bench_test.go similarity index 100% rename from x/coin/_attic/bench_test.go rename to x/coinstore/_attic/bench_test.go diff --git a/x/coin/_attic/handler.go b/x/coinstore/_attic/handler.go similarity index 100% rename from x/coin/_attic/handler.go rename to x/coinstore/_attic/handler.go diff --git a/x/coin/_attic/handler_test.go b/x/coinstore/_attic/handler_test.go similarity index 100% rename from x/coin/_attic/handler_test.go rename to x/coinstore/_attic/handler_test.go diff --git a/x/coin/_attic/helper.go b/x/coinstore/_attic/helper.go similarity index 100% rename from x/coin/_attic/helper.go rename to x/coinstore/_attic/helper.go diff --git a/x/coin/_attic/ibc_test.go b/x/coinstore/_attic/ibc_test.go similarity index 100% rename from x/coin/_attic/ibc_test.go rename to x/coinstore/_attic/ibc_test.go diff --git a/x/coin/_attic/store.go b/x/coinstore/_attic/store.go similarity index 100% rename from x/coin/_attic/store.go rename to x/coinstore/_attic/store.go diff --git a/x/coin/commands/query.go b/x/coinstore/commands/query.go similarity index 100% rename from x/coin/commands/query.go rename to x/coinstore/commands/query.go diff --git a/x/coin/commands/tx.go b/x/coinstore/commands/tx.go similarity index 100% rename from x/coin/commands/tx.go rename to x/coinstore/commands/tx.go diff --git a/x/coin/decorator.go b/x/coinstore/decorator.go similarity index 100% rename from x/coin/decorator.go rename to x/coinstore/decorator.go diff --git a/x/coin/errors.go b/x/coinstore/errors.go similarity index 100% rename from x/coin/errors.go rename to x/coinstore/errors.go diff --git a/x/coin/genesis.go b/x/coinstore/genesis.go similarity index 93% rename from x/coin/genesis.go rename to x/coinstore/genesis.go index b174c8c11a41..cc0163fcf0cf 100644 --- a/x/coin/genesis.go +++ b/x/coinstore/genesis.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" + "github.com/cosmos/cosmos-sdk/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire/data" ) @@ -16,7 +17,7 @@ type GenesisAccount struct { Address data.Bytes `json:"address"` // this from types.Account (don't know how to embed this properly) PubKey crypto.PubKey `json:"pub_key"` // May be nil, if not known. - Balance Coins `json:"coins"` + Balance types.Coins `json:"coins"` } // ToAccount - GenesisAccount struct to a basecoin Account diff --git a/x/coin/rest/handlers.go b/x/coinstore/rest/handlers.go similarity index 100% rename from x/coin/rest/handlers.go rename to x/coinstore/rest/handlers.go diff --git a/x/coin/tx.go b/x/coinstore/tx.go similarity index 89% rename from x/coin/tx.go rename to x/coinstore/tx.go index fcb0c84d54bc..ab128937412e 100644 --- a/x/coin/tx.go +++ b/x/coinstore/tx.go @@ -4,6 +4,7 @@ package coin import ( "fmt" + "github.com/cosmos/cosmos-sdk/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -17,7 +18,7 @@ type CoinMsg interface { // Input is a source of coins in a transaction. type Input struct { Address cmn.Bytes - Coins Coins + Coins types.Coins } func (in Input) ValidateBasic() error { @@ -38,7 +39,7 @@ func (txIn TxInput) String() string { } // NewTxInput - create a transaction input, used with SendTx -func NewTxInput(addr Actor, coins Coins) TxInput { +func NewTxInput(addr Actor, coins types.Coins) TxInput { input := TxInput{ Address: addr, Coins: coins, @@ -50,8 +51,8 @@ func NewTxInput(addr Actor, coins Coins) TxInput { // TxOutput - expected coin movement output, used with SendTx type TxOutput struct { - Address Actor `json:"address"` - Coins Coins `json:"coins"` + Address Actor `json:"address"` + Coins types.Coins `json:"coins"` } // ValidateBasic - validate transaction output @@ -77,7 +78,7 @@ func (txOut TxOutput) String() string { } // NewTxOutput - create a transaction output, used with SendTx -func NewTxOutput(addr Actor, coins Coins) TxOutput { +func NewTxOutput(addr Actor, coins types.Coins) TxOutput { output := TxOutput{ Address: addr, Coins: coins, @@ -103,7 +104,7 @@ func NewSendTx(in []TxInput, out []TxOutput) SendTx { // types.Tx { // NewSendOneTx is a helper for the standard (?) case where there is exactly // one sender and one recipient -func NewSendOneTx(sender, recipient Actor, amount Coins) SendTx { +func NewSendOneTx(sender, recipient Actor, amount types.Coins) SendTx { in := []TxInput{{Address: sender, Coins: amount}} out := []TxOutput{{Address: recipient, Coins: amount}} return SendTx{Inputs: in, Outputs: out} @@ -120,7 +121,7 @@ func (tx SendTx) ValidateBasic() error { return ErrNoOutputs() } // make sure all inputs and outputs are individually valid - var totalIn, totalOut Coins + var totalIn, totalOut types.Coins for _, in := range tx.Inputs { if err := in.ValidateBasic(); err != nil { return err @@ -153,11 +154,11 @@ type CreditTx struct { // Credit is the amount to change the credit... // This may be negative to remove some over-issued credit, // but can never bring the credit or the balance to negative - Credit Coins `json:"credit"` + Credit types.Coins `json:"credit"` } // NewCreditTx - modify the credit granted to a given account -func NewCreditTx(debitor Actor, credit Coins) CreditTx { +func NewCreditTx(debitor Actor, credit types.Coins) CreditTx { return CreditTx{Debitor: debitor, Credit: credit} } diff --git a/x/coin/tx_test.go b/x/coinstore/tx_test.go similarity index 100% rename from x/coin/tx_test.go rename to x/coinstore/tx_test.go diff --git a/x/coin/utils.go b/x/coinstore/utils.go similarity index 100% rename from x/coin/utils.go rename to x/coinstore/utils.go From 657820372cdd46d883532167727de2ca645dba15 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 26 Dec 2017 17:04:48 -0800 Subject: [PATCH 6/6] App compiles. Ready to build on it --- app/app.go | 101 +++++++++++++++++++++++----------------- app/app_test.go | 73 ++++++++++++++++++----------- glide.lock | 4 +- store/iavlstore.go | 3 +- store/rootmultistore.go | 45 ++++++++++++------ types/result.go | 6 +-- types/store.go | 6 ++- 7 files changed, 146 insertions(+), 92 deletions(-) diff --git a/app/app.go b/app/app.go index 6f107f2b7cd1..12fea597f351 100644 --- a/app/app.go +++ b/app/app.go @@ -8,12 +8,13 @@ import ( "github.com/golang/protobuf/proto" "github.com/pkg/errors" abci "github.com/tendermint/abci/types" + cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" "github.com/cosmos/cosmos-sdk/types" ) -var mainHeaderKey = "header" +var mainHeaderKey = []byte("header") // App - The ABCI application type App struct { @@ -23,16 +24,16 @@ type App struct { name string // Main (uncached) state - store types.CommitMultiStore + ms types.CommitMultiStore - // CheckTx state, a cache-wrap of store. - storeCheck types.CacheMultiStore + // CheckTx state, a cache-wrap of `.ms`. + msCheck types.CacheMultiStore - // DeliverTx state, a cache-wrap of store. - storeDeliver types.CacheMultiStore + // DeliverTx state, a cache-wrap of `.ms`. + msDeliver types.CacheMultiStore // Current block header - header *abci.Header + header abci.Header // Handler for CheckTx and DeliverTx. handler types.Handler @@ -54,8 +55,8 @@ func (app *App) Name() string { return app.name } -func (app *App) SetCommitStore(store types.CommitMultiStore) { - app.store = store +func (app *App) SetCommitMultiStore(ms types.CommitMultiStore) { + app.ms = ms } func (app *App) SetHandler(handler types.Handler) { @@ -63,26 +64,33 @@ func (app *App) SetHandler(handler types.Handler) { } func (app *App) LoadLatestVersion() error { - store := app.store - store.LoadLatestVersion() + app.ms.LoadLatestVersion() return app.initFromStore() } func (app *App) LoadVersion(version int64) error { - store := app.store - store.LoadVersion(version) + app.ms.LoadVersion(version) return app.initFromStore() } -// Initializes the remaining logic from app.store. +// The last CommitID of the multistore. +func (app *App) LastCommitID() types.CommitID { + return app.ms.LastCommitID() +} + +// The last commited block height. +func (app *App) LastBlockHeight() int64 { + return app.ms.LastCommitID().Version +} + +// Initializes the remaining logic from app.ms. func (app *App) initFromStore() error { - store := app.store - lastCommitID := store.LastCommitID() - main := store.GetKVStore("main") - header := (*abci.Header)(nil) + lastCommitID := app.ms.LastCommitID() + main := app.ms.GetKVStore("main") + header := abci.Header{} // Main store should exist. - if store.GetKVStore("main") == nil { + if app.ms.GetKVStore("main") == nil { return errors.New("App expects MultiStore with 'main' KVStore") } @@ -93,7 +101,7 @@ func (app *App) initFromStore() error { errStr := fmt.Sprintf("Version > 0 but missing key %s", mainHeaderKey) return errors.New(errStr) } - err := proto.Unmarshal(headerBytes, header) + err := proto.Unmarshal(headerBytes, &header) if err != nil { return errors.Wrap(err, "Failed to parse Header") } @@ -106,8 +114,8 @@ func (app *App) initFromStore() error { // Set App state. app.header = header - app.storeCheck = nil - app.storeDeliver = nil + app.msCheck = nil + app.msDeliver = nil app.valUpdates = nil return nil @@ -118,7 +126,7 @@ func (app *App) initFromStore() error { // Implements ABCI func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { - lastCommitID := app.store.LastCommitID() + lastCommitID := app.ms.LastCommitID() return abci.ResponseInfo{ Data: app.name, @@ -148,8 +156,8 @@ func (app *App) Query(req abci.RequestQuery) (res abci.ResponseQuery) { // Implements ABCI func (app *App) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { app.header = req.Header - app.storeDeliver = app.store.CacheMultiStore() - app.storeCheck = app.store.CacheMultiStore() + app.msDeliver = app.ms.CacheMultiStore() + app.msCheck = app.ms.CacheMultiStore() return } @@ -159,20 +167,22 @@ func (app *App) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) { // Initialize arguments to Handler. var isCheckTx = true var ctx = types.NewContext(app.header, isCheckTx, txBytes) - var store = app.store - var tx Tx = nil // nil until a decorator parses one. + var tx types.Tx = nil // nil until a decorator parses one. // Run the handler. - var result = app.handler(ctx, app.store, tx) + var result = app.handler(ctx, app.ms, tx) // Tell the blockchain engine (i.e. Tendermint). - return abci.ResponseDeliverTx{ + return abci.ResponseCheckTx{ Code: result.Code, Data: result.Data, Log: result.Log, - Gas: result.Gas, - FeeDenom: result.FeeDenom, - FeeAmount: result.FeeAmount, + GasWanted: result.GasWanted, + Fee: cmn.KI64Pair{ + []byte(result.FeeDenom), + result.FeeAmount, + }, + Tags: result.Tags, } } @@ -182,15 +192,14 @@ func (app *App) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { // Initialize arguments to Handler. var isCheckTx = false var ctx = types.NewContext(app.header, isCheckTx, txBytes) - var store = app.store - var tx Tx = nil // nil until a decorator parses one. + var tx types.Tx = nil // nil until a decorator parses one. // Run the handler. - var result = app.handler(ctx, app.store, tx) + var result = app.handler(ctx, app.ms, tx) // After-handler hooks. - if result.Code == abci.CodeType_OK { - app.valUpdates = append(app.valUpdates, result.ValUpdate) + if result.Code == abci.CodeTypeOK { + app.valUpdates = append(app.valUpdates, result.ValidatorUpdates...) } else { // Even though the Code is not OK, there will be some side effects, // like those caused by fee deductions or sequence incrementations. @@ -198,10 +207,12 @@ func (app *App) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { // Tell the blockchain engine (i.e. Tendermint). return abci.ResponseDeliverTx{ - Code: result.Code, - Data: result.Data, - Log: result.Log, - Tags: result.Tags, + Code: result.Code, + Data: result.Data, + Log: result.Log, + GasWanted: result.GasWanted, + GasUsed: result.GasUsed, + Tags: result.Tags, } } @@ -214,12 +225,14 @@ func (app *App) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { // Implements ABCI func (app *App) Commit() (res abci.ResponseCommit) { - app.storeDeliver.Write() - commitID := app.store.Commit() + app.msDeliver.Write() + commitID := app.ms.Commit() app.logger.Debug("Commit synced", "commit", commitID, ) - return abci.NewResultOK(hash, "") + return abci.ResponseCommit{ + Data: commitID.Hash, + } } //---------------------------------------- diff --git a/app/app_test.go b/app/app_test.go index 3ac550357855..befb2514583b 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -7,12 +7,13 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - sdk "github.com/cosmos/cosmos-sdk" + "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/types" abci "github.com/tendermint/abci/types" "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" ) func TestBasic(t *testing.T) { @@ -24,31 +25,33 @@ func TestBasic(t *testing.T) { } // Create app. - app := sdk.NewApp(t.Name()) - app.SetStore(mockMultiStore()) - app.SetHandler(func(ctx Context, store MultiStore, tx Tx) Result { + app := NewApp(t.Name()) + app.SetCommitMultiStore(newCommitMultiStore()) + app.SetHandler(func(ctx types.Context, store types.MultiStore, tx types.Tx) types.Result { // This could be a decorator. - fromJSON(ctx.TxBytes(), &tx) + var ttx testTx + fromJSON(ctx.TxBytes(), &ttx) - fmt.Println(">>", tx) + // XXX + return types.Result{} }) // Load latest state, which should be empty. err := app.LoadLatestVersion() assert.Nil(t, err) - assert.Equal(t, app.NextVersion(), 1) + assert.Equal(t, app.LastBlockHeight(), int64(0)) // Create the validators var numVals = 3 - var valSet = make([]*abci.Validator, numVals) + var valSet = make([]abci.Validator, numVals) for i := 0; i < numVals; i++ { valSet[i] = makeVal(secret(i)) } // Initialize the chain app.InitChain(abci.RequestInitChain{ - Validators: valset, + Validators: valSet, }) // Simulate the start of a block. @@ -62,24 +65,26 @@ func TestBasic(t *testing.T) { } txBytes := toJSON(tx) res := app.DeliverTx(txBytes) - require.True(res.IsOK(), "%#v", res) + assert.True(t, res.IsOK(), "%#v", res) } // Simulate the end of a block. // Get the summary of validator updates. - res := app.EndBlock(app.height) + res := app.EndBlock(abci.RequestEndBlock{}) valUpdates := res.ValidatorUpdates // Assert that validator updates are correct. for _, val := range valSet { + // Sanity + assert.NotEqual(t, len(val.PubKey), 0) // Find matching update and splice it out. for j := 0; j < len(valUpdates); { - assert.NotEqual(len(valUpdates.PubKey), 0) + valUpdate := valUpdates[j] // Matched. if bytes.Equal(valUpdate.PubKey, val.PubKey) { - assert.Equal(valUpdate.NewPower, val.Power+1) + assert.Equal(t, valUpdate.Power, val.Power+1) if j < len(valUpdates)-1 { // Splice it out. valUpdates = append(valUpdates[:j], valUpdates[j+1:]...) @@ -100,9 +105,9 @@ func randPower() int64 { return cmn.RandInt64() } -func makeVal(secret string) *abci.Validator { - return &abci.Validator{ - PubKey: makePubKey(string).Bytes(), +func makeVal(secret string) abci.Validator { + return abci.Validator{ + PubKey: makePubKey(secret).Bytes(), Power: randPower(), } } @@ -112,29 +117,43 @@ func makePubKey(secret string) crypto.PubKey { } func makePrivKey(secret string) crypto.PrivKey { - return crypto.GenPrivKeyEd25519FromSecret([]byte(id)) + privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret)) + return privKey.Wrap() } -func secret(index int) []byte { - return []byte(fmt.Sprintf("secret%d", index)) +func secret(index int) string { + return fmt.Sprintf("secret%d", index) } -func copyVal(val *abci.Validator) *abci.Validator { - val2 := *val - return &val2 +func copyVal(val abci.Validator) abci.Validator { + // val2 := *val + // return &val2 + return val } func toJSON(o interface{}) []byte { - bytes, err := json.Marshal(o) + bz, err := json.Marshal(o) if err != nil { panic(err) } - return bytes + // fmt.Println(">> toJSON:", string(bz)) + return bz } -func fromJSON(bytes []byte, ptr interface{}) { - err := json.Unmarshal(bytes, ptr) +func fromJSON(bz []byte, ptr interface{}) { + // fmt.Println(">> fromJSON:", string(bz)) + err := json.Unmarshal(bz, ptr) if err != nil { panic(err) } } + +// Creates a sample CommitMultiStore +func newCommitMultiStore() types.CommitMultiStore { + dbMain := dbm.NewMemDB() + dbXtra := dbm.NewMemDB() + ms := store.NewMultiStore(dbMain) // Also store rootMultiStore metadata here (it shouldn't clash) + ms.SetSubstoreLoader("main", store.NewIAVLStoreLoader(dbMain, 0, 0)) + ms.SetSubstoreLoader("xtra", store.NewIAVLStoreLoader(dbXtra, 0, 0)) + return ms +} diff --git a/glide.lock b/glide.lock index bb1cdd8cbb2a..b2a9eef33282 100644 --- a/glide.lock +++ b/glide.lock @@ -112,7 +112,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 4274f8eca234325d2fbc9a434f9bc099bd2c40d4 + version: 8f87efd7f86c2bae9df69aff69d715593d5d79f7 subpackages: - client - example/dummy @@ -174,7 +174,7 @@ imports: - types - version - name: github.com/tendermint/tmlibs - version: b70ae4919befb6ae3e5cb40ae8174e122e771d08 + version: b25df389db3c98f4b964bd39511c199f02d07715 subpackages: - autofile - cli diff --git a/store/iavlstore.go b/store/iavlstore.go index 0c333ab9207d..c349358c7b07 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -48,6 +48,7 @@ type iavlStore struct { tree *iavl.VersionedTree // How many old versions we hold onto. + // A value of 0 means keep all history. numHistory int64 } @@ -71,7 +72,7 @@ func (st *iavlStore) Commit() CommitID { } // Release an old version of history - if st.numHistory < st.tree.Version64() { + if st.numHistory > 0 && (st.numHistory < st.tree.Version64()) { toRelease := version - st.numHistory st.tree.DeleteVersion(toRelease) } diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 21b399946b2b..7508d3c0596e 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -26,6 +26,8 @@ type rootMultiStore struct { substores map[string]CommitStore } +var _ CommitMultiStore = (*rootMultiStore)(nil) + func NewMultiStore(db dbm.DB) *rootMultiStore { return &rootMultiStore{ db: db, @@ -35,6 +37,7 @@ func NewMultiStore(db dbm.DB) *rootMultiStore { } } +// Implements CommitMultiStore. func (rs *rootMultiStore) SetSubstoreLoader(name string, loader CommitStoreLoader) { if _, ok := rs.storeLoaders[name]; ok { panic(fmt.Sprintf("rootMultiStore duplicate substore name " + name)) @@ -42,17 +45,18 @@ func (rs *rootMultiStore) SetSubstoreLoader(name string, loader CommitStoreLoade rs.storeLoaders[name] = loader } -// Call once after all calls to SetSubstoreLoader are complete. +// Implements CommitMultiStore. +func (rs *rootMultiStore) GetSubstore(name string) CommitStore { + return rs.substores[name] +} + +// Implements CommitMultiStore. func (rs *rootMultiStore) LoadLatestVersion() error { ver := getLatestVersion(rs.db) return rs.LoadVersion(ver) } -// NOTE: Returns 0 unless LoadVersion() or LoadLatestVersion() is called. -func (rs *rootMultiStore) NextVersion() int64 { - return rs.nextVersion -} - +// Implements CommitMultiStore. func (rs *rootMultiStore) LoadVersion(ver int64) error { // Special logic for version 0 @@ -106,10 +110,13 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error { return nil } -// Implements CommitStore +//---------------------------------------- +// +CommitStore + +// Implements CommitStore. func (rs *rootMultiStore) Commit() CommitID { - // Commit substores + // Commit substores. version := rs.nextVersion state := commitSubstores(version, rs.substores) @@ -129,27 +136,36 @@ func (rs *rootMultiStore) Commit() CommitID { return commitID } -// Implements CommitStore +// Implements CommitStore. func (rs *rootMultiStore) CacheWrap() CacheWrap { return rs.CacheMultiStore().(CacheWrap) } -// Get the last committed CommitID +//---------------------------------------- +// +MultiStore + +// Implements MultiStore. func (rs *rootMultiStore) LastCommitID() CommitID { return rs.lastCommitID } -// Implements MultiStore +// 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) GetCommitStore(name string) CommitStore { +// Implements MultiStore. +func (rs *rootMultiStore) GetStore(name string) interface{} { return rs.substores[name] } -// Implements MultiStore +// Implements MultiStore. func (rs *rootMultiStore) GetKVStore(name string) KVStore { return rs.substores[name].(KVStore) } @@ -208,6 +224,7 @@ func (sc substoreCore) Hash() []byte { } //---------------------------------------- +// Misc. func getLatestVersion(db dbm.DB) int64 { var latest int64 diff --git a/types/result.go b/types/result.go index d56e5ceb119b..3ce194c25280 100644 --- a/types/result.go +++ b/types/result.go @@ -17,8 +17,8 @@ type Result struct { // Log is just debug information. NOTE: nondeterministic. Log string - // GasAllocated is the maximum units of work we allow this tx to perform. - GasAllocated int64 + // GasWanted is the maximum units of work we allow this tx to perform. + GasWanted int64 // GasUsed is the amount of gas actually consumed. NOTE: not used. GasUsed int64 @@ -28,7 +28,7 @@ type Result struct { FeeDenom string // Changes to the validator set. - ValSetDiff []abci.Validator + ValidatorUpdates []abci.Validator // Tags are used for transaction indexing and pubsub. Tags []cmn.KVPair diff --git a/types/store.go b/types/store.go index 73a0e848a709..adeba6f44514 100644 --- a/types/store.go +++ b/types/store.go @@ -26,7 +26,7 @@ type MultiStore interface { // call CacheMultiStore.Write(). CacheMultiStore() CacheMultiStore - // Convenience + // Convenience for fetching substores. GetStore(name string) interface{} GetKVStore(name string) KVStore } @@ -56,7 +56,11 @@ type CommitMultiStore interface { // Add a substore loader. SetSubstoreLoader(name string, loader CommitStoreLoader) + // Gets the substore, which is a CommitSubstore. + GetSubstore(name string) CommitStore + // Load the latest persisted version. + // Called once after all calls to SetSubstoreLoader are complete. LoadLatestVersion() error // Load a specific persisted version. When you load an old version, or