Unify CheckTx and DeliverTx (#286)

Unify CheckTx and DeliverTx
This commit is contained in:
Jae Kwon
2017-12-03 21:25:37 -08:00
committed by GitHub
parent 8c250cc840
commit a2a1151a4f
9 changed files with 146 additions and 202 deletions
+42 -29
View File
@@ -2,46 +2,39 @@ package types
import (
"context"
tm "github.com/tendermint/tendermint/types"
abci "github.com/tendermint/abci/types"
)
/*
NOTE: Golang's Context is embedded and relied on
for compatibility w/ tools like monkit.
(https://github.com/spacemonkeygo/monkit)
Usage:
defer mon.Task()(&ctx.Context)(&err)
*/
type SDKContext struct {
type Context struct {
context.Context
// NOTE: adding fields here will break monkit compatibility
// use context.Context instead if possible.
// Don't add any other fields here,
// it's probably not what you want to do.
}
func NewSDKContext(header tm.Header) SDKContext {
c := SDKContext{
func NewContext(header tm.Header, isCheckTx bool, txBytes []byte) Context {
c := Context{
Context: context.Background(),
}
c = c.setBlockHeader(header)
c = c.setBlockHeight(int64(header.Height))
c = c.setChainID(header.ChainID)
c = c.setIsCheckTx(isCheckTx)
c = c.setTxBytes(txBytes)
return c
}
func (c SDKContext) WithValueSDK(key interface{}, value interface{}) SDKContext {
return SDKContext{
// The original context.Context API.
func (c Context) WithValue(key interface{}, value interface{}) context.Context {
return context.WithValue(c.Context, key, value)
}
// Like WithValue() but retains this API.
func (c Context) WithValueSDK(key interface{}, value interface{}) Context {
return Context{
Context: context.WithValue(c.Context, key, value),
}
}
func (c SDKContext) WithValue(key interface{}, value interface{}) Context {
return c
}
//----------------------------------------
// Our extensions
@@ -51,31 +44,51 @@ const (
contextKeyBlockHeader contextKey = iota
contextKeyBlockHeight
contextKeyChainID
contextKeyIsCheckTx
contextKeyTxBytes
)
func (c SDKContext) BlockHeader() tm.Header {
func (c Context) BlockHeader() tm.Header {
return c.Value(contextKeyBlockHeader).(tm.Header)
}
func (c SDKContext) BlockHeight() int64 {
func (c Context) BlockHeight() int64 {
return c.Value(contextKeyBlockHeight).(int64)
}
func (c SDKContext) ChainID() string {
func (c Context) ChainID() string {
return c.Value(contextKeyChainID).(string)
}
func (c Context) IsCheckTx() bool {
return c.Value(contextKeyIsCheckTx).(bool)
}
func (c Context) TxBytes() []byte {
return c.Value(contextKeyTxBytes).([]byte)
}
// Unexposed to prevent overriding.
func (c SDKContext) setBlockHeader(header tm.Header) SDKContext {
func (c Context) setBlockHeader(header tm.Header) Context {
return c.WithValueSDK(contextKeyBlockHeader, header)
}
// Unexposed to prevent overriding.
func (c SDKContext) setBlockHeight(height int64) SDKContext {
func (c Context) setBlockHeight(height int64) Context {
return c.WithValueSDK(contextKeyBlockHeight, header)
}
// Unexposed to prevent overriding.
func (c SDKContext) setChainID(chainID string) SDKContext {
func (c Context) setChainID(chainID string) Context {
return c.WithValueSDK(contextKeyChainID, header)
}
// Unexposed to prevent overriding.
func (c Context) setIsCheckTx(isCheckTx bool) Context {
return c.WithValueSDK(contextKeyIsCheckTx, isCheckTx)
}
// Unexposed to prevent overriding.
func (c Context) setTxBytes(txBytes []byte) Context {
return c.WithValueSDK(contextKeyTxBytes, txBytes)
}
+5 -35
View File
@@ -1,22 +1,12 @@
package types
// A Decorator executes before/during/after a handler to enhance functionality.
type Decorator interface {
type Decorator func(ctx Context, ms MultiStore, tx Tx, next Handler) Result
// 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.
// Return a decorated handler
func Decorate(dec Decorator, next Handler) Handler {
return &decHandler{
decorator: dec,
next: next,
return func(ctx Context, ms MultiStore, tx Tx) Result {
return dec(ctx, ms, tx, next)
}
}
@@ -62,25 +52,5 @@ 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)
return Decorate(stack[0], build(stack[1:], end))
}
+4 -19
View File
@@ -1,24 +1,9 @@
package types
import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/tmlibs/log"
"github.com/cosmos/cosmos-sdk"
)
// 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
// Handler handles both ABCI DeliverTx and CheckTx requests.
// Iff ABCI.CheckTx, ctx.IsCheckTx() returns true.
type Handler func(ctx Context, ms MultiStore, tx Tx)
+39
View File
@@ -0,0 +1,39 @@
package types
import (
abci "github.com/tendermint/abci/types"
)
type KVPair struct {
Key []byte
Value []byte
}
// Result is the union of ResponseDeliverTx and ResponseCheckTx.
type Result struct {
// Code is the response code, is stored back on the chain.
Code uint32
// Data is any data returned from the app.
Data []byte
// Log is just debug information. NOTE: nondeterministic.
Log string
// GasAllocated is the maximum units of work we allow this tx to perform.
GasAllocated int64
// GasUsed is the amount of gas actually consumed. NOTE: not used.
GasUsed int64
// Tx fee amount and denom.
FeeAmount int64
FeeDenom string
// Changes to the validator set.
ValSetDiff []abci.Validator
// Tags are used for transaction indexing and pubsub.
Tags []KVPair
}
-29
View File
@@ -1,29 +0,0 @@
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
}
-2
View File
@@ -34,5 +34,3 @@ type Tx interface {
// .Empty().
Signatures() []Signature
}
type TxParser func(txBytes []byte) (Tx, error)