Implement register and update headers as handler
This commit is contained in:
parent
8747bd5a8b
commit
9c1e695d46
|
@ -1 +1,40 @@
|
||||||
package ibc
|
package ibc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/basecoin/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
errChainNotRegistered = fmt.Errorf("Chain not registered")
|
||||||
|
errChainAlreadyExists = fmt.Errorf("Chain already exists")
|
||||||
|
// errNotMember = fmt.Errorf("Not a member")
|
||||||
|
// errInsufficientSigs = fmt.Errorf("Not enough signatures")
|
||||||
|
// errNoMembers = fmt.Errorf("No members specified")
|
||||||
|
// errTooManyMembers = fmt.Errorf("Too many members specified")
|
||||||
|
// errNotEnoughMembers = fmt.Errorf("Not enough members specified")
|
||||||
|
|
||||||
|
IBCCodeChainNotRegistered = abci.CodeType(1001)
|
||||||
|
IBCCodeChainAlreadyExists = abci.CodeType(1002)
|
||||||
|
IBCCodePacketAlreadyExists = abci.CodeType(1003)
|
||||||
|
IBCCodeUnknownHeight = abci.CodeType(1004)
|
||||||
|
IBCCodeInvalidCommit = abci.CodeType(1005)
|
||||||
|
IBCCodeInvalidProof = abci.CodeType(1006)
|
||||||
|
)
|
||||||
|
|
||||||
|
func ErrNotRegistered(chainID string) error {
|
||||||
|
return errors.WithMessage(chainID, errChainNotRegistered, IBCCodeChainNotRegistered)
|
||||||
|
}
|
||||||
|
func IsNotRegistetedErr(err error) bool {
|
||||||
|
return errors.IsSameError(errChainNotRegistered, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrAlreadyRegistered(chainID string) error {
|
||||||
|
return errors.WithMessage(chainID, errChainAlreadyExists, IBCCodeChainAlreadyExists)
|
||||||
|
}
|
||||||
|
func IsAlreadyRegistetedErr(err error) bool {
|
||||||
|
return errors.IsSameError(errChainAlreadyExists, err)
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package ibc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/basecoin"
|
"github.com/tendermint/basecoin"
|
||||||
|
"github.com/tendermint/basecoin/errors"
|
||||||
|
"github.com/tendermint/basecoin/stack"
|
||||||
"github.com/tendermint/basecoin/state"
|
"github.com/tendermint/basecoin/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,11 +32,73 @@ func (Handler) Name() string {
|
||||||
// CheckTx verifies the packet is formated correctly, and has the proper sequence
|
// CheckTx verifies the packet is formated correctly, and has the proper sequence
|
||||||
// for a registered chain
|
// 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) {
|
||||||
return res, nil
|
err = tx.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := tx.Unwrap().(type) {
|
||||||
|
case RegisterChainTx:
|
||||||
|
return h.initSeed(ctx, store, t)
|
||||||
|
case UpdateChainTx:
|
||||||
|
return h.updateSeed(ctx, store, t)
|
||||||
|
}
|
||||||
|
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeliverTx verifies all signatures on the tx and updated the chain state
|
// DeliverTx verifies all signatures on the tx and updated the chain state
|
||||||
// apropriately
|
// 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) {
|
||||||
return res, nil
|
err = tx.ValidateBasic()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := tx.Unwrap().(type) {
|
||||||
|
case RegisterChainTx:
|
||||||
|
return h.initSeed(ctx, store, t)
|
||||||
|
case UpdateChainTx:
|
||||||
|
return h.updateSeed(ctx, store, t)
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
t RegisterChainTx) (res basecoin.Result, err error) {
|
||||||
|
|
||||||
|
chainID := t.ChainID()
|
||||||
|
s := NewChainSet(store)
|
||||||
|
err = s.Register(chainID, ctx.BlockHeight(), t.Seed.Height())
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
space := stack.PrefixedStore(chainID, store)
|
||||||
|
provider := newDBProvider(space)
|
||||||
|
err = provider.StoreSeed(t.Seed)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
t UpdateChainTx) (res basecoin.Result, err error) {
|
||||||
|
|
||||||
|
chainID := t.ChainID()
|
||||||
|
if !NewChainSet(store).Exists([]byte(chainID)) {
|
||||||
|
return res, ErrNotRegistered(chainID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the certifier for this chain
|
||||||
|
seed := t.Seed
|
||||||
|
space := stack.PrefixedStore(chainID, store)
|
||||||
|
cert, err := newCertifier(space, chainID, seed.Height())
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// this will import the seed if it is valid in the current context
|
||||||
|
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,22 @@ const (
|
||||||
prefixPacket = "p"
|
prefixPacket = "p"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newCertifier loads up the current state of this chain to make a proper
|
// newCertifier loads up the current state of this chain to make a proper certifier
|
||||||
func newCertifier(chainID string, store state.KVStore) (*certifiers.InquiringCertifier, error) {
|
// it will load the most recent height before block h if h is positive
|
||||||
|
// if h < 0, it will load the latest height
|
||||||
|
func newCertifier(store state.KVStore, chainID string, h int) (*certifiers.InquiringCertifier, error) {
|
||||||
// each chain has their own prefixed subspace
|
// each chain has their own prefixed subspace
|
||||||
space := stack.PrefixedStore(chainID, store)
|
p := newDBProvider(store)
|
||||||
p := newDBProvider(space)
|
|
||||||
|
|
||||||
// this gets the most recent verified seed
|
var seed certifiers.Seed
|
||||||
seed, err := certifiers.LatestSeed(p)
|
var err error
|
||||||
|
if h > 0 {
|
||||||
|
// this gets the most recent verified seed below the specified height
|
||||||
|
seed, err = p.GetByHeight(h)
|
||||||
|
} else {
|
||||||
|
// 0 or negative means start at latest seed
|
||||||
|
seed, err = certifiers.LatestSeed(p)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,49 @@
|
||||||
package ibc
|
package ibc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/basecoin/stack"
|
||||||
|
"github.com/tendermint/basecoin/state"
|
||||||
|
wire "github.com/tendermint/go-wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// this is the prefix for the list of chains
|
||||||
|
// we otherwise use the chainid as prefix, so this must not be an
|
||||||
|
// alpha-numeric byte
|
||||||
|
prefixChains = "**"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChainInfo is the global info we store for each registered chain,
|
||||||
|
// besides the headers, proofs, and packets
|
||||||
|
type ChainInfo struct {
|
||||||
|
RegisteredAt uint64 `json:"registered_at"`
|
||||||
|
RemoteBlock int `json:"remote_block"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainSet is the set of all registered chains
|
||||||
|
type ChainSet struct {
|
||||||
|
*state.Set
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewChainSet loads or initialized the ChainSet
|
||||||
|
func NewChainSet(store state.KVStore) ChainSet {
|
||||||
|
space := stack.PrefixedStore(prefixChains, store)
|
||||||
|
return ChainSet{
|
||||||
|
Set: state.NewSet(space),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register adds the named chain with some info
|
||||||
|
// returns error if already present
|
||||||
|
func (c ChainSet) Register(chainID string, ourHeight uint64, theirHeight int) error {
|
||||||
|
if c.Exists([]byte(chainID)) {
|
||||||
|
return ErrAlreadyRegistered(chainID)
|
||||||
|
}
|
||||||
|
info := ChainInfo{
|
||||||
|
RegisteredAt: ourHeight,
|
||||||
|
RemoteBlock: theirHeight,
|
||||||
|
}
|
||||||
|
data := wire.BinaryBytes(info)
|
||||||
|
c.Set.Set([]byte(chainID), data)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package ibc
|
package ibc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
abci "github.com/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/light-client/certifiers"
|
"github.com/tendermint/light-client/certifiers"
|
||||||
merkle "github.com/tendermint/merkleeyes/iavl"
|
merkle "github.com/tendermint/merkleeyes/iavl"
|
||||||
|
|
||||||
|
@ -21,13 +20,6 @@ const (
|
||||||
TypeUpdateChain = NameIBC + "/update"
|
TypeUpdateChain = NameIBC + "/update"
|
||||||
TypePacketCreate = NameIBC + "/create"
|
TypePacketCreate = NameIBC + "/create"
|
||||||
TypePacketPost = NameIBC + "/post"
|
TypePacketPost = NameIBC + "/post"
|
||||||
|
|
||||||
IBCCodeEncodingError = abci.CodeType(1001)
|
|
||||||
IBCCodeChainAlreadyExists = abci.CodeType(1002)
|
|
||||||
IBCCodePacketAlreadyExists = abci.CodeType(1003)
|
|
||||||
IBCCodeUnknownHeight = abci.CodeType(1004)
|
|
||||||
IBCCodeInvalidCommit = abci.CodeType(1005)
|
|
||||||
IBCCodeInvalidProof = abci.CodeType(1006)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -73,6 +65,11 @@ func (u UpdateChainTx) ValidateBasic() error {
|
||||||
return u.Seed.ValidateBasic(u.ChainID())
|
return u.Seed.ValidateBasic(u.ChainID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap - used to satisfy TxInner
|
||||||
|
func (u UpdateChainTx) Wrap() basecoin.Tx {
|
||||||
|
return basecoin.Tx{u}
|
||||||
|
}
|
||||||
|
|
||||||
// PacketCreateTx is meant to be called by IPC, another module...
|
// PacketCreateTx 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
|
||||||
|
|
Loading…
Reference in New Issue