From 9ea34e9c8f4459ea477128ec8d62af91973406be Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 12 Jul 2017 16:53:07 +0200 Subject: [PATCH] Add CheckHandler as a helper --- stack/helpers.go | 60 ++++++++++++++++++++++++++++++++++++++++--- stack/helpers_test.go | 35 +++++++++++++++++++++++++ stack/helperware.go | 4 +-- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/stack/helpers.go b/stack/helpers.go index a3dd296e5f..a21c867fa3 100644 --- a/stack/helpers.go +++ b/stack/helpers.go @@ -18,14 +18,19 @@ const ( //nolint const ( - ByteRawTx = 0x1 - TypeRawTx = "raw" + ByteRawTx = 0xF0 + ByteCheckTx = 0xF1 + + TypeRawTx = "raw" + TypeCheckTx = NameCheck + "/tx" + rawMaxSize = 2000 * 1000 ) func init() { basecoin.TxMapper. - RegisterImplementation(RawTx{}, TypeRawTx, ByteRawTx) + RegisterImplementation(RawTx{}, TypeRawTx, ByteRawTx). + RegisterImplementation(CheckTx{}, TypeCheckTx, ByteCheckTx) } // RawTx just contains bytes that can be hex-ified @@ -49,6 +54,24 @@ func (r RawTx) ValidateBasic() error { return nil } +// CheckTx contains a list of permissions to be tested +type CheckTx struct { + Required []basecoin.Actor +} + +var _ basecoin.TxInner = CheckTx{} + +// nolint +func NewCheckTx(req []basecoin.Actor) basecoin.Tx { + return CheckTx{req}.Wrap() +} +func (c CheckTx) Wrap() basecoin.Tx { + return basecoin.Tx{c} +} +func (CheckTx) ValidateBasic() error { + return nil +} + // OKHandler just used to return okay to everything type OKHandler struct { Log string @@ -148,3 +171,34 @@ func (p PanicHandler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx ba } panic(p.Msg) } + +// CheckHandler accepts CheckTx and verifies the permissions +type CheckHandler struct { + PassOption +} + +// Name - return handler's name +func (CheckHandler) Name() string { + return NameCheck +} + +// CheckTx verifies the permissions +func (c CheckHandler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) { + check, ok := tx.Unwrap().(CheckTx) + if !ok { + return res, errors.ErrUnknownTxType(tx) + } + + for _, perm := range check.Required { + if !ctx.HasPermission(perm) { + return res, errors.ErrUnauthorized() + } + } + return res, nil +} + +// DeliverTx verifies the permissions +func (c CheckHandler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) { + // until something changes, just do the same as check + return c.CheckTx(ctx, store, tx) +} diff --git a/stack/helpers_test.go b/stack/helpers_test.go index 58748e054d..a45732c16b 100644 --- a/stack/helpers_test.go +++ b/stack/helpers_test.go @@ -62,3 +62,38 @@ func TestPanic(t *testing.T) { assert.Panics(func() { fail.CheckTx(ctx, store, tx) }) assert.Panics(func() { fail.DeliverTx(ctx, store, tx) }) } + +func TestCheck(t *testing.T) { + assert := assert.New(t) + + ctx := MockContext("check-chain", 123) + store := state.NewMemKVStore() + h := CheckHandler{} + + a := basecoin.Actor{App: "foo", Address: []byte("baz")} + b := basecoin.Actor{App: "si-ly", Address: []byte("bar")} + + cases := []struct { + valid bool + signers, required []basecoin.Actor + }{ + {true, []basecoin.Actor{a}, []basecoin.Actor{a}}, + {true, []basecoin.Actor{a, b}, []basecoin.Actor{a}}, + {false, []basecoin.Actor{a}, []basecoin.Actor{a, b}}, + {false, []basecoin.Actor{a}, []basecoin.Actor{b}}, + } + + for i, tc := range cases { + tx := CheckTx{tc.required}.Wrap() + myCtx := ctx.WithPermissions(tc.signers...) + _, err := h.CheckTx(myCtx, store, tx) + _, err2 := h.DeliverTx(myCtx, store, tx) + if tc.valid { + assert.Nil(err, "%d: %+v", i, err) + assert.Nil(err2, "%d: %+v", i, err2) + } else { + assert.NotNil(err, "%d", i) + assert.NotNil(err2, "%d", i) + } + } +} diff --git a/stack/helperware.go b/stack/helperware.go index adca481c6d..46cdfaa8cc 100644 --- a/stack/helperware.go +++ b/stack/helperware.go @@ -8,8 +8,8 @@ import ( ) const ( - NameCheck = "chck" - NameGrant = "grnt" + NameCheck = "check" + NameGrant = "grant" ) // CheckMiddleware returns an error if the tx doesn't have auth of this