From 30eced21c5dddfaa4a541d3cbe31f17fb0aa13aa Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 17 Jul 2017 21:52:02 +0200 Subject: [PATCH] Wrote bulk of ibc post packet middleware --- modules/ibc/middleware.go | 77 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/modules/ibc/middleware.go b/modules/ibc/middleware.go index cb32ea603..869795149 100644 --- a/modules/ibc/middleware.go +++ b/modules/ibc/middleware.go @@ -1,6 +1,8 @@ package ibc import ( + "errors" + "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/stack" "github.com/tendermint/basecoin/state" @@ -27,11 +29,82 @@ func (Middleware) Name() string { // 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 + // if it is not a PostPacket, just let it go through + post, ok := tx.Unwrap().(PostPacketTx) + if !ok { + return next.CheckTx(ctx, store, tx) + } + + // parse this packet and get the ibc-enhanced tx and context + ictx, itx, err := m.verifyPost(ctx, store, post) + if err != nil { + return res, err + } + return next.CheckTx(ictx, store, itx) } // 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 + // if it is not a PostPacket, just let it go through + post, ok := tx.Unwrap().(PostPacketTx) + if !ok { + return next.DeliverTx(ctx, store, tx) + } + + // parse this packet and get the ibc-enhanced tx and context + ictx, itx, err := m.verifyPost(ctx, store, post) + if err != nil { + return res, err + } + return next.DeliverTx(ictx, store, itx) +} + +// verifyPost accepts a message bound for this chain... +// TODO: think about relay +func (m Middleware) verifyPost(ctx basecoin.Context, store state.KVStore, + tx PostPacketTx) (ictx basecoin.Context, itx basecoin.Tx, err error) { + + // make sure the chain is registered + from := tx.FromChainID + if !NewChainSet(store).Exists([]byte(from)) { + err = ErrNotRegistered(from) + return + } + + // make sure this sequence number is the next in the list + q := InputQueue(store, from) + packet := tx.Packet + if q.Tail() != packet.Sequence { + err = errors.New("Incorrect sequence number - out of order") // TODO + return + } + + // look up the referenced header + space := stack.PrefixedStore(from, store) + provider := newDBProvider(space) + // TODO: GetExactHeight helper? + seed, err := provider.GetByHeight(int(tx.FromChainHeight)) + if err != nil { + return ictx, itx, err + } + if seed.Height() != int(tx.FromChainHeight) { + err = errors.New("no such height") // TODO + return + } + + // verify the merkle hash.... + root := seed.Header.AppHash + key := []byte("?????") // TODO! + tx.Proof.Verify(key, packet.Bytes(), root) + + // TODO: verify packet.Permissions + + // add to input queue + q.Push(packet.Bytes()) + + // return the wrapped tx along with the extra permissions + ictx = ictx.WithPermissions(packet.Permissions...) + itx = packet.Tx + return }