support SendTx to other chains via IBC
This commit is contained in:
+54
-12
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
@@ -13,7 +14,6 @@ import (
|
||||
merkle "github.com/tendermint/merkleeyes/iavl"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
bcsm "github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
tm "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -55,20 +55,53 @@ type Packet struct {
|
||||
SrcChainID string
|
||||
DstChainID string
|
||||
Sequence uint64
|
||||
Type string
|
||||
Type string // redundant now that Type() is a method on Payload ?
|
||||
Payload Payload
|
||||
}
|
||||
|
||||
func NewPacket(src, dst string, seq uint64, ty string, payload Payload) Packet {
|
||||
func NewPacket(src, dst string, seq uint64, payload Payload) Packet {
|
||||
return Packet{
|
||||
SrcChainID: src,
|
||||
DstChainID: dst,
|
||||
Sequence: seq,
|
||||
Type: ty,
|
||||
Type: payload.Type(),
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSequenceNumber gets the sequence number for packets being sent from the src chain to the dst chain
|
||||
func GetSequenceNumber(store types.KVStore, src, dst string) uint64 {
|
||||
sequenceKey := toKey(_IBC, _EGRESS, src, dst)
|
||||
seqBytes := store.Get(sequenceKey)
|
||||
if seqBytes == nil {
|
||||
return 0
|
||||
}
|
||||
seq, err := strconv.ParseUint(string(seqBytes), 10, 64)
|
||||
if err != nil {
|
||||
cmn.PanicSanity(err.Error())
|
||||
}
|
||||
return seq
|
||||
}
|
||||
|
||||
// SetSequenceNumber sets the sequence number for packets being sent from the src chain to the dst chain
|
||||
func SetSequenceNumber(store types.KVStore, src, dst string, seq uint64) {
|
||||
sequenceKey := toKey(_IBC, _EGRESS, src, dst)
|
||||
store.Set(sequenceKey, []byte(strconv.FormatUint(seq, 10)))
|
||||
}
|
||||
|
||||
// SaveNewIBCPacket creates an IBC packet with the given payload from the src chain to the dst chain
|
||||
// using the correct sequence number. It also increments the sequence number by 1
|
||||
func SaveNewIBCPacket(state types.KVStore, src, dst string, payload Payload) {
|
||||
// fetch sequence number and increment by 1
|
||||
seq := GetSequenceNumber(state, src, dst)
|
||||
SetSequenceNumber(state, src, dst, seq+1)
|
||||
|
||||
// save ibc packet
|
||||
packetKey := toKey(_IBC, _EGRESS, src, dst, cmn.Fmt("%v", seq))
|
||||
packet := NewPacket(src, dst, uint64(seq), payload)
|
||||
save(state, packetKey, packet)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
const (
|
||||
@@ -78,21 +111,26 @@ const (
|
||||
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ Payload }{},
|
||||
wire.ConcreteType{BytesPayload{}, PayloadTypeBytes},
|
||||
wire.ConcreteType{DataPayload{}, PayloadTypeBytes},
|
||||
wire.ConcreteType{CoinsPayload{}, PayloadTypeCoins},
|
||||
)
|
||||
|
||||
type Payload interface {
|
||||
AssertIsPayload()
|
||||
Type() string
|
||||
ValidateBasic() abci.Result
|
||||
}
|
||||
|
||||
func (BytesPayload) AssertIsPayload() {}
|
||||
func (DataPayload) AssertIsPayload() {}
|
||||
func (CoinsPayload) AssertIsPayload() {}
|
||||
|
||||
type BytesPayload []byte
|
||||
type DataPayload []byte
|
||||
|
||||
func (p BytesPayload) ValidateBasic() abci.Result {
|
||||
func (p DataPayload) Type() string {
|
||||
return "data"
|
||||
}
|
||||
|
||||
func (p DataPayload) ValidateBasic() abci.Result {
|
||||
return abci.OK
|
||||
}
|
||||
|
||||
@@ -101,6 +139,10 @@ type CoinsPayload struct {
|
||||
Coins types.Coins
|
||||
}
|
||||
|
||||
func (p CoinsPayload) Type() string {
|
||||
return "coin"
|
||||
}
|
||||
|
||||
func (p CoinsPayload) ValidateBasic() abci.Result {
|
||||
// TODO: validate
|
||||
return abci.OK
|
||||
@@ -351,7 +393,7 @@ func (sm *IBCStateMachine) runPacketCreateTx(tx IBCPacketCreateTx) {
|
||||
|
||||
// Execute the payload
|
||||
switch payload := tx.Packet.Payload.(type) {
|
||||
case BytesPayload:
|
||||
case DataPayload:
|
||||
// do nothing
|
||||
case CoinsPayload:
|
||||
// ensure enough coins were sent in tx to cover the payload coins
|
||||
@@ -428,16 +470,16 @@ func (sm *IBCStateMachine) runPacketPostTx(tx IBCPacketPostTx) {
|
||||
|
||||
// Execute payload
|
||||
switch payload := packet.Payload.(type) {
|
||||
case BytesPayload:
|
||||
case DataPayload:
|
||||
// do nothing
|
||||
case CoinsPayload:
|
||||
// Add coins to destination account
|
||||
acc := bcsm.GetAccount(sm.store, payload.Address)
|
||||
acc := types.GetAccount(sm.store, payload.Address)
|
||||
if acc == nil {
|
||||
acc = &types.Account{}
|
||||
}
|
||||
acc.Balance = acc.Balance.Plus(payload.Coins)
|
||||
bcsm.SetAccount(sm.store, payload.Address, acc)
|
||||
types.SetAccount(sm.store, payload.Address, acc)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/tendermint/merkleeyes/iavl"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
sm "github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
tm "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -170,7 +169,7 @@ func TestIBCPluginPost(t *testing.T) {
|
||||
registerChain(t, ibcPlugin, store, ctx, "test_chain", string(genDocJSON_1))
|
||||
|
||||
// Create a new packet (for testing)
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, "data", BytesPayload([]byte("hello world")))
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, DataPayload([]byte("hello world")))
|
||||
res := ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{
|
||||
Packet: packet,
|
||||
}}))
|
||||
@@ -203,7 +202,7 @@ func TestIBCPluginPayloadBytes(t *testing.T) {
|
||||
registerChain(t, ibcPlugin, store, ctx, "test_chain", string(genDocJSON_1))
|
||||
|
||||
// Create a new packet (for testing)
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, "data", BytesPayload([]byte("hello world")))
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, DataPayload([]byte("hello world")))
|
||||
res := ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{
|
||||
Packet: packet,
|
||||
}}))
|
||||
@@ -282,7 +281,7 @@ func TestIBCPluginPayloadCoins(t *testing.T) {
|
||||
coinsGood := types.Coins{types.Coin{"mycoin", 1}}
|
||||
|
||||
// Try to send too many coins
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, "data", CoinsPayload{
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, CoinsPayload{
|
||||
Address: destinationAddr,
|
||||
Coins: coinsBad,
|
||||
})
|
||||
@@ -292,7 +291,7 @@ func TestIBCPluginPayloadCoins(t *testing.T) {
|
||||
assertAndLog(t, store, res, abci.CodeType_InsufficientFunds)
|
||||
|
||||
// Send a small enough number of coins
|
||||
packet = NewPacket("test_chain", "dst_chain", 0, "data", CoinsPayload{
|
||||
packet = NewPacket("test_chain", "dst_chain", 0, CoinsPayload{
|
||||
Address: destinationAddr,
|
||||
Coins: coinsGood,
|
||||
})
|
||||
@@ -334,7 +333,7 @@ func TestIBCPluginPayloadCoins(t *testing.T) {
|
||||
assert.Nil(err)
|
||||
|
||||
// Account should be empty before the tx
|
||||
acc := sm.GetAccount(store, destinationAddr)
|
||||
acc := types.GetAccount(store, destinationAddr)
|
||||
assert.Nil(acc)
|
||||
|
||||
// Post a packet
|
||||
@@ -347,7 +346,7 @@ func TestIBCPluginPayloadCoins(t *testing.T) {
|
||||
assertAndLog(t, store, res, abci.CodeType_OK)
|
||||
|
||||
// Account should now have some coins
|
||||
acc = sm.GetAccount(store, destinationAddr)
|
||||
acc = types.GetAccount(store, destinationAddr)
|
||||
assert.Equal(acc.Balance, coinsGood)
|
||||
}
|
||||
|
||||
@@ -408,7 +407,7 @@ func TestIBCPluginBadProof(t *testing.T) {
|
||||
registerChain(t, ibcPlugin, store, ctx, "test_chain", string(genDocJSON_1))
|
||||
|
||||
// Create a new packet (for testing)
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, "data", BytesPayload([]byte("hello world")))
|
||||
packet := NewPacket("test_chain", "dst_chain", 0, DataPayload([]byte("hello world")))
|
||||
res := ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{
|
||||
Packet: packet,
|
||||
}}))
|
||||
|
||||
Reference in New Issue
Block a user