Add Registrar permission to attaching chains

This commit is contained in:
Ethan Frey
2017-07-27 16:25:04 -04:00
parent 91eb91b803
commit 485ec80cca
3 changed files with 70 additions and 20 deletions
+48 -20
View File
@@ -1,6 +1,9 @@
package ibc
import (
"github.com/tendermint/go-wire/data"
"github.com/tendermint/tmlibs/log"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/stack"
@@ -10,6 +13,9 @@ import (
const (
// NameIBC is the name of this module
NameIBC = "ibc"
// OptionRegistrar is the option name to set the actor
// to handle ibc chain registration
OptionRegistrar = "registrar"
)
var (
@@ -23,29 +29,44 @@ func AllowIBC(app string) basecoin.Actor {
}
// Handler allows us to update the chain state or create a packet
//
// TODO: require auth for registration, the authorized actor (or role)
// should be defined in the handler, and set via SetOption
type Handler struct {
// TODO: add option to set who can permit registration and store it
basecoin.NopOption
Registrar basecoin.Actor
}
var _ basecoin.Handler = Handler{}
var _ basecoin.Handler = &Handler{}
// NewHandler makes a role handler to create roles
func NewHandler() Handler {
return Handler{}
// NewHandler makes a Handler that allows all chains to connect via IBC.
// Set a Registrar via SetOption to restrict it.
func NewHandler() *Handler {
return new(Handler)
}
// Name - return name space
func (Handler) Name() string {
func (*Handler) Name() string {
return NameIBC
}
// SetOption - sets the registrar for IBC
func (h *Handler) SetOption(l log.Logger, store state.KVStore, module, key, value string) (log string, err error) {
if module != NameIBC {
return "", errors.ErrUnknownModule(module)
}
if key == OptionRegistrar {
var act basecoin.Actor
err = data.FromJSON([]byte(value), &act)
if err != nil {
return "", err
}
h.Registrar = act
// TODO: save/load from disk!
return "Success", nil
}
return "", errors.ErrUnknownKey(key)
}
// CheckTx verifies the packet is formated correctly, and has the proper sequence
// for a registered chain
func (h Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
func (h *Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
err = tx.ValidateBasic()
if err != nil {
return res, err
@@ -64,7 +85,7 @@ func (h Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.
// DeliverTx verifies all signatures on the tx and updated the chain state
// apropriately
func (h Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
func (h *Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx) (res basecoin.Result, err error) {
err = tx.ValidateBasic()
if err != nil {
return res, err
@@ -72,7 +93,6 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoi
switch t := tx.Unwrap().(type) {
case RegisterChainTx:
// TODO: do we want some permissioning for this???
return h.initSeed(ctx, store, t)
case UpdateChainTx:
return h.updateSeed(ctx, store, t)
@@ -82,10 +102,19 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoi
return res, errors.ErrUnknownTxType(tx.Unwrap())
}
// initSeed imports the first seed for this chain and accepts it as the root of trust
func (h Handler) initSeed(ctx basecoin.Context, store state.KVStore,
// initSeed imports the first seed for this chain and
// accepts it as the root of trust.
//
// only the registrar, if set, is allowed to do this
func (h *Handler) initSeed(ctx basecoin.Context, store state.KVStore,
t RegisterChainTx) (res basecoin.Result, err error) {
// check permission to attach
// nothing set, means anyone can connect
if !h.Registrar.Empty() && !ctx.HasPermission(h.Registrar) {
return res, errors.ErrUnauthorized()
}
chainID := t.ChainID()
s := NewChainSet(store)
err = s.Register(chainID, ctx.BlockHeight(), t.Seed.Height())
@@ -101,7 +130,7 @@ func (h Handler) initSeed(ctx basecoin.Context, store state.KVStore,
// updateSeed checks the seed against the existing chain data and rejects it if it
// doesn't fit (or no chain data)
func (h Handler) updateSeed(ctx basecoin.Context, store state.KVStore,
func (h *Handler) updateSeed(ctx basecoin.Context, store state.KVStore,
t UpdateChainTx) (res basecoin.Result, err error) {
chainID := t.ChainID()
@@ -124,7 +153,7 @@ func (h Handler) updateSeed(ctx basecoin.Context, store state.KVStore,
// createPacket makes sure all permissions are good and the destination
// chain is registed. If so, it appends it to the outgoing queue
func (h Handler) createPacket(ctx basecoin.Context, store state.KVStore,
func (h *Handler) createPacket(ctx basecoin.Context, store state.KVStore,
t CreatePacketTx) (res basecoin.Result, err error) {
// make sure the chain is registed
@@ -134,7 +163,7 @@ func (h Handler) createPacket(ctx basecoin.Context, store state.KVStore,
}
// make sure we have the special IBC permission
mod, err := t.Tx.GetKind()
mod, err := t.Tx.GetMod()
if err != nil {
return res, err
}
@@ -155,8 +184,7 @@ func (h Handler) createPacket(ctx basecoin.Context, store state.KVStore,
return res, ErrCannotSetPermission()
}
// add the permission with the current ChainID
packet.Permissions[i] = p
packet.Permissions[i].ChainID = ctx.ChainID()
packet.Permissions[i] = p.WithChain(ctx.ChainID())
}
// now add it to the output queue....