2016-02-07 22:54:49 -08:00
|
|
|
package app
|
2016-02-05 23:16:33 -08:00
|
|
|
|
|
|
|
import (
|
2017-07-04 03:22:06 -07:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2017-01-14 20:42:47 -08:00
|
|
|
abci "github.com/tendermint/abci/types"
|
2017-06-21 09:15:11 -07:00
|
|
|
cmn "github.com/tendermint/tmlibs/common"
|
2017-05-01 07:03:54 -07:00
|
|
|
"github.com/tendermint/tmlibs/log"
|
2017-04-01 14:31:44 -07:00
|
|
|
|
2017-07-25 19:19:31 -07:00
|
|
|
"github.com/tendermint/basecoin"
|
2017-07-03 08:32:01 -07:00
|
|
|
"github.com/tendermint/basecoin/errors"
|
|
|
|
"github.com/tendermint/basecoin/stack"
|
2017-04-01 14:31:44 -07:00
|
|
|
sm "github.com/tendermint/basecoin/state"
|
|
|
|
"github.com/tendermint/basecoin/version"
|
2016-02-05 23:16:33 -08:00
|
|
|
)
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
//nolint
|
2016-03-27 12:47:50 -07:00
|
|
|
const (
|
2017-07-04 03:22:06 -07:00
|
|
|
ModuleNameBase = "base"
|
|
|
|
ChainKey = "chain_id"
|
2016-03-27 12:47:50 -07:00
|
|
|
)
|
2016-02-05 23:16:33 -08:00
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// Basecoin - The ABCI application
|
2016-02-16 12:29:54 -08:00
|
|
|
type Basecoin struct {
|
2017-07-30 14:34:33 -07:00
|
|
|
info *sm.ChainState
|
2017-07-26 13:35:02 -07:00
|
|
|
state *Store
|
2017-07-25 19:19:31 -07:00
|
|
|
|
|
|
|
handler basecoin.Handler
|
2017-07-30 14:34:33 -07:00
|
|
|
|
|
|
|
pending []*abci.Validator
|
2017-07-25 19:19:31 -07:00
|
|
|
height uint64
|
|
|
|
logger log.Logger
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-06 22:27:29 -07:00
|
|
|
var _ abci.Application = &Basecoin{}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// NewBasecoin - create a new instance of the basecoin application
|
2017-07-26 13:35:02 -07:00
|
|
|
func NewBasecoin(handler basecoin.Handler, store *Store, logger log.Logger) *Basecoin {
|
2016-02-16 12:29:54 -08:00
|
|
|
return &Basecoin{
|
2017-07-25 19:19:31 -07:00
|
|
|
handler: handler,
|
|
|
|
info: sm.NewChainState(),
|
|
|
|
state: store,
|
|
|
|
logger: logger,
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-25 19:19:31 -07:00
|
|
|
// GetChainID returns the currently stored chain
|
|
|
|
func (app *Basecoin) GetChainID() string {
|
|
|
|
return app.info.GetChainID(app.state.Committed())
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetState is back... please kill me
|
2017-07-26 16:55:05 -07:00
|
|
|
func (app *Basecoin) GetState() sm.SimpleDB {
|
2017-07-25 19:19:31 -07:00
|
|
|
return app.state.Append()
|
2017-02-03 13:06:12 -08:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// Info - ABCI
|
2017-01-14 20:42:47 -08:00
|
|
|
func (app *Basecoin) Info() abci.ResponseInfo {
|
2017-07-25 19:19:31 -07:00
|
|
|
resp := app.state.Info()
|
2017-07-10 03:19:42 -07:00
|
|
|
app.height = resp.LastBlockHeight
|
2017-06-21 09:15:11 -07:00
|
|
|
return abci.ResponseInfo{
|
2017-07-04 20:28:27 -07:00
|
|
|
Data: fmt.Sprintf("Basecoin v%v", version.Version),
|
2017-06-21 09:15:11 -07:00
|
|
|
LastBlockHeight: resp.LastBlockHeight,
|
|
|
|
LastBlockAppHash: resp.LastBlockAppHash,
|
|
|
|
}
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-30 09:57:48 -07:00
|
|
|
// InitState - used to setup state (was SetOption)
|
|
|
|
// to be used by InitChain later
|
|
|
|
func (app *Basecoin) InitState(key string, value string) string {
|
2017-07-04 20:28:27 -07:00
|
|
|
|
|
|
|
module, key := splitKey(key)
|
2017-07-25 19:19:31 -07:00
|
|
|
state := app.state.Append()
|
2017-07-04 20:28:27 -07:00
|
|
|
|
2017-07-04 03:22:06 -07:00
|
|
|
if module == ModuleNameBase {
|
2017-07-04 20:28:27 -07:00
|
|
|
if key == ChainKey {
|
2017-07-25 19:19:31 -07:00
|
|
|
app.info.SetChainID(state, value)
|
2017-07-04 20:28:27 -07:00
|
|
|
return "Success"
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("Error: unknown base option: %s", key)
|
2017-07-03 09:58:28 -07:00
|
|
|
}
|
|
|
|
|
2017-07-30 09:57:48 -07:00
|
|
|
log, err := app.handler.InitState(app.logger, state, module, key, value)
|
2017-07-03 09:58:28 -07:00
|
|
|
if err == nil {
|
|
|
|
return log
|
|
|
|
}
|
|
|
|
return "Error: " + err.Error()
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-30 09:57:48 -07:00
|
|
|
// SetOption - ABCI
|
|
|
|
func (app *Basecoin) SetOption(key string, value string) string {
|
|
|
|
return "Not Implemented"
|
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// DeliverTx - ABCI
|
2017-07-03 08:32:01 -07:00
|
|
|
func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result {
|
|
|
|
tx, err := basecoin.LoadTx(txBytes)
|
2016-02-05 23:16:33 -08:00
|
|
|
if err != nil {
|
2017-07-03 08:32:01 -07:00
|
|
|
return errors.Result(err)
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
2017-01-12 12:25:04 -08:00
|
|
|
|
2017-07-03 12:34:08 -07:00
|
|
|
ctx := stack.NewContext(
|
2017-07-25 19:19:31 -07:00
|
|
|
app.GetChainID(),
|
2017-07-10 03:19:42 -07:00
|
|
|
app.height,
|
2017-07-03 12:34:08 -07:00
|
|
|
app.logger.With("call", "delivertx"),
|
|
|
|
)
|
2017-07-25 19:19:31 -07:00
|
|
|
res, err := app.handler.DeliverTx(ctx, app.state.Append(), tx)
|
2017-07-03 08:32:01 -07:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return errors.Result(err)
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
2017-07-30 14:34:33 -07:00
|
|
|
if len(res.Diff) > 0 {
|
|
|
|
app.pending = append(app.pending, res.Diff...)
|
|
|
|
}
|
2017-07-03 08:32:01 -07:00
|
|
|
return res.ToABCI()
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// CheckTx - ABCI
|
2017-07-03 08:32:01 -07:00
|
|
|
func (app *Basecoin) CheckTx(txBytes []byte) abci.Result {
|
|
|
|
tx, err := basecoin.LoadTx(txBytes)
|
2016-02-05 23:16:33 -08:00
|
|
|
if err != nil {
|
2017-07-03 08:32:01 -07:00
|
|
|
return errors.Result(err)
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
2017-01-12 12:25:04 -08:00
|
|
|
|
2017-07-03 12:34:08 -07:00
|
|
|
ctx := stack.NewContext(
|
2017-07-25 19:19:31 -07:00
|
|
|
app.GetChainID(),
|
2017-07-10 03:19:42 -07:00
|
|
|
app.height,
|
2017-07-03 12:34:08 -07:00
|
|
|
app.logger.With("call", "checktx"),
|
|
|
|
)
|
2017-07-25 19:19:31 -07:00
|
|
|
res, err := app.handler.CheckTx(ctx, app.state.Check(), tx)
|
2017-07-03 08:32:01 -07:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return errors.Result(err)
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
2017-07-03 08:32:01 -07:00
|
|
|
return res.ToABCI()
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// Query - ABCI
|
2017-01-28 09:29:32 -08:00
|
|
|
func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) {
|
|
|
|
if len(reqQuery.Data) == 0 {
|
|
|
|
resQuery.Log = "Query cannot be zero length"
|
|
|
|
resQuery.Code = abci.CodeType_EncodingError
|
|
|
|
return
|
2016-03-27 21:51:04 -07:00
|
|
|
}
|
2017-01-12 12:25:04 -08:00
|
|
|
|
2017-07-25 19:19:31 -07:00
|
|
|
return app.state.Query(reqQuery)
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// Commit - ABCI
|
2017-01-14 20:42:47 -08:00
|
|
|
func (app *Basecoin) Commit() (res abci.Result) {
|
2017-01-12 17:49:51 -08:00
|
|
|
// Commit state
|
|
|
|
res = app.state.Commit()
|
2016-03-23 02:47:05 -07:00
|
|
|
if res.IsErr() {
|
2017-06-21 09:15:11 -07:00
|
|
|
cmn.PanicSanity("Error getting hash: " + res.Error())
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
2016-03-23 02:47:05 -07:00
|
|
|
return res
|
2016-02-05 23:16:33 -08:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// InitChain - ABCI
|
2017-01-14 20:42:47 -08:00
|
|
|
func (app *Basecoin) InitChain(validators []*abci.Validator) {
|
2017-07-03 08:32:01 -07:00
|
|
|
// for _, plugin := range app.plugins.GetList() {
|
|
|
|
// plugin.InitChain(app.state, validators)
|
|
|
|
// }
|
2016-03-15 15:01:53 -07:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// BeginBlock - ABCI
|
2017-02-04 14:47:36 -08:00
|
|
|
func (app *Basecoin) BeginBlock(hash []byte, header *abci.Header) {
|
2017-07-10 03:19:42 -07:00
|
|
|
app.height++
|
2017-07-03 08:32:01 -07:00
|
|
|
// for _, plugin := range app.plugins.GetList() {
|
|
|
|
// plugin.BeginBlock(app.state, hash, header)
|
|
|
|
// }
|
2016-03-29 14:25:17 -07:00
|
|
|
}
|
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
// EndBlock - ABCI
|
2017-07-30 14:34:33 -07:00
|
|
|
// Returns a list of all validator changes made in this block
|
2017-02-04 14:47:36 -08:00
|
|
|
func (app *Basecoin) EndBlock(height uint64) (res abci.ResponseEndBlock) {
|
2017-07-30 14:34:33 -07:00
|
|
|
// TODO: cleanup in case a validator exists multiple times in the list
|
|
|
|
res.Diffs = app.pending
|
|
|
|
app.pending = nil
|
2016-04-18 08:09:19 -07:00
|
|
|
return
|
2016-03-15 15:01:53 -07:00
|
|
|
}
|
2017-07-04 03:22:06 -07:00
|
|
|
|
2017-07-04 20:28:27 -07:00
|
|
|
//TODO move split key to tmlibs?
|
|
|
|
|
2017-07-04 03:22:06 -07:00
|
|
|
// Splits the string at the first '/'.
|
|
|
|
// if there are none, assign default module ("base").
|
|
|
|
func splitKey(key string) (string, string) {
|
|
|
|
if strings.Contains(key, "/") {
|
|
|
|
keyParts := strings.SplitN(key, "/", 2)
|
|
|
|
return keyParts[0], keyParts[1]
|
|
|
|
}
|
|
|
|
return ModuleNameBase, key
|
|
|
|
}
|