Add InitValidate method for setup
This commit is contained in:
parent
4b69f1d5ba
commit
37550ca91d
|
@ -114,7 +114,8 @@ func NewHandler(feeDenom string) basecoin.Handler {
|
|||
|
||||
// Handler the counter transaction processing handler
|
||||
type Handler struct {
|
||||
stack.NopOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Dispatchable = Handler{}
|
||||
|
|
33
handler.go
33
handler.go
|
@ -10,22 +10,27 @@ import (
|
|||
|
||||
// Handler is anything that processes a transaction
|
||||
type Handler interface {
|
||||
// Checker verifies there are valid fees and estimates work
|
||||
Checker
|
||||
// Deliver performs the tx once it makes it in the block
|
||||
Deliver
|
||||
// This is for app options
|
||||
// InitStater sets state from the genesis file
|
||||
InitStater
|
||||
// InitValidater sets the initial validator set
|
||||
InitValidater
|
||||
// Named ensures there is a name for the item
|
||||
Named
|
||||
// TODO: for staker
|
||||
// InitChain(log log.Logger, store state.SimpleDB, vals []*abci.Validator)
|
||||
|
||||
// TODO????
|
||||
// BeginBlock(store state.SimpleDB, hash []byte, header *abci.Header)
|
||||
}
|
||||
|
||||
// Named ensures there is a name for the item
|
||||
type Named interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
// Checker verifies there are valid fees and estimates work
|
||||
type Checker interface {
|
||||
CheckTx(ctx Context, store state.SimpleDB, tx Tx) (CheckResult, error)
|
||||
}
|
||||
|
@ -37,6 +42,7 @@ func (c CheckerFunc) CheckTx(ctx Context, store state.SimpleDB, tx Tx) (CheckRes
|
|||
return c(ctx, store, tx)
|
||||
}
|
||||
|
||||
// Deliver performs the tx once it makes it in the block
|
||||
type Deliver interface {
|
||||
DeliverTx(ctx Context, store state.SimpleDB, tx Tx) (DeliverResult, error)
|
||||
}
|
||||
|
@ -48,6 +54,7 @@ func (c DeliverFunc) DeliverTx(ctx Context, store state.SimpleDB, tx Tx) (Delive
|
|||
return c(ctx, store, tx)
|
||||
}
|
||||
|
||||
// InitStater sets state from the genesis file
|
||||
type InitStater interface {
|
||||
InitState(l log.Logger, store state.SimpleDB, module, key, value string) (string, error)
|
||||
}
|
||||
|
@ -59,6 +66,18 @@ func (c InitStateFunc) InitState(l log.Logger, store state.SimpleDB, module, key
|
|||
return c(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// InitValidater sets the initial validator set
|
||||
type InitValidater interface {
|
||||
InitValidate(log log.Logger, store state.SimpleDB, vals []*abci.Validator)
|
||||
}
|
||||
|
||||
// InitValidateFunc (like http.HandlerFunc) is a shortcut for making wrapers
|
||||
type InitValidateFunc func(log.Logger, state.SimpleDB, []*abci.Validator)
|
||||
|
||||
func (c InitValidateFunc) InitValidate(l log.Logger, store state.SimpleDB, vals []*abci.Validator) {
|
||||
c(l, store, vals)
|
||||
}
|
||||
|
||||
//---------- results and some wrappers --------
|
||||
|
||||
type Dataer interface {
|
||||
|
@ -119,8 +138,12 @@ type NopDeliver struct{}
|
|||
|
||||
func (_ NopDeliver) DeliverTx(Context, state.SimpleDB, Tx) (r DeliverResult, e error) { return }
|
||||
|
||||
type NopOption struct{}
|
||||
type NopInitState struct{}
|
||||
|
||||
func (_ NopOption) InitState(log.Logger, state.SimpleDB, string, string, string) (string, error) {
|
||||
func (_ NopInitState) InitState(log.Logger, state.SimpleDB, string, string, string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
type NopInitValidate struct{}
|
||||
|
||||
func (_ NopInitValidate) InitValidate(log log.Logger, store state.SimpleDB, vals []*abci.Validator) {}
|
||||
|
|
|
@ -17,7 +17,8 @@ const (
|
|||
// Signatures parses out go-crypto signatures and adds permissions to the
|
||||
// context for use inside the application
|
||||
type Signatures struct {
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
// Name of the module - fulfills Middleware interface
|
||||
|
|
|
@ -13,7 +13,8 @@ const (
|
|||
|
||||
// Chain enforces that this tx was bound to the named chain
|
||||
type Chain struct {
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
// Name of the module - fulfills Middleware interface
|
||||
|
|
|
@ -3,6 +3,7 @@ package base
|
|||
import (
|
||||
"time"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
|
@ -70,6 +71,15 @@ func (Logger) InitState(l log.Logger, store state.SimpleDB, module, key, value s
|
|||
return res, err
|
||||
}
|
||||
|
||||
// InitValidate logs time and result - fulfills Middlware interface
|
||||
func (Logger) InitValidate(l log.Logger, store state.SimpleDB, vals []*abci.Validator, next basecoin.InitValidater) {
|
||||
start := time.Now()
|
||||
next.InitValidate(l, store, vals)
|
||||
delta := time.Now().Sub(start)
|
||||
l = l.With("duration", micros(delta))
|
||||
l.Info("InitValidate")
|
||||
}
|
||||
|
||||
// micros returns how many microseconds passed in a call
|
||||
func micros(d time.Duration) int {
|
||||
return int(d.Seconds() * 1000000)
|
||||
|
|
|
@ -18,7 +18,7 @@ package base
|
|||
|
||||
// // Multiplexer grabs a MultiTx and sends them sequentially down the line
|
||||
// type Multiplexer struct {
|
||||
// stack.PassOption
|
||||
// stack.PassInitState
|
||||
// }
|
||||
|
||||
// // Name of the module - fulfills Middleware interface
|
||||
|
|
|
@ -16,7 +16,9 @@ import (
|
|||
const NameCoin = "coin"
|
||||
|
||||
// Handler includes an accountant
|
||||
type Handler struct{}
|
||||
type Handler struct {
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Dispatchable = Handler{}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ type SimpleFeeMiddleware struct {
|
|||
// all fees go here, which could be a dump (Bank) or something reachable
|
||||
// by other app logic
|
||||
Collector basecoin.Actor
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Middleware = SimpleFeeMiddleware{}
|
||||
|
|
|
@ -34,7 +34,9 @@ func AllowIBC(app string) basecoin.Actor {
|
|||
}
|
||||
|
||||
// Handler updates the chain state or creates an ibc packet
|
||||
type Handler struct{}
|
||||
type Handler struct {
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = Handler{}
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ import (
|
|||
// Middleware allows us to verify the IBC proof on a packet and
|
||||
// and if valid, attach this permission to the wrapped packet
|
||||
type Middleware struct {
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Middleware = Middleware{}
|
||||
|
|
|
@ -13,7 +13,8 @@ const (
|
|||
|
||||
// ReplayCheck uses the sequence to check for replay attacks
|
||||
type ReplayCheck struct {
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
// Name of the module - fulfills Middleware interface
|
||||
|
|
|
@ -11,7 +11,8 @@ const NameRole = "role"
|
|||
|
||||
// Handler allows us to create new roles
|
||||
type Handler struct {
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = Handler{}
|
||||
|
|
|
@ -9,7 +9,8 @@ import (
|
|||
// Middleware allows us to add a requested role as a permission
|
||||
// if the tx requests it and has sufficient authority
|
||||
type Middleware struct {
|
||||
stack.PassOption
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Middleware = Middleware{}
|
||||
|
|
|
@ -14,7 +14,8 @@ const (
|
|||
type Checkpoint struct {
|
||||
OnCheck bool
|
||||
OnDeliver bool
|
||||
PassOption
|
||||
PassInitState
|
||||
PassInitValidate
|
||||
}
|
||||
|
||||
// Name of the module - fulfills Middleware interface
|
||||
|
|
|
@ -32,12 +32,12 @@ func makeState() state.SimpleDB {
|
|||
func TestCheckpointer(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
good := writerHand{"foo", []byte{1, 2}, []byte("bar")}
|
||||
good := writerHand{name: "foo", key: []byte{1, 2}, value: []byte("bar")}
|
||||
bad := FailHandler{Err: errors.New("no go")}
|
||||
|
||||
app := New(
|
||||
Checkpoint{OnCheck: true},
|
||||
writerMid{"bing", []byte{1, 2}, []byte("bang")},
|
||||
writerMid{name: "bing", key: []byte{1, 2}, value: []byte("bang")},
|
||||
Checkpoint{OnDeliver: true},
|
||||
).Use(
|
||||
NewDispatcher(
|
||||
|
|
|
@ -2,8 +2,10 @@ package stack
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
|
@ -119,6 +121,16 @@ func (d *Dispatcher) InitState(l log.Logger, store state.SimpleDB, module, key,
|
|||
return r.InitState(l, store, module, key, value, cb)
|
||||
}
|
||||
|
||||
// InitValidate makes sure all modules are informed
|
||||
func (d *Dispatcher) InitValidate(log log.Logger, store state.SimpleDB, vals []*abci.Validator) {
|
||||
for _, mod := range d.sortedModules() {
|
||||
// no ctx, so secureCheck not needed
|
||||
cb := d
|
||||
space := stateSpace(store, mod.Name())
|
||||
mod.InitValidate(log, space, vals, cb)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dispatcher) lookupTx(tx basecoin.Tx) (Dispatchable, error) {
|
||||
kind, err := tx.GetKind()
|
||||
if err != nil {
|
||||
|
@ -140,3 +152,19 @@ func (d *Dispatcher) lookupModule(name string) (Dispatchable, error) {
|
|||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (d *Dispatcher) sortedModules() []Dispatchable {
|
||||
// order all routes names
|
||||
size := len(d.routes)
|
||||
names := make([]string, 0, size)
|
||||
for k := range d.routes {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
|
||||
res := make([]Dispatchable, size)
|
||||
for i, k := range names {
|
||||
res[i] = d.routes[k]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -94,7 +94,8 @@ func (r FailTx) ValidateBasic() error {
|
|||
// OKHandler just used to return okay to everything
|
||||
type OKHandler struct {
|
||||
Log string
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = OKHandler{}
|
||||
|
@ -116,7 +117,8 @@ func (ok OKHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx bas
|
|||
|
||||
// EchoHandler returns success, echoing res.Data = tx bytes
|
||||
type EchoHandler struct {
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = EchoHandler{}
|
||||
|
@ -141,7 +143,8 @@ func (EchoHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx base
|
|||
// FailHandler always returns an error
|
||||
type FailHandler struct {
|
||||
Err error
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = FailHandler{}
|
||||
|
@ -165,7 +168,8 @@ func (f FailHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx ba
|
|||
type PanicHandler struct {
|
||||
Msg string
|
||||
Err error
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = PanicHandler{}
|
||||
|
@ -193,7 +197,8 @@ func (p PanicHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx b
|
|||
|
||||
// CheckHandler accepts CheckTx and verifies the permissions
|
||||
type CheckHandler struct {
|
||||
basecoin.NopOption
|
||||
basecoin.NopInitState
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = CheckHandler{}
|
||||
|
|
|
@ -16,7 +16,8 @@ const (
|
|||
// Required Actor, otherwise passes along the call untouched
|
||||
type CheckMiddleware struct {
|
||||
Required basecoin.Actor
|
||||
PassOption
|
||||
PassInitState
|
||||
PassInitValidate
|
||||
}
|
||||
|
||||
var _ Middleware = CheckMiddleware{}
|
||||
|
@ -42,7 +43,8 @@ func (p CheckMiddleware) DeliverTx(ctx basecoin.Context, store state.SimpleDB, t
|
|||
// GrantMiddleware tries to set the permission to this Actor, which may be prohibited
|
||||
type GrantMiddleware struct {
|
||||
Auth basecoin.Actor
|
||||
PassOption
|
||||
PassInitState
|
||||
PassInitValidate
|
||||
}
|
||||
|
||||
var _ Middleware = GrantMiddleware{}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
|
@ -15,7 +16,8 @@ import (
|
|||
type Middleware interface {
|
||||
CheckerMiddle
|
||||
DeliverMiddle
|
||||
InitStateMiddle
|
||||
InitStaterMiddle
|
||||
InitValidaterMiddle
|
||||
basecoin.Named
|
||||
}
|
||||
|
||||
|
@ -45,19 +47,31 @@ func (d DeliverMiddleFunc) DeliverTx(ctx basecoin.Context, store state.SimpleDB,
|
|||
return d(ctx, store, tx, next)
|
||||
}
|
||||
|
||||
type InitStateMiddle interface {
|
||||
type InitStaterMiddle interface {
|
||||
InitState(l log.Logger, store state.SimpleDB, module,
|
||||
key, value string, next basecoin.InitStater) (string, error)
|
||||
}
|
||||
|
||||
type InitStateMiddleFunc func(log.Logger, state.SimpleDB,
|
||||
type InitStaterMiddleFunc func(log.Logger, state.SimpleDB,
|
||||
string, string, string, basecoin.InitStater) (string, error)
|
||||
|
||||
func (c InitStateMiddleFunc) InitState(l log.Logger, store state.SimpleDB,
|
||||
func (c InitStaterMiddleFunc) InitState(l log.Logger, store state.SimpleDB,
|
||||
module, key, value string, next basecoin.InitStater) (string, error) {
|
||||
return c(l, store, module, key, value, next)
|
||||
}
|
||||
|
||||
type InitValidaterMiddle interface {
|
||||
InitValidate(l log.Logger, store state.SimpleDB, vals []*abci.Validator, next basecoin.InitValidater)
|
||||
}
|
||||
|
||||
type InitValidaterMiddleFunc func(log.Logger, state.SimpleDB,
|
||||
[]*abci.Validator, basecoin.InitValidater)
|
||||
|
||||
func (c InitValidaterMiddleFunc) InitValidate(l log.Logger, store state.SimpleDB,
|
||||
vals []*abci.Validator, next basecoin.InitValidater) {
|
||||
c(l, store, vals, next)
|
||||
}
|
||||
|
||||
// holders
|
||||
type PassCheck struct{}
|
||||
|
||||
|
@ -73,18 +87,18 @@ func (_ PassDeliver) DeliverTx(ctx basecoin.Context, store state.SimpleDB,
|
|||
return next.DeliverTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
type PassOption struct{}
|
||||
type PassInitState struct{}
|
||||
|
||||
func (_ PassOption) InitState(l log.Logger, store state.SimpleDB, module,
|
||||
func (_ PassInitState) InitState(l log.Logger, store state.SimpleDB, module,
|
||||
key, value string, next basecoin.InitStater) (string, error) {
|
||||
return next.InitState(l, store, module, key, value)
|
||||
}
|
||||
|
||||
type NopOption struct{}
|
||||
type PassInitValidate struct{}
|
||||
|
||||
func (_ NopOption) InitState(l log.Logger, store state.SimpleDB, module,
|
||||
key, value string, next basecoin.InitStater) (string, error) {
|
||||
return "", nil
|
||||
func (_ PassInitValidate) InitValidate(l log.Logger, store state.SimpleDB,
|
||||
vals []*abci.Validator, next basecoin.InitValidater) {
|
||||
next.InitValidate(l, store, vals)
|
||||
}
|
||||
|
||||
// Dispatchable is like middleware, except the meaning of "next" is different.
|
||||
|
@ -126,3 +140,8 @@ func (w wrapped) InitState(l log.Logger, store state.SimpleDB,
|
|||
module, key, value string, _ basecoin.InitStater) (string, error) {
|
||||
return w.h.InitState(l, store, module, key, value)
|
||||
}
|
||||
|
||||
func (w wrapped) InitValidate(l log.Logger, store state.SimpleDB,
|
||||
vals []*abci.Validator, next basecoin.InitValidater) {
|
||||
w.h.InitValidate(l, store, vals)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
|
@ -59,6 +60,12 @@ func (m *middleware) InitState(l log.Logger, store state.SimpleDB, module, key,
|
|||
return m.middleware.InitState(l, store, module, key, value, m.next)
|
||||
}
|
||||
|
||||
func (m *middleware) InitValidate(l log.Logger, store state.SimpleDB, vals []*abci.Validator) {
|
||||
// set the namespace for the app
|
||||
store = stateSpace(store, m.space)
|
||||
m.middleware.InitValidate(l, store, vals, m.next)
|
||||
}
|
||||
|
||||
// builder is used to associate info with the middleware, so we can build
|
||||
// it properly
|
||||
type builder struct {
|
||||
|
|
|
@ -3,6 +3,7 @@ package stack
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
|
@ -55,6 +56,21 @@ func (Recovery) InitState(l log.Logger, store state.SimpleDB, module, key, value
|
|||
return next.InitState(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// InitValidate catches any panic and logs it
|
||||
// TODO: return an error???
|
||||
func (Recovery) InitValidate(l log.Logger, store state.SimpleDB,
|
||||
vals []*abci.Validator, next basecoin.InitValidater) {
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// TODO: return an error???
|
||||
err := normalizePanic(r)
|
||||
l.With("err", err).Error(err.Error())
|
||||
}
|
||||
}()
|
||||
next.InitValidate(l, store, vals)
|
||||
}
|
||||
|
||||
// normalizePanic makes sure we can get a nice TMError (with stack) out of it
|
||||
func normalizePanic(p interface{}) error {
|
||||
if err, isErr := p.(error); isErr {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
type writerMid struct {
|
||||
name string
|
||||
key, value []byte
|
||||
PassInitValidate
|
||||
}
|
||||
|
||||
var _ Middleware = writerMid{}
|
||||
|
@ -41,10 +42,11 @@ func (w writerMid) InitState(l log.Logger, store state.SimpleDB, module,
|
|||
return next.InitState(l, store, module, key, value)
|
||||
}
|
||||
|
||||
// writerHand is a middleware that writes the given bytes on CheckTx and DeliverTx
|
||||
// writerHand is a handler that writes the given bytes on CheckTx and DeliverTx
|
||||
type writerHand struct {
|
||||
name string
|
||||
key, value []byte
|
||||
basecoin.NopInitValidate
|
||||
}
|
||||
|
||||
var _ basecoin.Handler = writerHand{}
|
||||
|
@ -76,9 +78,9 @@ func TestStateSpace(t *testing.T) {
|
|||
expected []data.Bytes
|
||||
}{
|
||||
{
|
||||
writerHand{"foo", []byte{1, 2}, []byte("bar")},
|
||||
writerHand{name: "foo", key: []byte{1, 2}, value: []byte("bar")},
|
||||
[]Middleware{
|
||||
writerMid{"bing", []byte{1, 2}, []byte("bang")},
|
||||
writerMid{name: "bing", key: []byte{1, 2}, value: []byte("bang")},
|
||||
},
|
||||
[]data.Bytes{
|
||||
{'f', 'o', 'o', 0, 1, 2},
|
||||
|
|
Loading…
Reference in New Issue