Started on ibc module tx, types

This commit is contained in:
Ethan Frey 2017-07-13 19:22:05 +02:00
parent 88781593bb
commit 697c2f1e04
6 changed files with 275 additions and 0 deletions

1
modules/ibc/errors.go Normal file
View File

@ -0,0 +1 @@
package ibc

40
modules/ibc/handler.go Normal file
View File

@ -0,0 +1,40 @@
package ibc
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/state"
)
// nolint
const (
NameIBC = "ibc"
)
// Handler allows us to update the chain state or create a packet
type Handler struct {
basecoin.NopOption
}
var _ basecoin.Handler = Handler{}
// NewHandler makes a role handler to create roles
func NewHandler() Handler {
return Handler{}
}
// Name - return name space
func (Handler) Name() string {
return NameIBC
}
// 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
}
// 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
}

37
modules/ibc/middleware.go Normal file
View File

@ -0,0 +1,37 @@
package ibc
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
)
// Middleware allows us to verify the IBC proof on a packet and
// and if valid, attach this permission to the wrapped packet
type Middleware struct {
stack.PassOption
}
var _ stack.Middleware = Middleware{}
// NewMiddleware creates a role-checking middleware
func NewMiddleware() Middleware {
return Middleware{}
}
// Name - return name space
func (Middleware) Name() string {
return NameIBC
}
// CheckTx verifies the named chain and height is present, and verifies
// the merkle proof in the packet
func (m Middleware) CheckTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Checker) (res basecoin.Result, err error) {
return res, nil
}
// DeliverTx verifies the named chain and height is present, and verifies
// the merkle proof in the packet
func (m Middleware) DeliverTx(ctx basecoin.Context, store state.KVStore, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.Result, err error) {
return res, nil
}

44
modules/ibc/provider.go Normal file
View File

@ -0,0 +1,44 @@
package ibc
import (
"github.com/tendermint/light-client/certifiers"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
)
// newCertifier loads up the current state of this chain to make a proper
func newCertifier(chainID string, store state.KVStore) (*certifiers.InquiringCertifier, error) {
// each chain has their own prefixed subspace
space := stack.PrefixedStore(chainID, store)
p := dbProvider{space}
// this gets the most recent verified seed
seed, err := certifiers.LatestSeed(p)
if err != nil {
return nil, err
}
// we have no source for untrusted keys, but use the db to load trusted history
cert := certifiers.NewInquiring(chainID, seed.Validators, p,
certifiers.MissingProvider{})
return cert, nil
}
// dbProvider wraps our kv store so it integrates with light-client verification
type dbProvider struct {
store state.KVStore
}
var _ certifiers.Provider = dbProvider{}
func (d dbProvider) StoreSeed(seed certifiers.Seed) error {
return nil
}
func (d dbProvider) GetByHeight(h int) (certifiers.Seed, error) {
return certifiers.Seed{}, certifiers.ErrSeedNotFound()
}
func (d dbProvider) GetByHash(hash []byte) (certifiers.Seed, error) {
return certifiers.Seed{}, certifiers.ErrSeedNotFound()
}

1
modules/ibc/store.go Normal file
View File

@ -0,0 +1 @@
package ibc

152
modules/ibc/tx.go Normal file
View File

@ -0,0 +1,152 @@
package ibc
import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/light-client/certifiers"
merkle "github.com/tendermint/merkleeyes/iavl"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
)
// nolint
const (
// 0x3? series for ibc
ByteRegisterChain = byte(0x30)
ByteUpdateChain = byte(0x31)
BytePacketCreate = byte(0x32)
BytePacketPost = byte(0x33)
TypeRegisterChain = NameIBC + "/register"
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() {
basecoin.TxMapper.
RegisterImplementation(RegisterChainTx{}, TypeRegisterChain, ByteRegisterChain).
RegisterImplementation(UpdateChainTx{}, TypeUpdateChain, ByteUpdateChain).
RegisterImplementation(PacketCreateTx{}, TypePacketCreate, BytePacketCreate).
RegisterImplementation(PacketPostTx{}, TypePacketPost, BytePacketPost)
}
// RegisterChainTx allows you to register a new chain on this blockchain
type RegisterChainTx struct {
Seed certifiers.Seed `json:"seed"`
}
// ChainID helps get the chain this tx refers to
func (r RegisterChainTx) ChainID() string {
return r.Seed.Header.ChainID
}
// ValidateBasic makes sure this is consistent, without checking the sigs
func (r RegisterChainTx) ValidateBasic() error {
return r.Seed.ValidateBasic(r.ChainID())
}
// Wrap - used to satisfy TxInner
func (r RegisterChainTx) Wrap() basecoin.Tx {
return basecoin.Tx{r}
}
// UpdateChainTx updates the state of this chain
type UpdateChainTx struct {
Seed certifiers.Seed `json:"seed"`
}
// ChainID helps get the chain this tx refers to
func (u UpdateChainTx) ChainID() string {
return u.Seed.Header.ChainID
}
// ValidateBasic makes sure this is consistent, without checking the sigs
func (u UpdateChainTx) ValidateBasic() error {
return u.Seed.ValidateBasic(u.ChainID())
}
// 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
// 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 {
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 {
if p.DestChain == "" {
return errors.ErrNoChain()
}
// if len(p.Permissions) == 0 {
// return ErrNoPermissions()
// }
return nil
}
// Wrap - used to satisfy TxInner
func (p PacketCreateTx) Wrap() basecoin.Tx {
return basecoin.Tx{p}
}
// PacketPostTx takes a wrapped packet from another chain and
// TODO!!!
type PacketPostTx struct {
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
Proof *merkle.IAVLProof
// Packet
}
// ValidateBasic makes sure this is consistent - used to satisfy TxInner
func (p PacketPostTx) ValidateBasic() error {
// TODO
return nil
}
// Wrap - used to satisfy TxInner
func (p PacketPostTx) Wrap() basecoin.Tx {
return basecoin.Tx{p}
}
// proof := tx.Proof
// if proof == nil {
// sm.res.Code = IBCCodeInvalidProof
// sm.res.Log = "Proof is nil"
// return
// }
// packetBytes := wire.BinaryBytes(packet)
// // Make sure packet's proof matches given (packet, key, blockhash)
// ok := proof.Verify(packetKeyEgress, packetBytes, header.AppHash)
// if !ok {
// sm.res.Code = IBCCodeInvalidProof
// sm.res.Log = fmt.Sprintf("Proof is invalid. key: %s; packetByes %X; header %v; proof %v", packetKeyEgress, packetBytes, header, proof)
// return
// }
// // Execute payload
// switch payload := packet.Payload.(type) {
// case DataPayload:
// // do nothing
// case CoinsPayload:
// // Add coins to destination account
// acc := types.GetAccount(sm.store, payload.Address)
// if acc == nil {
// acc = &types.Account{}
// }
// acc.Balance = acc.Balance.Plus(payload.Coins)
// types.SetAccount(sm.store, payload.Address, acc)
// }