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

DNM: app wiring POC #9398

Closed
wants to merge 20 commits into from
67 changes: 67 additions & 0 deletions core/abci/app_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package abci

import (
"context"

"github.com/tendermint/tendermint/abci/types"
)

type AppBase struct {
handler Handler
checkCtx context.Context
deliverCtx context.Context
}

var _ types.Application = AppBase{}

func (a AppBase) Info(info types.RequestInfo) types.ResponseInfo {
return a.handler.Info(a.checkCtx, info)
}

func (a AppBase) SetOption(option types.RequestSetOption) types.ResponseSetOption {
return a.handler.SetOption(a.checkCtx, option)
}

func (a AppBase) Query(query types.RequestQuery) types.ResponseQuery {
return a.handler.Query(a.checkCtx, query)
}

func (a AppBase) CheckTx(tx types.RequestCheckTx) types.ResponseCheckTx {
return a.handler.CheckTx(a.checkCtx, tx)
}

func (a AppBase) InitChain(chain types.RequestInitChain) types.ResponseInitChain {
return a.handler.InitChain(a.deliverCtx, chain)
}

func (a AppBase) BeginBlock(block types.RequestBeginBlock) types.ResponseBeginBlock {
return a.handler.BeginBlock(a.deliverCtx, block)
}

func (a AppBase) DeliverTx(tx types.RequestDeliverTx) types.ResponseDeliverTx {
return a.handler.DeliverTx(a.deliverCtx, tx)
}

func (a AppBase) EndBlock(block types.RequestEndBlock) types.ResponseEndBlock {
return a.handler.EndBlock(a.deliverCtx, block)
}

func (a AppBase) Commit() types.ResponseCommit {
return a.handler.Commit(a.deliverCtx)
}

func (a AppBase) ListSnapshots(snapshots types.RequestListSnapshots) types.ResponseListSnapshots {
return a.handler.ListSnapshots(a.checkCtx, snapshots)
}

func (a AppBase) OfferSnapshot(snapshot types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
return a.handler.OfferSnapshot(a.checkCtx, snapshot)
}

func (a AppBase) LoadSnapshotChunk(chunk types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
return a.handler.LoadSnapshotChunk(a.checkCtx, chunk)
}

func (a AppBase) ApplySnapshotChunk(chunk types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
return a.handler.ApplySnapshotChunk(a.checkCtx, chunk)
}
5 changes: 5 additions & 0 deletions core/abci/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package config

type Config struct {
Middleware []interface{}
}
30 changes: 30 additions & 0 deletions core/abci/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package abci

import (
"context"

types "github.com/tendermint/tendermint/abci/types"
)

