Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Baseapp #1400

Merged
merged 1 commit into from
Jul 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 73 additions & 109 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,36 +204,6 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
return errors.New("baseapp expects MultiStore with 'main' KVStore")
}

// XXX: Do we really need the header? What does it have that we want
// here that's not already in the CommitID ? If an app wants to have it,
// they can do so in their BeginBlocker. If we force it in baseapp,
// then either we force the AppHash to change with every block (since the header
// will be in the merkle store) or we can't write the state and the header to the
// db atomically without doing some surgery on the store interfaces ...

// if we've committed before, we expect <dbHeaderKey> to exist in the db
/*
var lastCommitID = app.cms.LastCommitID()
var header abci.Header

if !lastCommitID.IsZero() {
headerBytes := app.db.Get(dbHeaderKey)
if len(headerBytes) == 0 {
errStr := fmt.Sprintf("Version > 0 but missing key %s", dbHeaderKey)
return errors.New(errStr)
}
err := proto.Unmarshal(headerBytes, &header)
if err != nil {
return errors.Wrap(err, "failed to parse Header")
}
lastVersion := lastCommitID.Version
if header.Height != lastVersion {
errStr := fmt.Sprintf("expected db://%s.Height %v but got %v", dbHeaderKey, lastVersion, header.Height)
return errors.New(errStr)
}
}
*/

return nil
}

Expand Down Expand Up @@ -490,21 +460,7 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
}
}

// nolint - Mostly for testing
func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeCheck, nil, tx)
}

// nolint - full tx execution
func (app *BaseApp) Simulate(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeSimulate, nil, tx)
}

// nolint
func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeDeliver, nil, tx)
}

// Basic validator for msgs
func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
if msgs == nil || len(msgs) == 0 {
// TODO: probably shouldn't be ErrInternal. Maybe new ErrInvalidMessage, or ?
Expand All @@ -519,9 +475,75 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
return err
}
}

return nil
}

func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) {
// Get the context
if mode == runTxModeCheck || mode == runTxModeSimulate {
ctx = app.checkState.ctx.WithTxBytes(txBytes)
} else {
ctx = app.deliverState.ctx.WithTxBytes(txBytes)
ctx = ctx.WithSigningValidators(app.signedValidators)
}

// Simulate a DeliverTx for gas calculation
if mode == runTxModeSimulate {
ctx = ctx.WithIsCheckTx(false)
}

return
}

// Iterates through msgs and executes them
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg) (result sdk.Result) {
// accumulate results
logs := make([]string, 0, len(msgs))
var data []byte // NOTE: we just append them all (?!)
var tags sdk.Tags // also just append them all
var code sdk.ABCICodeType
for msgIdx, msg := range msgs {
// Match route.
msgType := msg.Type()
handler := app.router.Route(msgType)
if handler == nil {
return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgType).Result()
}

msgResult := handler(ctx, msg)

// NOTE: GasWanted is determined by ante handler and
// GasUsed by the GasMeter

// Append Data and Tags
data = append(data, msgResult.Data...)
tags = append(tags, msgResult.Tags...)

// Stop execution and return on first failed message.
if !msgResult.IsOK() {
logs = append(logs, fmt.Sprintf("Msg %d failed: %s", msgIdx, msgResult.Log))
code = msgResult.Code
break
}

// Construct usable logs in multi-message transactions.
logs = append(logs, fmt.Sprintf("Msg %d: %s", msgIdx, msgResult.Log))
}

// Set the final gas values.
result = sdk.Result{
Code: code,
Data: data,
Log: strings.Join(logs, "\n"),
GasUsed: ctx.GasMeter().GasConsumed(),
// TODO: FeeAmount/FeeDenom
Tags: tags,
}

return result
}

// Returns deliverState if app is in runTxModeDeliver, otherwhise returns checkstate
func getState(app *BaseApp, mode runTxMode) *state {
if mode == runTxModeCheck || mode == runTxModeSimulate {
Expand Down Expand Up @@ -559,6 +581,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk

// Get the Msg.
var msgs = tx.GetMsgs()

err := validateBasicTxMsgs(msgs)
if err != nil {
return err.Result()
Expand All @@ -573,81 +596,22 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
if !newCtx.IsZero() {
ctx = newCtx
}
gasWanted = anteResult.GasWanted
gasWanted = result.GasWanted
}

// Get the correct cache, CacheWrap app.checkState.ms in case it fails.
// CacheWrap the state in case it fails.
msCache := getState(app, mode).CacheMultiStore()
ctx = ctx.WithMultiStore(msCache)

// accumulate results
logs := make([]string, 0, len(msgs))
var data []byte // NOTE: we just append them all (?!)
var tags sdk.Tags // also just append them all
var code sdk.ABCICodeType
for msgIdx, msg := range msgs {
// Match route.
msgType := msg.Type()
handler := app.router.Route(msgType)
if handler == nil {
return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgType).Result()
}

msgResult := handler(ctx, msg)

// NOTE: GasWanted is determined by ante handler and
// GasUsed by the GasMeter

// Append Data and Tags
data = append(data, msgResult.Data...)
tags = append(tags, msgResult.Tags...)

// Stop execution and return on first failed message.
if !msgResult.IsOK() {
logs = append(logs, fmt.Sprintf("Msg %d failed: %s", msgIdx, msgResult.Log))
code = msgResult.Code
break
}

// Construct usable logs in multi-message transactions.
logs = append(logs, fmt.Sprintf("Msg %d: %s", msgIdx, msgResult.Log))
}

// Set the final gas values.
result = sdk.Result{
Code: code,
Data: data,
Log: strings.Join(logs, "\n"),
GasWanted: gasWanted,
GasUsed: ctx.GasMeter().GasConsumed(),
// TODO: FeeAmount/FeeDenom
Tags: tags,
}
result = app.runMsgs(ctx, msgs)
result.GasWanted = gasWanted

// Only update state if all messages pass and we're not in a simulation.
if result.IsOK() && mode != runTxModeSimulate {
msCache.Write()
}

return result
}

func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) sdk.Context {
var ctx sdk.Context

// Get the context.
if mode == runTxModeCheck || mode == runTxModeSimulate {
ctx = app.checkState.ctx.WithTxBytes(txBytes)
} else {
ctx = app.deliverState.ctx.WithTxBytes(txBytes)
ctx = ctx.WithSigningValidators(app.signedValidators)
}

// Simulate a DeliverTx for gas calculation.
if mode == runTxModeSimulate {
ctx = ctx.WithIsCheckTx(false)
}
return ctx
return
}

// Implements ABCI
Expand Down
16 changes: 16 additions & 0 deletions baseapp/helpers.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
package baseapp

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/abci/server"
abci "github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common"
)

// nolint - Mostly for testing
func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeCheck, nil, tx)
}

// nolint - full tx execution
func (app *BaseApp) Simulate(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeSimulate, nil, tx)
}

// nolint
func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) {
return app.runTx(runTxModeDeliver, nil, tx)
}

// RunForever - BasecoinApp execution and cleanup
func RunForever(app abci.Application) {

Expand Down