Update decorators/handler/results.go add tx_msg/signature.go
This commit is contained in:
parent
6a9b8c3a92
commit
458fba22d3
46
db.go
46
db.go
|
@ -1,46 +0,0 @@
|
||||||
package sdk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/tendermint/go-wire/data"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KVStore is a simple interface to get/set data
|
|
||||||
type KVStore interface {
|
|
||||||
Set(key, value []byte)
|
|
||||||
Get(key []byte) (value []byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------
|
|
||||||
|
|
||||||
// Model grabs together key and value to allow easier return values
|
|
||||||
type Model struct {
|
|
||||||
Key data.Bytes
|
|
||||||
Value data.Bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
// SimpleDB allows us to do some basic range queries on a db
|
|
||||||
type SimpleDB interface {
|
|
||||||
KVStore
|
|
||||||
|
|
||||||
Has(key []byte) (has bool)
|
|
||||||
Remove(key []byte) (value []byte) // returns old value if there was one
|
|
||||||
|
|
||||||
// Start is inclusive, End is exclusive...
|
|
||||||
// Thus List ([]byte{12, 13}, []byte{12, 14}) will return anything with
|
|
||||||
// the prefix []byte{12, 13}
|
|
||||||
List(start, end []byte, limit int) []Model
|
|
||||||
First(start, end []byte) Model
|
|
||||||
Last(start, end []byte) Model
|
|
||||||
|
|
||||||
// Checkpoint returns the same state, but where writes
|
|
||||||
// are buffered and don't affect the parent
|
|
||||||
Checkpoint() SimpleDB
|
|
||||||
|
|
||||||
// Commit will take all changes from the checkpoint and write
|
|
||||||
// them to the parent.
|
|
||||||
// Returns an error if this is not a child of this one
|
|
||||||
Commit(SimpleDB) error
|
|
||||||
|
|
||||||
// Discard will remove reference to this
|
|
||||||
Discard()
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
package sdk
|
|
||||||
|
|
||||||
// Decorator is anything that wraps another handler
|
|
||||||
// to enhance functionality.
|
|
||||||
//
|
|
||||||
// They are usually chained together via ChainDecorators
|
|
||||||
// before wrapping an interface.
|
|
||||||
type Decorator interface {
|
|
||||||
DecorateChecker
|
|
||||||
DecorateDeliverer
|
|
||||||
}
|
|
||||||
|
|
||||||
type DecorateChecker interface {
|
|
||||||
CheckTx(ctx Context, store SimpleDB,
|
|
||||||
tx interface{}, next Checker) (CheckResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type DecorateDeliverer interface {
|
|
||||||
DeliverTx(ctx Context, store SimpleDB, tx interface{},
|
|
||||||
next Deliverer) (DeliverResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stack is the entire application stack
|
|
||||||
type Stack struct {
|
|
||||||
decorators []Decorator
|
|
||||||
handler Handler
|
|
||||||
Handler // the compiled version, which we expose
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Handler = &Stack{}
|
|
||||||
|
|
||||||
// ChainDecorators prepares a stack of decorators,
|
|
||||||
// you must call `.WithHandler()` before you can execute it.
|
|
||||||
func ChainDecorators(decorators ...Decorator) *Stack {
|
|
||||||
s := &Stack{
|
|
||||||
decorators: decorators,
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHandler sets the final handler for the stack and
|
|
||||||
// prepares it for use
|
|
||||||
func (s *Stack) WithHandler(handler Handler) *Stack {
|
|
||||||
if handler == nil {
|
|
||||||
panic("Cannot have a Stack without an end handler")
|
|
||||||
}
|
|
||||||
s.handler = handler
|
|
||||||
s.Handler = build(s.decorators, s.handler)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// build wraps each decorator around the next, so that
|
|
||||||
// the last in the list is closest to the handler
|
|
||||||
func build(stack []Decorator, end Handler) Handler {
|
|
||||||
if len(stack) == 0 {
|
|
||||||
return end
|
|
||||||
}
|
|
||||||
return wrap(stack[0], build(stack[1:], end))
|
|
||||||
}
|
|
||||||
|
|
||||||
// decorator lets us wrap a whole stack up into one Handler
|
|
||||||
//
|
|
||||||
// heavily inspired by negroni's design
|
|
||||||
type decorator struct {
|
|
||||||
decorator Decorator
|
|
||||||
next Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure it fulfils the interface
|
|
||||||
var _ Handler = &decorator{}
|
|
||||||
|
|
||||||
// CheckTx fulfils Handler interface
|
|
||||||
func (m *decorator) CheckTx(ctx Context, store SimpleDB,
|
|
||||||
tx interface{}) (CheckResult, error) {
|
|
||||||
|
|
||||||
return m.decorator.CheckTx(ctx, store, tx, m.next)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeliverTx fulfils Handler interface
|
|
||||||
func (m *decorator) DeliverTx(ctx Context, store SimpleDB,
|
|
||||||
tx interface{}) (res DeliverResult, err error) {
|
|
||||||
|
|
||||||
return m.decorator.DeliverTx(ctx, store, tx, m.next)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrap puts one decorator around a handler
|
|
||||||
func wrap(dec Decorator, next Handler) Handler {
|
|
||||||
return &decorator{
|
|
||||||
decorator: dec,
|
|
||||||
next: next,
|
|
||||||
}
|
|
||||||
}
|
|
105
handler.go
105
handler.go
|
@ -1,105 +0,0 @@
|
||||||
package sdk
|
|
||||||
|
|
||||||
import (
|
|
||||||
abci "github.com/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/tmlibs/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// ModuleNameBase is the module name for internal functionality
|
|
||||||
ModuleNameBase = "base"
|
|
||||||
// ChainKey is the option key for setting the chain id
|
|
||||||
ChainKey = "chain_id"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handler is anything that processes a transaction.
|
|
||||||
// Must handle checktx and delivertx
|
|
||||||
type Handler interface {
|
|
||||||
// Checker verifies there are valid fees and estimates work
|
|
||||||
Checker
|
|
||||||
// Deliver performs the tx once it makes it in the block
|
|
||||||
Deliverer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checker verifies there are valid fees and estimates work
|
|
||||||
type Checker interface {
|
|
||||||
CheckTx(ctx Context, store SimpleDB, tx interface{}) (CheckResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckerFunc (like http.HandlerFunc) is a shortcut for making wrappers
|
|
||||||
type CheckerFunc func(Context, SimpleDB, interface{}) (CheckResult, error)
|
|
||||||
|
|
||||||
func (c CheckerFunc) CheckTx(ctx Context, store SimpleDB, tx interface{}) (CheckResult, error) {
|
|
||||||
return c(ctx, store, tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deliverer performs the tx once it makes it in the block
|
|
||||||
type Deliverer interface {
|
|
||||||
DeliverTx(ctx Context, store SimpleDB, tx interface{}) (DeliverResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelivererFunc (like http.HandlerFunc) is a shortcut for making wrappers
|
|
||||||
type DelivererFunc func(Context, SimpleDB, interface{}) (DeliverResult, error)
|
|
||||||
|
|
||||||
func (c DelivererFunc) DeliverTx(ctx Context, store SimpleDB, tx interface{}) (DeliverResult, error) {
|
|
||||||
return c(ctx, store, tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
|
||||||
// Lifecycle actions, not tied to the tx handler
|
|
||||||
|
|
||||||
// Ticker can be executed every block.
|
|
||||||
// Called from BeginBlock
|
|
||||||
type Ticker interface {
|
|
||||||
Tick(Context, SimpleDB) ([]*abci.Validator, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TickerFunc allows a function to implement the interface
|
|
||||||
type TickerFunc func(Context, SimpleDB) ([]*abci.Validator, error)
|
|
||||||
|
|
||||||
func (t TickerFunc) Tick(ctx Context, store SimpleDB) ([]*abci.Validator, error) {
|
|
||||||
return t(ctx, store)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitValidator sets the initial validator set.
|
|
||||||
// Called from InitChain
|
|
||||||
type InitValidator interface {
|
|
||||||
InitValidators(logger log.Logger, store SimpleDB,
|
|
||||||
vals []*abci.Validator)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitStater sets state from the genesis file
|
|
||||||
//
|
|
||||||
// TODO: Think if this belongs here, in genesis, or somewhere else
|
|
||||||
type InitStater interface {
|
|
||||||
InitState(logger log.Logger, store SimpleDB,
|
|
||||||
module, key, value string) (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// Helper methods
|
|
||||||
|
|
||||||
// Msg allows us to get the actual tx from a structure with lots of
|
|
||||||
// decorator information. This is usually what should be passed to Handlers.
|
|
||||||
type Msg interface {
|
|
||||||
GetTx() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustGetTx forces the msg to the interface and extracts the tx
|
|
||||||
func MustGetTx(msg interface{}) interface{} {
|
|
||||||
m := msg.(Msg)
|
|
||||||
return m.GetTx()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapTx embeds the tx into a Msg interface, with no decorator info
|
|
||||||
func WrapTx(tx interface{}) Msg {
|
|
||||||
return msg{tx}
|
|
||||||
}
|
|
||||||
|
|
||||||
type msg struct {
|
|
||||||
tx interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m msg) GetTx() interface{} {
|
|
||||||
return m.tx
|
|
||||||
}
|
|
70
results.go
70
results.go
|
@ -1,70 +0,0 @@
|
||||||
package sdk
|
|
||||||
|
|
||||||
import (
|
|
||||||
abci "github.com/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/go-wire/data"
|
|
||||||
)
|
|
||||||
|
|
||||||
//---------- results and some wrappers --------
|
|
||||||
|
|
||||||
// Result is a common interface of CheckResult and GetResult
|
|
||||||
type Result interface {
|
|
||||||
GetData() data.Bytes
|
|
||||||
GetLog() string
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToABCI(r Result) abci.Result {
|
|
||||||
return abci.Result{
|
|
||||||
Data: r.GetData(),
|
|
||||||
Log: r.GetLog(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckResult captures any non-error abci result
|
|
||||||
// to make sure people use error for error cases
|
|
||||||
type CheckResult struct {
|
|
||||||
Data data.Bytes
|
|
||||||
Log string
|
|
||||||
// GasAllocated is the maximum units of work we allow this tx to perform
|
|
||||||
GasAllocated uint64
|
|
||||||
// GasPayment is the total fees for this tx (or other source of payment)
|
|
||||||
GasPayment uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCheck sets the gas used and the response data but no more info
|
|
||||||
// these are the most common info needed to be set by the Handler
|
|
||||||
func NewCheck(gasAllocated uint64, log string) CheckResult {
|
|
||||||
return CheckResult{
|
|
||||||
GasAllocated: gasAllocated,
|
|
||||||
Log: log,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Result = CheckResult{}
|
|
||||||
|
|
||||||
func (r CheckResult) GetData() data.Bytes {
|
|
||||||
return r.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r CheckResult) GetLog() string {
|
|
||||||
return r.Log
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeliverResult captures any non-error abci result
|
|
||||||
// to make sure people use error for error cases
|
|
||||||
type DeliverResult struct {
|
|
||||||
Data data.Bytes
|
|
||||||
Log string
|
|
||||||
Diff []*abci.Validator
|
|
||||||
GasUsed uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Result = DeliverResult{}
|
|
||||||
|
|
||||||
func (r DeliverResult) GetData() data.Bytes {
|
|
||||||
return r.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r DeliverResult) GetLog() string {
|
|
||||||
return r.Log
|
|
||||||
}
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
package sdk
|
||||||
|
|
||||||
|
// A Decorator executes before/during/after a handler to enhance functionality.
|
||||||
|
type Decorator interface {
|
||||||
|
|
||||||
|
// Decorate Handler.CheckTx
|
||||||
|
CheckTx(ctx Context, ms MultiStore, tx Tx,
|
||||||
|
next CheckTxFunc) CheckResult
|
||||||
|
|
||||||
|
// Decorate Handler.DeliverTx
|
||||||
|
DeliverTx(ctx Context, ms MultiStore, tx Tx,
|
||||||
|
next DeliverTxFunc) DeliverResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Decorator tied to its base handler "next" is itself a handler.
|
||||||
|
func Decorate(dec Decorator, next Handler) Handler {
|
||||||
|
return &decHandler{
|
||||||
|
decorator: dec,
|
||||||
|
next: next,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper to construct a decorated Handler from a stack of Decorators
|
||||||
|
(first-decorator-first-call as in Python @decorators) , w/ Handler provided
|
||||||
|
last for syntactic sugar of Stack().WithHandler()
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
handler := sdk.Stack(
|
||||||
|
decorator1,
|
||||||
|
decorator2,
|
||||||
|
...,
|
||||||
|
).WithHandler(myHandler)
|
||||||
|
|
||||||
|
*/
|
||||||
|
func Stack(decorators ...Decorator) stack {
|
||||||
|
return stack{
|
||||||
|
decs: decorators,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to expose this.
|
||||||
|
type stack struct {
|
||||||
|
decs []Decorator
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHandler sets the final handler for the stack and
|
||||||
|
// returns the decoratored Handler.
|
||||||
|
func (s *Stack) WithHandler(handler Handler) Handler {
|
||||||
|
if handler == nil {
|
||||||
|
panic("WithHandler() requires a non-nil Handler")
|
||||||
|
}
|
||||||
|
return build(s.decs, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build wraps each decorator around the next, so that
|
||||||
|
// the last in the list is closest to the handler
|
||||||
|
func build(stack []Decorator, end Handler) Handler {
|
||||||
|
if len(stack) == 0 {
|
||||||
|
return end
|
||||||
|
}
|
||||||
|
return decHandler{
|
||||||
|
decorator: stack[0],
|
||||||
|
next: build(stack[1:], end),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
|
||||||
|
type decHandler struct {
|
||||||
|
decorator Decorator
|
||||||
|
next Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Handler = &decHandler{}
|
||||||
|
|
||||||
|
func (dh *decHandler) CheckTx(ctx Context, ms MultiStore, tx Tx) CheckResult {
|
||||||
|
return dh.decorator.CheckTx(ctx, ms, tx, dh.next)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dh *decHandler) DeliverTx(ctx Context, ms MultiStore, tx Tx) DeliverResult {
|
||||||
|
return dh.decorator.DeliverTx(ctx, ms, tx, dh.next)
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package sdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler is something that processes a transaction.
|
||||||
|
type Handler interface {
|
||||||
|
|
||||||
|
// Checker verifies there are valid fees and estimates work.
|
||||||
|
CheckTx(ctx Context, ms MultiStore, tx Tx) CheckResult
|
||||||
|
|
||||||
|
// Deliverer performs the tx once it makes it in the block.
|
||||||
|
DeliverTx(ctx Context, ms MultiStore, tx Tx) DeliverResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checker verifies there are valid fees and estimates work.
|
||||||
|
// NOTE: Keep in sync with Handler.CheckTx
|
||||||
|
type CheckTxFunc func(ctx Context, ms MultiStore, tx Tx) CheckResult
|
||||||
|
|
||||||
|
// Deliverer performs the tx once it makes it in the block.
|
||||||
|
// NOTE: Keep in sync with Handler.DeliverTx
|
||||||
|
type DeliverTxFunc func(ctx Context, ms MultiStore, tx Tx) DeliverResult
|
27
types/msg.go
27
types/msg.go
|
@ -1,27 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
||||||
import crypto "github.com/tendermint/go-crypto"
|
|
||||||
|
|
||||||
// The parsed tx bytes is called a Msg.
|
|
||||||
type Msg interface {
|
|
||||||
Get(key interface{}) (value interface{})
|
|
||||||
Origin() (tx []byte)
|
|
||||||
|
|
||||||
// Signers() returns the crypto.PubKey of signers
|
|
||||||
// responsible for signing the Msg.
|
|
||||||
// CONTRACT: All signatures must be present to be valid.
|
|
||||||
// CONTRACT: Returns pubkeys in some deterministic order
|
|
||||||
// CONTRACT: Get(MsgKeySigners) compatible.
|
|
||||||
Signers() []crypto.PubKey
|
|
||||||
|
|
||||||
// Signatures() returns the crypto.Signature of sigenrs
|
|
||||||
// who signed the Msg.
|
|
||||||
// CONTRACT: Length returned is same as length of
|
|
||||||
// pubkeys returned from MsgKeySigners, and the order
|
|
||||||
// matches.
|
|
||||||
// CONTRACT: If the signature is missing (ie the Msg is
|
|
||||||
// invalid), then the corresponding signature is
|
|
||||||
// .Empty().
|
|
||||||
// CONTRACT: Get(MsgKeySignatures) compatible.
|
|
||||||
Signatures() []crypto.Signature
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CheckResult captures any non-error ABCI result
|
||||||
|
// to make sure people use error for error cases.
|
||||||
|
type CheckResult struct {
|
||||||
|
abci.Result
|
||||||
|
|
||||||
|
// GasAllocated is the maximum units of work we allow this tx to perform
|
||||||
|
GasAllocated uint64
|
||||||
|
|
||||||
|
// GasPayment is the total fees for this tx (or other source of payment)
|
||||||
|
GasPayment uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverResult captures any non-error abci result
|
||||||
|
// to make sure people use error for error cases
|
||||||
|
type DeliverResult struct {
|
||||||
|
abci.Result
|
||||||
|
|
||||||
|
// TODO comment
|
||||||
|
Diff []*abci.Validator
|
||||||
|
|
||||||
|
// TODO comment
|
||||||
|
GasUsed uint64
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import crypto "github.com/tendermint/go-crypto"
|
||||||
|
|
||||||
|
type Signature interface {
|
||||||
|
CryptoSig() crypto.Signature
|
||||||
|
Sequence() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// StdSignature is a simple way to prevent replay attacks.
|
||||||
|
// There must be better strategies, but this is simplest.
|
||||||
|
type StdSignature struct {
|
||||||
|
crypto.Signature
|
||||||
|
Sequence int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss StdSignature) CryptoSig() crypto.Signature {
|
||||||
|
return ss.Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss StdSignature) Sequence() int {
|
||||||
|
return ss.Sequence
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
type Msg interface {
|
||||||
|
|
||||||
|
// Get some property of the Msg.
|
||||||
|
Get(key interface{}) (value interface{})
|
||||||
|
|
||||||
|
// Get the canonical byte representation of the Msg.
|
||||||
|
SignBytes() []byte
|
||||||
|
|
||||||
|
// ValidateBasic does a simple validation check that
|
||||||
|
// doesn't require access to any other information.
|
||||||
|
ValidateBasic() error
|
||||||
|
|
||||||
|
// Signers returns the addrs of signers that must sign.
|
||||||
|
// CONTRACT: All signatures must be present to be valid.
|
||||||
|
// CONTRACT: Returns addrs in some deterministic order.
|
||||||
|
Signers() [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tx interface {
|
||||||
|
Msg
|
||||||
|
|
||||||
|
// Get the canonical byte representation of the Tx.
|
||||||
|
// Includes any signatures (or empty slots).
|
||||||
|
TxBytes() []byte
|
||||||
|
|
||||||
|
// Signatures returns the signature of signers who signed the Msg.
|
||||||
|
// CONTRACT: Length returned is same as length of
|
||||||
|
// pubkeys returned from MsgKeySigners, and the order
|
||||||
|
// matches.
|
||||||
|
// CONTRACT: If the signature is missing (ie the Msg is
|
||||||
|
// invalid), then the corresponding signature is
|
||||||
|
// .Empty().
|
||||||
|
Signatures() []Signature
|
||||||
|
}
|
Loading…
Reference in New Issue