Start defining CreatePacket
This commit is contained in:
parent
715d573e1a
commit
91eb91b803
|
@ -11,6 +11,8 @@ import (
|
|||
var (
|
||||
errChainNotRegistered = fmt.Errorf("Chain not registered")
|
||||
errChainAlreadyExists = fmt.Errorf("Chain already exists")
|
||||
errNeedsIBCPermission = fmt.Errorf("Needs app-permission to send IBC")
|
||||
errCannotSetPermission = fmt.Errorf("Requesting invalid permission on IBC")
|
||||
// errNotMember = fmt.Errorf("Not a member")
|
||||
// errInsufficientSigs = fmt.Errorf("Not enough signatures")
|
||||
// errNoMembers = fmt.Errorf("No members specified")
|
||||
|
@ -23,12 +25,13 @@ var (
|
|||
IBCCodeUnknownHeight = abci.CodeType(1004)
|
||||
IBCCodeInvalidCommit = abci.CodeType(1005)
|
||||
IBCCodeInvalidProof = abci.CodeType(1006)
|
||||
IBCCodeInvalidCall = abci.CodeType(1007)
|
||||
)
|
||||
|
||||
func ErrNotRegistered(chainID string) error {
|
||||
return errors.WithMessage(chainID, errChainNotRegistered, IBCCodeChainNotRegistered)
|
||||
}
|
||||
func IsNotRegistetedErr(err error) bool {
|
||||
func IsNotRegisteredErr(err error) bool {
|
||||
return errors.IsSameError(errChainNotRegistered, err)
|
||||
}
|
||||
|
||||
|
@ -38,3 +41,17 @@ func ErrAlreadyRegistered(chainID string) error {
|
|||
func IsAlreadyRegistetedErr(err error) bool {
|
||||
return errors.IsSameError(errChainAlreadyExists, err)
|
||||
}
|
||||
|
||||
func ErrNeedsIBCPermission() error {
|
||||
return errors.WithCode(errNeedsIBCPermission, IBCCodeInvalidCall)
|
||||
}
|
||||
func IsNeedsIBCPermissionErr(err error) bool {
|
||||
return errors.IsSameError(errNeedsIBCPermission, err)
|
||||
}
|
||||
|
||||
func ErrCannotSetPermission() error {
|
||||
return errors.WithCode(errCannotSetPermission, IBCCodeInvalidCall)
|
||||
}
|
||||
func IsCannotSetPermissionErr(err error) bool {
|
||||
return errors.IsSameError(errCannotSetPermission, err)
|
||||
}
|
||||
|
|
|
@ -7,16 +7,27 @@ import (
|
|||
"github.com/tendermint/basecoin/state"
|
||||
)
|
||||
|
||||
// nolint
|
||||
const (
|
||||
// NameIBC is the name of this module
|
||||
NameIBC = "ibc"
|
||||
)
|
||||
|
||||
var (
|
||||
allowIBC = []byte{0x42, 0xbe, 0xef, 0x1}
|
||||
)
|
||||
|
||||
// AllowIBC is the special code that an app must set to
|
||||
// enable sending IBC packets for this app-type
|
||||
func AllowIBC(app string) basecoin.Actor {
|
||||
return basecoin.Actor{App: app, Address: allowIBC}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -45,6 +56,8 @@ func (h Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.
|
|||
return h.initSeed(ctx, store, t)
|
||||
case UpdateChainTx:
|
||||
return h.updateSeed(ctx, store, t)
|
||||
case CreatePacketTx:
|
||||
return h.createPacket(ctx, store, t)
|
||||
}
|
||||
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
||||
}
|
||||
|
@ -63,6 +76,8 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoi
|
|||
return h.initSeed(ctx, store, t)
|
||||
case UpdateChainTx:
|
||||
return h.updateSeed(ctx, store, t)
|
||||
case CreatePacketTx:
|
||||
return h.createPacket(ctx, store, t)
|
||||
}
|
||||
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
||||
}
|
||||
|
@ -106,3 +121,45 @@ func (h Handler) updateSeed(ctx basecoin.Context, store state.KVStore,
|
|||
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// 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,
|
||||
t CreatePacketTx) (res basecoin.Result, err error) {
|
||||
|
||||
// make sure the chain is registed
|
||||
dest := t.DestChain
|
||||
if !NewChainSet(store).Exists([]byte(dest)) {
|
||||
return res, ErrNotRegistered(dest)
|
||||
}
|
||||
|
||||
// make sure we have the special IBC permission
|
||||
mod, err := t.Tx.GetKind()
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if !ctx.HasPermission(AllowIBC(mod)) {
|
||||
return res, ErrNeedsIBCPermission()
|
||||
}
|
||||
|
||||
// start making the packet to send
|
||||
packet := Packet{
|
||||
DestChain: t.DestChain,
|
||||
Tx: t.Tx,
|
||||
Permissions: make([]basecoin.Actor, len(t.Permissions)),
|
||||
}
|
||||
|
||||
// make sure we have all the permissions we want to send
|
||||
for i, p := range t.Permissions {
|
||||
if !ctx.HasPermission(p) {
|
||||
return res, ErrCannotSetPermission()
|
||||
}
|
||||
// add the permission with the current ChainID
|
||||
packet.Permissions[i] = p
|
||||
packet.Permissions[i].ChainID = ctx.ChainID()
|
||||
}
|
||||
|
||||
// now add it to the output queue....
|
||||
// TODO: where to store, also set the sequence....
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ibc
|
||||
|
||||
import (
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/stack"
|
||||
"github.com/tendermint/basecoin/state"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
|
@ -47,3 +48,17 @@ func (c ChainSet) Register(chainID string, ourHeight uint64, theirHeight int) er
|
|||
c.Set.Set([]byte(chainID), data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Packet is a wrapped transaction and permission that we want to
|
||||
// send off to another chain.
|
||||
type Packet struct {
|
||||
DestChain string `json:"dest_chain"`
|
||||
Sequence int `json:"sequence"`
|
||||
Permissions []basecoin.Actor `json:"permissions"`
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
}
|
||||
|
||||
// Bytes returns a serialization of the Packet
|
||||
func (p Packet) Bytes() []byte {
|
||||
return wire.BinaryBytes(p)
|
||||
}
|
||||
|
|
|
@ -13,21 +13,21 @@ const (
|
|||
// 0x3? series for ibc
|
||||
ByteRegisterChain = byte(0x30)
|
||||
ByteUpdateChain = byte(0x31)
|
||||
BytePacketCreate = byte(0x32)
|
||||
BytePacketPost = byte(0x33)
|
||||
ByteCreatePacket = byte(0x32)
|
||||
BytePostPacket = byte(0x33)
|
||||
|
||||
TypeRegisterChain = NameIBC + "/register"
|
||||
TypeUpdateChain = NameIBC + "/update"
|
||||
TypePacketCreate = NameIBC + "/create"
|
||||
TypePacketPost = NameIBC + "/post"
|
||||
TypeCreatePacket = NameIBC + "/create"
|
||||
TypePostPacket = NameIBC + "/post"
|
||||
)
|
||||
|
||||
func init() {
|
||||
basecoin.TxMapper.
|
||||
RegisterImplementation(RegisterChainTx{}, TypeRegisterChain, ByteRegisterChain).
|
||||
RegisterImplementation(UpdateChainTx{}, TypeUpdateChain, ByteUpdateChain).
|
||||
RegisterImplementation(PacketCreateTx{}, TypePacketCreate, BytePacketCreate).
|
||||
RegisterImplementation(PacketPostTx{}, TypePacketPost, BytePacketPost)
|
||||
RegisterImplementation(CreatePacketTx{}, TypeCreatePacket, ByteCreatePacket).
|
||||
RegisterImplementation(PostPacketTx{}, TypePostPacket, BytePostPacket)
|
||||
}
|
||||
|
||||
// RegisterChainTx allows you to register a new chain on this blockchain
|
||||
|
@ -70,20 +70,21 @@ func (u UpdateChainTx) Wrap() basecoin.Tx {
|
|||
return basecoin.Tx{u}
|
||||
}
|
||||
|
||||
// PacketCreateTx is meant to be called by IPC, another module...
|
||||
// CreatePacketTx is meant to be called by IPC, another module...
|
||||
//
|
||||
// this is the tx that will be sent to another app and the permissions it
|
||||
// comes with (which must be a subset of the permissions on the current tx)
|
||||
//
|
||||
// TODO: how to control who can create packets (can I just signed create packet?)
|
||||
type PacketCreateTx struct {
|
||||
// If must have the special `AllowIBC` permission from the app
|
||||
// that can send this packet (so only coins can request SendTx packet)
|
||||
type CreatePacketTx struct {
|
||||
DestChain string `json:"dest_chain"`
|
||||
Permissions []basecoin.Actor `json:"permissions"`
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
}
|
||||
|
||||
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
||||
func (p PacketCreateTx) ValidateBasic() error {
|
||||
func (p CreatePacketTx) ValidateBasic() error {
|
||||
if p.DestChain == "" {
|
||||
return errors.ErrNoChain()
|
||||
}
|
||||
|
@ -94,27 +95,32 @@ func (p PacketCreateTx) ValidateBasic() error {
|
|||
}
|
||||
|
||||
// Wrap - used to satisfy TxInner
|
||||
func (p PacketCreateTx) Wrap() basecoin.Tx {
|
||||
func (p CreatePacketTx) Wrap() basecoin.Tx {
|
||||
return basecoin.Tx{p}
|
||||
}
|
||||
|
||||
// PacketPostTx takes a wrapped packet from another chain and
|
||||
// PostPacketTx takes a wrapped packet from another chain and
|
||||
// TODO!!!
|
||||
type PacketPostTx struct {
|
||||
// also think... which chains can relay packets???
|
||||
// right now, enforce that these packets are only sent directly,
|
||||
// not routed over the hub. add routing later.
|
||||
type PostPacketTx struct {
|
||||
// make sure we have this header...
|
||||
FromChainID string // The immediate source of the packet, not always Packet.SrcChainID
|
||||
FromChainHeight uint64 // The block height in which Packet was committed, to check Proof
|
||||
// this proof must match the header and the packet.Bytes()
|
||||
Proof *merkle.IAVLProof
|
||||
// Packet
|
||||
Packet Packet
|
||||
}
|
||||
|
||||
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
||||
func (p PacketPostTx) ValidateBasic() error {
|
||||
func (p PostPacketTx) ValidateBasic() error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wrap - used to satisfy TxInner
|
||||
func (p PacketPostTx) Wrap() basecoin.Tx {
|
||||
func (p PostPacketTx) Wrap() basecoin.Tx {
|
||||
return basecoin.Tx{p}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue