relayer app

This commit is contained in:
mossid 2018-03-14 16:14:04 +01:00
parent 7049025f87
commit 820152b873
4 changed files with 322 additions and 0 deletions

10
x/ibc/commands/flags.go Normal file
View File

@ -0,0 +1,10 @@
package commands
const (
flagTo = "to"
flagAmount = "amount"
flagChain = "chain"
flagChain1 = "chain1"
flagChain2 = "chain2"
flagSequence = "sequence"
)

61
x/ibc/commands/helpers.go Normal file
View File

@ -0,0 +1,61 @@
package commands
import (
"fmt"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
)
func buildTx(cdc *wire.Codec, msg sdk.Msg) ([]byte, error) {
keybase, err := keys.GetKeyBase()
if err != nil {
return nil, err
}
name := viper.GetString(client.FlagName)
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 := cdc.MarshalBinary(tx)
if err != nil {
return nil, err
}
return txBytes, nil
}
func getAddress() []byte {
keybase, err := keys.GetKeyBase()
if err != nil {
panic(err)
}
name := viper.GetString(client.FlagName)
info, err := keybase.Get(name)
if err != nil {
panic(err)
}
return info.Address()
}

171
x/ibc/commands/relay.go Normal file
View File

@ -0,0 +1,171 @@
package commands
import (
"fmt"
"time"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/builder"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/ibc"
)
func IBCRelayCmd(cdc *wire.Codec) *cobra.Command {
cmdr := relayCommander{cdc, "ibc"}
cmd := &cobra.Command{
Use: "relay",
Run: cmdr.runIBCRelay,
}
cmd.Flags().String(flagTo, "", "Address to send coins")
cmd.Flags().String(flagAmount, "", "Amount of coins to send")
cmd.Flags().Int64(flagSequence, 0, "Sequence number to sign the tx")
return cmd
}
type relayCommander struct {
cdc *wire.Codec
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
if err := c.cdc.UnmarshalBinary(bz, &packet); err != nil {
panic(err)
}
address := getAddress()
msg := ibc.IBCReceiveMsg{
IBCPacket: packet,
Relayer: address,
Sequence: sequence,
}
res, err := buildTx(c.cdc, msg)
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
if err = c.cdc.UnmarshalBinary(processedbz, &processed); err != nil {
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
if err = c.cdc.UnmarshalBinary(egressLengthbz, &egressLength); err != nil {
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
}*/

80
x/ibc/commands/send.go Normal file
View File

@ -0,0 +1,80 @@
package commands
import (
"encoding/hex"
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/builder"
sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/ibc"
)
func IBCTransferCmd(cdc *wire.Codec) *cobra.Command {
cmdr := sendCommander{cdc}
cmd := &cobra.Command{
Use: "send",
RunE: cmdr.runIBCTransfer,
}
cmd.Flags().String(flagTo, "", "Address to send coins")
cmd.Flags().String(flagAmount, "", "Amount of coins to send")
cmd.Flags().String(flagChain, "", "Destination chain to send coins")
return cmd
}
type sendCommander struct {
cdc *wire.Codec
}
func (c sendCommander) runIBCTransfer(cmd *cobra.Command, args []string) error {
address := getAddress()
msg, err := buildMsg(address)
if err != nil {
return err
}
txBytes, err := buildTx(c.cdc, msg)
if err != nil {
return err
}
res, err := builder.BroadcastTx(txBytes)
if err != nil {
return err
}
fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String())
return nil
}
func buildMsg(from sdk.Address) (sdk.Msg, error) {
amount := viper.GetString(flagAmount)
coins, err := sdk.ParseCoins(amount)
if err != nil {
return nil, err
}
dest := viper.GetString(flagTo)
bz, err := hex.DecodeString(dest)
if err != nil {
return nil, err
}
to := sdk.Address(bz)
return ibc.IBCTransferMsg{
IBCPacket: ibc.IBCPacket{
SrcAddr: from,
DestAddr: to,
Coins: coins,
SrcChain: viper.GetString(client.FlagNode),
DestChain: viper.GetString(flagChain),
},
}, nil
}