Add CheckHandler as a helper

This commit is contained in:
Ethan Frey 2017-07-12 16:53:07 +02:00
parent 7e7f124bc9
commit 9ea34e9c8f
3 changed files with 94 additions and 5 deletions

View File

@ -18,14 +18,19 @@ const (
//nolint //nolint
const ( const (
ByteRawTx = 0x1 ByteRawTx = 0xF0
ByteCheckTx = 0xF1
TypeRawTx = "raw" TypeRawTx = "raw"
TypeCheckTx = NameCheck + "/tx"
rawMaxSize = 2000 * 1000 rawMaxSize = 2000 * 1000
) )
func init() { func init() {
basecoin.TxMapper. basecoin.TxMapper.
RegisterImplementation(RawTx{}, TypeRawTx, ByteRawTx) RegisterImplementation(RawTx{}, TypeRawTx, ByteRawTx).
RegisterImplementation(CheckTx{}, TypeCheckTx, ByteCheckTx)
} }
// RawTx just contains bytes that can be hex-ified // RawTx just contains bytes that can be hex-ified
@ -49,6 +54,24 @@ func (r RawTx) ValidateBasic() error {
return nil 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 // OKHandler just used to return okay to everything
type OKHandler struct { type OKHandler struct {
Log string Log string
@ -148,3 +171,34 @@ func (p PanicHandler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx ba
} }
panic(p.Msg) 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)
}

View File

@ -62,3 +62,38 @@ func TestPanic(t *testing.T) {
assert.Panics(func() { fail.CheckTx(ctx, store, tx) }) assert.Panics(func() { fail.CheckTx(ctx, store, tx) })
assert.Panics(func() { fail.DeliverTx(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)
}
}
}

View File

@ -8,8 +8,8 @@ import (
) )
const ( const (
NameCheck = "chck" NameCheck = "check"
NameGrant = "grnt" NameGrant = "grant"
) )
// CheckMiddleware returns an error if the tx doesn't have auth of this // CheckMiddleware returns an error if the tx doesn't have auth of this