Add roles middleware and handler
This commit is contained in:
parent
3e52e6b959
commit
11a8c0d9a2
|
@ -22,6 +22,7 @@ var (
|
||||||
errInvalidFormat = fmt.Errorf("Invalid format")
|
errInvalidFormat = fmt.Errorf("Invalid format")
|
||||||
errUnknownModule = fmt.Errorf("Unknown module")
|
errUnknownModule = fmt.Errorf("Unknown module")
|
||||||
errExpired = fmt.Errorf("Tx expired")
|
errExpired = fmt.Errorf("Tx expired")
|
||||||
|
errUnknownKey = fmt.Errorf("Unknown key")
|
||||||
)
|
)
|
||||||
|
|
||||||
// some crazy reflection to unwrap any generated struct.
|
// some crazy reflection to unwrap any generated struct.
|
||||||
|
@ -63,6 +64,14 @@ func IsUnknownModuleErr(err error) bool {
|
||||||
return IsSameError(errUnknownModule, err)
|
return IsSameError(errUnknownModule, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ErrUnknownKey(mod string) TMError {
|
||||||
|
w := errors.Wrap(errUnknownKey, mod)
|
||||||
|
return WithCode(w, abci.CodeType_UnknownRequest)
|
||||||
|
}
|
||||||
|
func IsUnknownKeyErr(err error) bool {
|
||||||
|
return IsSameError(errUnknownKey, err)
|
||||||
|
}
|
||||||
|
|
||||||
func ErrInternal(msg string) TMError {
|
func ErrInternal(msg string) TMError {
|
||||||
return New(msg, abci.CodeType_InternalError)
|
return New(msg, abci.CodeType_InternalError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package coin
|
package coin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/tendermint/go-wire/data"
|
"github.com/tendermint/go-wire/data"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
|
||||||
|
@ -106,8 +104,7 @@ func (h Handler) SetOption(l log.Logger, store state.KVStore, module, key, value
|
||||||
return "Success", nil
|
return "Success", nil
|
||||||
|
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("Unknown key: %s", key)
|
return errors.ErrUnknownKey(key)
|
||||||
return "", errors.ErrInternal(msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (send SendTx, err error) {
|
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (send SendTx, err error) {
|
||||||
|
|
|
@ -1,4 +1,63 @@
|
||||||
package roles
|
package roles
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
|
||||||
|
"github.com/tendermint/basecoin"
|
||||||
|
"github.com/tendermint/basecoin/errors"
|
||||||
|
"github.com/tendermint/basecoin/state"
|
||||||
|
)
|
||||||
|
|
||||||
//NameRole - name space of the roles module
|
//NameRole - name space of the roles module
|
||||||
const NameRole = "role"
|
const NameRole = "role"
|
||||||
|
|
||||||
|
type Handler struct{}
|
||||||
|
|
||||||
|
var _ basecoin.Handler = Handler{}
|
||||||
|
|
||||||
|
// NewHandler makes a role handler to create roles
|
||||||
|
func NewHandler() Handler {
|
||||||
|
return Handler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name - return name space
|
||||||
|
func (Handler) Name() string {
|
||||||
|
return NameRole
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx checks if there is enough money in the account
|
||||||
|
func (h Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
|
||||||
|
_, err = checkTx(ctx, tx)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx moves the money
|
||||||
|
func (h Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
|
||||||
|
create, err := checkTx(ctx, tx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// lets try...
|
||||||
|
role := NewRole(create.MinSigs, create.Signers)
|
||||||
|
err = createRole(store, MakeKey(create.Role), role)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOption - sets the genesis account balance
|
||||||
|
func (h Handler) SetOption(l log.Logger, store state.KVStore, module, key, value string) (log string, err error) {
|
||||||
|
if module != NameRole {
|
||||||
|
return "", errors.ErrUnknownModule(module)
|
||||||
|
}
|
||||||
|
return "", errors.ErrUnknownKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (create CreateRoleTx, err error) {
|
||||||
|
// check if the tx is proper type and valid
|
||||||
|
create, ok := tx.Unwrap().(CreateRoleTx)
|
||||||
|
if !ok {
|
||||||
|
return create, errors.ErrInvalidFormat(tx)
|
||||||
|
}
|
||||||
|
err = create.ValidateBasic()
|
||||||
|
return create, err
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,81 @@
|
||||||
package roles
|
package roles
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/basecoin"
|
||||||
|
"github.com/tendermint/basecoin/errors"
|
||||||
|
"github.com/tendermint/basecoin/stack"
|
||||||
|
"github.com/tendermint/basecoin/state"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Middleware struct {
|
||||||
|
stack.PassOption
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ stack.Middleware = Middleware{}
|
||||||
|
|
||||||
|
func NewMiddleware() Middleware {
|
||||||
|
return Middleware{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name - return name space
|
||||||
|
func (Middleware) Name() string {
|
||||||
|
return NameRole
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx checks if this is valid
|
||||||
|
func (m Middleware) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Checker) (res basecoin.Result, err error) {
|
||||||
|
assume, err := checkMiddleTx(ctx, tx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err = assumeRole(ctx, store, assume)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return next.CheckTx(ctx, store, assume.Tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx moves the money
|
||||||
|
func (m Middleware) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.Result, err error) {
|
||||||
|
assume, err := checkMiddleTx(ctx, tx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err = assumeRole(ctx, store, assume)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return next.DeliverTx(ctx, store, assume.Tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkMiddleTx(ctx basecoin.Context, tx basecoin.Tx) (assume AssumeRoleTx, err error) {
|
||||||
|
// check if the tx is proper type and valid
|
||||||
|
assume, ok := tx.Unwrap().(AssumeRoleTx)
|
||||||
|
if !ok {
|
||||||
|
return assume, errors.ErrInvalidFormat(tx)
|
||||||
|
}
|
||||||
|
err = assume.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return assume, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// load it up and check it out...
|
||||||
|
return assume, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func assumeRole(ctx basecoin.Context, store state.KVStore, assume AssumeRoleTx) (basecoin.Context, error) {
|
||||||
|
role, err := loadRole(store, MakeKey(assume.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !role.IsAuthorized(ctx) {
|
||||||
|
return nil, ErrInsufficientSigs()
|
||||||
|
}
|
||||||
|
ctx = ctx.WithPermissions(NewPerm(assume.Role))
|
||||||
|
return ctx, nil
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,13 @@ import (
|
||||||
wire "github.com/tendermint/go-wire"
|
wire "github.com/tendermint/go-wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewPerm(role []byte) basecoin.Actor {
|
||||||
|
return basecoin.Actor{
|
||||||
|
App: NameRole,
|
||||||
|
Address: role,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Role - structure to hold permissioning
|
// Role - structure to hold permissioning
|
||||||
type Role struct {
|
type Role struct {
|
||||||
MinSigs uint32 `json:"min_sigs"`
|
MinSigs uint32 `json:"min_sigs"`
|
||||||
|
|
Loading…
Reference in New Issue