Implement register and update headers as handler
This commit is contained in:
parent
8747bd5a8b
commit
9c1e695d46
|
@ -1 +1,40 @@
|
|||
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 (
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/errors"
|
||||
"github.com/tendermint/basecoin/stack"
|
||||
"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
|
||||
// for a registered chain
|
||||
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
|
||||
// apropriately
|
||||
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"
|
||||
)
|
||||
|
||||
// newCertifier loads up the current state of this chain to make a proper
|
||||
func newCertifier(chainID string, store state.KVStore) (*certifiers.InquiringCertifier, error) {
|
||||
// newCertifier loads up the current state of this chain to make a proper certifier
|
||||
// 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
|
||||
space := stack.PrefixedStore(chainID, store)
|
||||
p := newDBProvider(space)
|
||||
p := newDBProvider(store)
|
||||
|
||||
// this gets the most recent verified seed
|
||||
seed, err := certifiers.LatestSeed(p)
|
||||
var seed certifiers.Seed
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1 +1,49 @@
|
|||
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
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
merkle "github.com/tendermint/merkleeyes/iavl"
|
||||
|
||||
|
@ -21,13 +20,6 @@ const (
|
|||
TypeUpdateChain = NameIBC + "/update"
|
||||
TypePacketCreate = NameIBC + "/create"
|
||||
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() {
|
||||
|
@ -73,6 +65,11 @@ func (u UpdateChainTx) ValidateBasic() error {
|
|||
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...
|
||||
//
|
||||
// this is the tx that will be sent to another app and the permissions it
|
||||
|
|
Loading…
Reference in New Issue