From f4393511ee12ddbdd15dfc09e1bc3238a4846193 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 1 Jun 2017 20:01:19 +0200 Subject: [PATCH] First demo of handlers --- handler.go | 53 +++++++++++++++++++++++++++++++++++++++++ handlers/base.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 handler.go create mode 100644 handlers/base.go diff --git a/handler.go b/handler.go new file mode 100644 index 0000000000..704b2beee9 --- /dev/null +++ b/handler.go @@ -0,0 +1,53 @@ +package basecoin + +import ( + abci "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-wire/data" + + "github.com/tendermint/basecoin/types" +) + +// Handler is anything that processes a transaction +type Handler interface { + CheckTx(ctx Context, store types.KVStore, tx Tx) (Result, error) + DeliverTx(ctx Context, store types.KVStore, tx Tx) (Result, error) + + // TODO: flesh these out as well + // SetOption(store types.KVStore, key, value string) (log string) + // InitChain(store types.KVStore, vals []*abci.Validator) + // BeginBlock(store types.KVStore, hash []byte, header *abci.Header) + // EndBlock(store types.KVStore, height uint64) abci.ResponseEndBlock +} + +// TODO: Context is a place-holder, soon we add some request data here from the +// higher-levels (like tell an app who signed). +// Trust me, we will need it like CallContext now... +type Context struct { + sigs []crypto.PubKey +} + +// TOTALLY insecure. will redo later, but you get the point +func (c Context) AddSigners(keys ...crypto.PubKey) Context { + return Context{ + sigs: append(c.sigs, keys...), + } +} + +func (c Context) GetSigners() []crypto.PubKey { + return c.sigs +} + +// Result captures any non-error abci result +// to make sure people use error for error cases +type Result struct { + Data data.Bytes + Log string +} + +func (r Result) ToABCI() abci.Result { + return abci.Result{ + Data: r.Data, + Log: r.Log, + } +} diff --git a/handlers/base.go b/handlers/base.go new file mode 100644 index 0000000000..a9c0329037 --- /dev/null +++ b/handlers/base.go @@ -0,0 +1,61 @@ +package handlers + +import ( + crypto "github.com/tendermint/go-crypto" + + "github.com/tendermint/basecoin" + "github.com/tendermint/basecoin/errors" + "github.com/tendermint/basecoin/types" +) + +type SignedHandler struct { + AllowMultiSig bool + Inner basecoin.Handler +} + +func (h SignedHandler) Next() basecoin.Handler { + return h.Inner +} + +var _ basecoin.Handler = SignedHandler{} + +type Signed interface { + basecoin.TxLayer + Signers() ([]crypto.PubKey, error) +} + +func (h SignedHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) { + var sigs []crypto.PubKey + + stx, ok := tx.Unwrap().(Signed) + if !ok { + return res, errors.Unauthorized() + } + + sigs, err = stx.Signers() + if err != nil { + return res, err + } + + // add the signers to the context and continue + ctx2 := ctx.AddSigners(sigs...) + return h.Next().CheckTx(ctx2, store, stx.Next()) +} + +func (h SignedHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) { + var sigs []crypto.PubKey + + stx, ok := tx.Unwrap().(Signed) + if !ok { + return res, errors.Unauthorized() + } + + sigs, err = stx.Signers() + if err != nil { + return res, err + } + + // add the signers to the context and continue + ctx2 := ctx.AddSigners(sigs...) + return h.Next().DeliverTx(ctx2, store, stx.Next()) +}