type Handler interface {
// Info/Query Connection
Info(ctx context.Context, req types.RequestInfo) types.ResponseInfo // Return application info
SetOption(ctx context.Context, req types.RequestSetOption) types.ResponseSetOption // Set application option
Query(ctx context.Context, req types.RequestQuery) types.ResponseQuery // Query for state

// Mempool Connection
CheckTx(ctx context.Context, req types.RequestCheckTx) types.ResponseCheckTx // Validate a tx for the mempool

// Consensus Connection
InitChain(ctx context.Context, req types.RequestInitChain) types.ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore
BeginBlock(ctx context.Context, req types.RequestBeginBlock) types.ResponseBeginBlock // Signals the beginning of a block
DeliverTx(ctx context.Context, req types.RequestDeliverTx) types.ResponseDeliverTx // Deliver a tx for full processing
EndBlock(ctx context.Context, req types.RequestEndBlock) types.ResponseEndBlock // Signals the end of a block, returns changes to the validator set
Commit(context.Context) types.ResponseCommit // Commit the state and return the application Merkle root hash

// State Sync Connection
ListSnapshots(ctx context.Context, req types.RequestListSnapshots) types.ResponseListSnapshots // List available snapshots
OfferSnapshot(ctx context.Context, req types.RequestOfferSnapshot) types.ResponseOfferSnapshot // Offer a snapshot to the application
LoadSnapshotChunk(ctx context.Context, req types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk // Load a snapshot chunk
ApplySnapshotChunk(ctx context.Context, req types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk // Apply a shapshot chunk
}
63 changes: 63 additions & 0 deletions core/abci/handler_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package abci

import (
"context"

"github.com/tendermint/tendermint/abci/types"
)

type HandlerBase struct{}

func (h HandlerBase) Info(context.Context, types.RequestInfo) types.ResponseInfo {
return types.ResponseInfo{}
}

func (h HandlerBase) SetOption(context.Context, types.RequestSetOption) types.ResponseSetOption {
return types.ResponseSetOption{}
}

func (h HandlerBase) Query(context.Context, types.RequestQuery) types.ResponseQuery {
return types.ResponseQuery{}
}

func (h HandlerBase) CheckTx(context.Context, types.RequestCheckTx) types.ResponseCheckTx {
return types.ResponseCheckTx{}
}

func (h HandlerBase) InitChain(context.Context, types.RequestInitChain) types.ResponseInitChain {
return types.ResponseInitChain{}
}

func (h HandlerBase) BeginBlock(context.Context, types.RequestBeginBlock) types.ResponseBeginBlock {
return types.ResponseBeginBlock{}
}

func (h HandlerBase) DeliverTx(context.Context, types.RequestDeliverTx) types.ResponseDeliverTx {
return types.ResponseDeliverTx{}
}

func (h HandlerBase) EndBlock(context.Context, types.RequestEndBlock) types.ResponseEndBlock {
return types.ResponseEndBlock{}
}

func (h HandlerBase) Commit(context.Context) types.ResponseCommit {
return types.ResponseCommit{}
}

func (h HandlerBase) ListSnapshots(context.Context, types.RequestListSnapshots) types.ResponseListSnapshots {
return types.ResponseListSnapshots{}
}

func (h HandlerBase) OfferSnapshot(context.Context, types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
return types.ResponseOfferSnapshot{}
}

func (h HandlerBase) LoadSnapshotChunk(context.Context, types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
return types.ResponseLoadSnapshotChunk{}
}

func (h HandlerBase) ApplySnapshotChunk(context.Context, types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
return types.ResponseApplySnapshotChunk{}
}

var _ Handler = HandlerBase{}
88 changes: 88 additions & 0 deletions core/abci/header/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package header

import (
"context"
"fmt"

tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/tendermint/tendermint/abci/types"

"github.com/cosmos/cosmos-sdk/core/abci"
)

var Middleware abci.Middleware = func(handler abci.Handler) abci.Handler {
return &middleware{
Handler: handler,
}
}

type middleware struct {
abci.Handler
initialHeight int64
lastBlockHeight int64
}

func (m *middleware) InitChain(ctx context.Context, req types.RequestInitChain) types.ResponseInitChain {
// On a new chain, we consider the init chain block height as 0, even though
// req.InitialHeight is 1 by default.
initHeader := tmproto.Header{ChainID: req.ChainId, Time: req.Time}

// If req.InitialHeight is > 1, then we set the initial version in the
// stores.
if req.InitialHeight > 1 {
m.initialHeight = req.InitialHeight
initHeader = tmproto.Header{ChainID: req.ChainId, Height: req.InitialHeight, Time: req.Time}
}

sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx = sdkCtx.WithBlockHeader(initHeader)
ctx = context.WithValue(ctx, sdk.SdkContextKey, sdkCtx)

return m.Handler.InitChain(ctx, req)
}

func (m *middleware) BeginBlock(ctx context.Context, req types.RequestBeginBlock) types.ResponseBeginBlock {
if err := m.validateHeight(req); err != nil {
panic(err)
}

m.lastBlockHeight = req.Header.Height

sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx = sdkCtx.
WithBlockHeader(req.Header).
WithBlockHeight(req.Header.Height)
ctx = context.WithValue(ctx, sdk.SdkContextKey, sdkCtx)

return m.Handler.BeginBlock(ctx, req)
}

func (m middleware) validateHeight(req types.RequestBeginBlock) error {
if req.Header.Height < 1 {
return fmt.Errorf("invalid height: %d", req.Header.Height)
}

// expectedHeight holds the expected height to validate.
var expectedHeight int64
if m.lastBlockHeight == 0 && m.initialHeight > 1 {
// In this case, we're validating the first block of the chain (no
// previous commit). The height we're expecting is the initial height.
expectedHeight = m.initialHeight
} else {
// This case can means two things:
// - either there was already a previous commit in the store, in which
// case we increment the version from there,
// - or there was no previous commit, and initial version was not set,
// in which case we start at version 1.
expectedHeight = m.lastBlockHeight + 1
}

if req.Header.Height != expectedHeight {
return fmt.Errorf("invalid height: %d; expected: %d", req.Header.Height, expectedHeight)
}

return nil
}
3 changes: 3 additions & 0 deletions core/abci/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package abci

type Middleware func(Handler) Handler
Loading