2018-03-14 08:14:04 -07:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
2018-03-15 04:38:17 -07:00
|
|
|
"encoding/json"
|
2018-03-14 08:14:04 -07:00
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/builder"
|
|
|
|
|
2018-03-15 04:38:17 -07:00
|
|
|
//wire "github.com/tendermint/go-amino"
|
2018-03-14 08:14:04 -07:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/ibc"
|
|
|
|
)
|
|
|
|
|
2018-03-15 04:38:17 -07:00
|
|
|
func IBCRelayCmd() *cobra.Command {
|
|
|
|
cmdr := relayCommander{"ibc"}
|
2018-03-14 08:14:04 -07:00
|
|
|
|
|
|
|
cmd := &cobra.Command{
|
|
|
|
Use: "relay",
|
|
|
|
Run: cmdr.runIBCRelay,
|
|
|
|
}
|
2018-03-15 03:36:17 -07:00
|
|
|
cmd.Flags().String(client.FlagName, "", "Name of the key to sign")
|
2018-03-14 08:14:04 -07:00
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
type relayCommander struct {
|
2018-03-15 04:38:17 -07:00
|
|
|
// cdc *wire.Codec
|
2018-03-14 08:14:04 -07:00
|
|
|
ibcStore string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c relayCommander) runIBCRelay(cmd *cobra.Command, args []string) {
|
|
|
|
chain1 := viper.GetString(flagChain1)
|
|
|
|
chain2 := viper.GetString(flagChain2)
|
|
|
|
|
|
|
|
go c.loop(chain1, chain2)
|
|
|
|
go c.loop(chain2, chain1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/cosmos/cosmos-sdk/blob/master/client/helpers.go using specified address
|
|
|
|
|
|
|
|
func query(id string, key []byte, storeName string) (res []byte, err error) {
|
|
|
|
orig := viper.GetString(client.FlagNode)
|
|
|
|
viper.Set(client.FlagNode, id)
|
|
|
|
res, err = builder.Query(key, storeName)
|
|
|
|
viper.Set(client.FlagNode, orig)
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func broadcastTx(id string, tx []byte) error {
|
|
|
|
orig := viper.GetString(client.FlagNode)
|
|
|
|
viper.Set(client.FlagNode, id)
|
|
|
|
_, err := builder.BroadcastTx(tx)
|
|
|
|
viper.Set(client.FlagNode, orig)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c relayCommander) refine(bz []byte, sequence int64) []byte {
|
|
|
|
var packet ibc.IBCPacket
|
2018-03-15 04:38:17 -07:00
|
|
|
if err := json.Unmarshal(bz, &packet); err != nil {
|
2018-03-14 08:14:04 -07:00
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-15 03:36:17 -07:00
|
|
|
|
|
|
|
name := viper.GetString(client.FlagName)
|
|
|
|
|
|
|
|
address := getAddress(name)
|
2018-03-14 08:14:04 -07:00
|
|
|
msg := ibc.IBCReceiveMsg{
|
|
|
|
IBCPacket: packet,
|
|
|
|
Relayer: address,
|
|
|
|
Sequence: sequence,
|
|
|
|
}
|
2018-03-15 04:38:17 -07:00
|
|
|
res, err := buildTx(msg, name)
|
2018-03-14 08:14:04 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c relayCommander) loop(fromID, toID string) {
|
|
|
|
ingressKey := ibc.IngressKey(fromID)
|
|
|
|
|
|
|
|
processedbz, err := query(toID, ingressKey, c.ibcStore)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var processed int64
|
2018-03-15 04:38:17 -07:00
|
|
|
if err = json.Unmarshal(processedbz, &processed); err != nil {
|
2018-03-14 08:14:04 -07:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
OUTER:
|
|
|
|
for {
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
lengthKey := ibc.EgressLengthKey(toID)
|
|
|
|
egressLengthbz, err := query(fromID, lengthKey, c.ibcStore)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error querying outgoing packet list length: '%s'\n", err)
|
|
|
|
continue OUTER
|
|
|
|
}
|
|
|
|
var egressLength int64
|
2018-03-15 04:38:17 -07:00
|
|
|
if err = json.Unmarshal(egressLengthbz, &egressLength); err != nil {
|
2018-03-14 08:14:04 -07:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := processed; i < egressLength; i++ {
|
|
|
|
egressbz, err := query(fromID, ibc.EgressKey(toID, i), c.ibcStore)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error querying egress packet: '%s'\n", err)
|
|
|
|
continue OUTER
|
|
|
|
}
|
|
|
|
|
|
|
|
err = broadcastTx(toID, c.refine(egressbz, i))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error broadcasting ingress packet: '%s'\n", err)
|
|
|
|
continue OUTER
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Relayed packet: %d\n", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
processed = egressLength
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (c relayCommander) buildTx() ([]byte, error) {
|
|
|
|
keybase, err := keys.GetKeyBase()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
name := viper.GetString(client.FlagName)
|
|
|
|
info, err := keybase.Get(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("No key for: %s, name")
|
|
|
|
}
|
|
|
|
from := info.PubKey.Address()
|
|
|
|
|
|
|
|
msg, err := buildMsg(from)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
bz := msg.GetSignBytes()
|
|
|
|
buf := client.BufferStdin()
|
|
|
|
prompt := fmt.Sprintf("Password to sign with '%s':", name)
|
|
|
|
passphrase, err := client.GetPassword(prompt, buf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sig, pubkey, err := keybase.Sign(name, passphrase, bz)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sigs := []sdk.StdSignature{{
|
|
|
|
PubKey: pubkey,
|
|
|
|
Signature: sig,
|
|
|
|
Sequence: viper.GetInt64(flagSequence),
|
|
|
|
}}
|
|
|
|
|
|
|
|
tx := sdk.NewStdTx(msg, sigs)
|
|
|
|
|
|
|
|
txBytes, err := c.cdc.MarshalBinary(tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return txBytes, nil
|
|
|
|
}*/
|