diff --git a/db.go b/db.go deleted file mode 100644 index bcb5c98b46ed..000000000000 --- a/db.go +++ /dev/null @@ -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() -} diff --git a/decorators.go b/decorators.go deleted file mode 100644 index 71f5fa959bd7..000000000000 --- a/decorators.go +++ /dev/null @@ -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, - } -} diff --git a/handler.go b/handler.go deleted file mode 100644 index ae7906029ea9..000000000000 --- a/handler.go +++ /dev/null @@ -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 -} diff --git a/results.go b/results.go deleted file mode 100644 index d4ee9f0e867a..000000000000 --- a/results.go +++ /dev/null @@ -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 -} diff --git a/_gen.go b/types/_gen.go similarity index 100% rename from _gen.go rename to types/_gen.go diff --git a/types/decorators.go b/types/decorators.go new file mode 100644 index 000000000000..d75f57da2f1f --- /dev/null +++ b/types/decorators.go @@ -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) +} diff --git a/types/handler.go b/types/handler.go new file mode 100644 index 000000000000..ff10ced1c6e0 --- /dev/null +++ b/types/handler.go @@ -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 diff --git a/types/msg.go b/types/msg.go deleted file mode 100644 index d2fc6d155063..000000000000 --- a/types/msg.go +++ /dev/null @@ -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 -} diff --git a/types/results.go b/types/results.go new file mode 100644 index 000000000000..016206243708 --- /dev/null +++ b/types/results.go @@ -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 +} diff --git a/types/signature.go b/types/signature.go new file mode 100644 index 000000000000..a13dffb19d9f --- /dev/null +++ b/types/signature.go @@ -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 +} diff --git a/types/tx_msg.go b/types/tx_msg.go new file mode 100644 index 000000000000..dce71bff49e7 --- /dev/null +++ b/types/tx_msg.go @@ -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 +}