Start defining CreatePacket
This commit is contained in:
parent
715d573e1a
commit
91eb91b803
|
@ -9,8 +9,10 @@ import (
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
var (
|
var (
|
||||||
errChainNotRegistered = fmt.Errorf("Chain not registered")
|
errChainNotRegistered = fmt.Errorf("Chain not registered")
|
||||||
errChainAlreadyExists = fmt.Errorf("Chain already exists")
|
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")
|
// errNotMember = fmt.Errorf("Not a member")
|
||||||
// errInsufficientSigs = fmt.Errorf("Not enough signatures")
|
// errInsufficientSigs = fmt.Errorf("Not enough signatures")
|
||||||
// errNoMembers = fmt.Errorf("No members specified")
|
// errNoMembers = fmt.Errorf("No members specified")
|
||||||
|
@ -23,12 +25,13 @@ var (
|
||||||
IBCCodeUnknownHeight = abci.CodeType(1004)
|
IBCCodeUnknownHeight = abci.CodeType(1004)
|
||||||
IBCCodeInvalidCommit = abci.CodeType(1005)
|
IBCCodeInvalidCommit = abci.CodeType(1005)
|
||||||
IBCCodeInvalidProof = abci.CodeType(1006)
|
IBCCodeInvalidProof = abci.CodeType(1006)
|
||||||
|
IBCCodeInvalidCall = abci.CodeType(1007)
|
||||||
)
|
)
|
||||||
|
|
||||||
func ErrNotRegistered(chainID string) error {
|
func ErrNotRegistered(chainID string) error {
|
||||||
return errors.WithMessage(chainID, errChainNotRegistered, IBCCodeChainNotRegistered)
|
return errors.WithMessage(chainID, errChainNotRegistered, IBCCodeChainNotRegistered)
|
||||||
}
|
}
|
||||||
func IsNotRegistetedErr(err error) bool {
|
func IsNotRegisteredErr(err error) bool {
|
||||||
return errors.IsSameError(errChainNotRegistered, err)
|
return errors.IsSameError(errChainNotRegistered, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,3 +41,17 @@ func ErrAlreadyRegistered(chainID string) error {
|
||||||
func IsAlreadyRegistetedErr(err error) bool {
|
func IsAlreadyRegistetedErr(err error) bool {
|
||||||
return errors.IsSameError(errChainAlreadyExists, err)
|
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"
|
"github.com/tendermint/basecoin/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint
|
|
||||||
const (
|
const (
|
||||||
|
// NameIBC is the name of this module
|
||||||
NameIBC = "ibc"
|
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
|
// Handler allows us to update the chain state or create a packet
|
||||||
//
|
//
|
||||||
// TODO: require auth for registration, the authorized actor (or role)
|
// TODO: require auth for registration, the authorized actor (or role)
|
||||||
// should be defined in the handler, and set via SetOption
|
// should be defined in the handler, and set via SetOption
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
// TODO: add option to set who can permit registration and store it
|
||||||
basecoin.NopOption
|
basecoin.NopOption
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +56,8 @@ func (h Handler) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.
|
||||||
return h.initSeed(ctx, store, t)
|
return h.initSeed(ctx, store, t)
|
||||||
case UpdateChainTx:
|
case UpdateChainTx:
|
||||||
return h.updateSeed(ctx, store, t)
|
return h.updateSeed(ctx, store, t)
|
||||||
|
case CreatePacketTx:
|
||||||
|
return h.createPacket(ctx, store, t)
|
||||||
}
|
}
|
||||||
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
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)
|
return h.initSeed(ctx, store, t)
|
||||||
case UpdateChainTx:
|
case UpdateChainTx:
|
||||||
return h.updateSeed(ctx, store, t)
|
return h.updateSeed(ctx, store, t)
|
||||||
|
case CreatePacketTx:
|
||||||
|
return h.createPacket(ctx, store, t)
|
||||||
}
|
}
|
||||||
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
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)
|
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||||
return res, err
|
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
|
package ibc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/tendermint/basecoin"
|
||||||
"github.com/tendermint/basecoin/stack"
|
"github.com/tendermint/basecoin/stack"
|
||||||
"github.com/tendermint/basecoin/state"
|
"github.com/tendermint/basecoin/state"
|
||||||
wire "github.com/tendermint/go-wire"
|
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)
|
c.Set.Set([]byte(chainID), data)
|
||||||
return nil
|
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
|
// 0x3? series for ibc
|
||||||
ByteRegisterChain = byte(0x30)
|
ByteRegisterChain = byte(0x30)
|
||||||
ByteUpdateChain = byte(0x31)
|
ByteUpdateChain = byte(0x31)
|
||||||
BytePacketCreate = byte(0x32)
|
ByteCreatePacket = byte(0x32)
|
||||||
BytePacketPost = byte(0x33)
|
BytePostPacket = byte(0x33)
|
||||||
|
|
||||||
TypeRegisterChain = NameIBC + "/register"
|
TypeRegisterChain = NameIBC + "/register"
|
||||||
TypeUpdateChain = NameIBC + "/update"
|
TypeUpdateChain = NameIBC + "/update"
|
||||||
TypePacketCreate = NameIBC + "/create"
|
TypeCreatePacket = NameIBC + "/create"
|
||||||
TypePacketPost = NameIBC + "/post"
|
TypePostPacket = NameIBC + "/post"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
basecoin.TxMapper.
|
basecoin.TxMapper.
|
||||||
RegisterImplementation(RegisterChainTx{}, TypeRegisterChain, ByteRegisterChain).
|
RegisterImplementation(RegisterChainTx{}, TypeRegisterChain, ByteRegisterChain).
|
||||||
RegisterImplementation(UpdateChainTx{}, TypeUpdateChain, ByteUpdateChain).
|
RegisterImplementation(UpdateChainTx{}, TypeUpdateChain, ByteUpdateChain).
|
||||||
RegisterImplementation(PacketCreateTx{}, TypePacketCreate, BytePacketCreate).
|
RegisterImplementation(CreatePacketTx{}, TypeCreatePacket, ByteCreatePacket).
|
||||||
RegisterImplementation(PacketPostTx{}, TypePacketPost, BytePacketPost)
|
RegisterImplementation(PostPacketTx{}, TypePostPacket, BytePostPacket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterChainTx allows you to register a new chain on this blockchain
|
// 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}
|
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
|
// 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)
|
// 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?)
|
// If must have the special `AllowIBC` permission from the app
|
||||||
type PacketCreateTx struct {
|
// that can send this packet (so only coins can request SendTx packet)
|
||||||
|
type CreatePacketTx struct {
|
||||||
DestChain string `json:"dest_chain"`
|
DestChain string `json:"dest_chain"`
|
||||||
Permissions []basecoin.Actor `json:"permissions"`
|
Permissions []basecoin.Actor `json:"permissions"`
|
||||||
Tx basecoin.Tx `json:"tx"`
|
Tx basecoin.Tx `json:"tx"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
||||||
func (p PacketCreateTx) ValidateBasic() error {
|
func (p CreatePacketTx) ValidateBasic() error {
|
||||||
if p.DestChain == "" {
|
if p.DestChain == "" {
|
||||||
return errors.ErrNoChain()
|
return errors.ErrNoChain()
|
||||||
}
|
}
|
||||||
|
@ -94,27 +95,32 @@ func (p PacketCreateTx) ValidateBasic() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap - used to satisfy TxInner
|
// Wrap - used to satisfy TxInner
|
||||||
func (p PacketCreateTx) Wrap() basecoin.Tx {
|
func (p CreatePacketTx) Wrap() basecoin.Tx {
|
||||||
return basecoin.Tx{p}
|
return basecoin.Tx{p}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PacketPostTx takes a wrapped packet from another chain and
|
// PostPacketTx takes a wrapped packet from another chain and
|
||||||
// TODO!!!
|
// 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
|
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
|
FromChainHeight uint64 // The block height in which Packet was committed, to check Proof
|
||||||
Proof *merkle.IAVLProof
|
// this proof must match the header and the packet.Bytes()
|
||||||
// Packet
|
Proof *merkle.IAVLProof
|
||||||
|
Packet Packet
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
|
||||||
func (p PacketPostTx) ValidateBasic() error {
|
func (p PostPacketTx) ValidateBasic() error {
|
||||||
// TODO
|
// TODO
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap - used to satisfy TxInner
|
// Wrap - used to satisfy TxInner
|
||||||
func (p PacketPostTx) Wrap() basecoin.Tx {
|
func (p PostPacketTx) Wrap() basecoin.Tx {
|
||||||
return basecoin.Tx{p}
|
return basecoin.Tx{p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue