2017-01-30 06:16:51 -08:00
|
|
|
package commands
|
2017-01-29 18:41:37 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
"github.com/pkg/errors"
|
2017-03-08 23:19:07 -08:00
|
|
|
"github.com/spf13/cobra"
|
2017-01-29 18:41:37 -08:00
|
|
|
|
|
|
|
"github.com/tendermint/basecoin/plugins/ibc"
|
|
|
|
|
|
|
|
"github.com/tendermint/go-wire"
|
2017-04-25 22:20:29 -07:00
|
|
|
"github.com/tendermint/merkleeyes/iavl"
|
2017-01-29 18:41:37 -08:00
|
|
|
tmtypes "github.com/tendermint/tendermint/types"
|
|
|
|
)
|
|
|
|
|
2017-02-13 14:04:49 -08:00
|
|
|
// returns a new IBC plugin to be registered with Basecoin
|
|
|
|
func NewIBCPlugin() *ibc.IBCPlugin {
|
|
|
|
return ibc.New()
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
//commands
|
2017-01-30 06:16:51 -08:00
|
|
|
var (
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCTxCmd = &cobra.Command{
|
|
|
|
Use: "ibc",
|
|
|
|
Short: "An IBC transaction, for InterBlockchain Communication",
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCRegisterTxCmd = &cobra.Command{
|
|
|
|
Use: "register",
|
|
|
|
Short: "Register a blockchain via IBC",
|
2017-04-15 09:07:27 -07:00
|
|
|
RunE: ibcRegisterTxCmd,
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCUpdateTxCmd = &cobra.Command{
|
|
|
|
Use: "update",
|
|
|
|
Short: "Update the latest state of a blockchain via IBC",
|
2017-04-15 09:07:27 -07:00
|
|
|
RunE: ibcUpdateTxCmd,
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCPacketTxCmd = &cobra.Command{
|
|
|
|
Use: "packet",
|
|
|
|
Short: "Send a new packet via IBC",
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCPacketCreateTxCmd = &cobra.Command{
|
|
|
|
Use: "create",
|
|
|
|
Short: "Create an egress IBC packet",
|
2017-04-15 09:07:27 -07:00
|
|
|
RunE: ibcPacketCreateTxCmd,
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
IBCPacketPostTxCmd = &cobra.Command{
|
|
|
|
Use: "post",
|
|
|
|
Short: "Deliver an IBC packet to another chain",
|
2017-04-15 09:07:27 -07:00
|
|
|
RunE: ibcPacketPostTxCmd,
|
2017-02-07 10:16:41 -08:00
|
|
|
}
|
2017-03-08 23:19:07 -08:00
|
|
|
)
|
2017-02-07 10:16:41 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
//flags
|
|
|
|
var (
|
|
|
|
ibcChainIDFlag string
|
|
|
|
ibcGenesisFlag string
|
|
|
|
ibcHeaderFlag string
|
|
|
|
ibcCommitFlag string
|
|
|
|
ibcFromFlag string
|
|
|
|
ibcToFlag string
|
|
|
|
ibcTypeFlag string
|
|
|
|
ibcPayloadFlag string
|
|
|
|
ibcPacketFlag string
|
|
|
|
ibcProofFlag string
|
|
|
|
ibcSequenceFlag int
|
|
|
|
ibcHeightFlag int
|
2017-02-07 10:16:41 -08:00
|
|
|
)
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
func init() {
|
2017-02-07 10:16:41 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
// register flags
|
|
|
|
registerFlags := []Flag2Register{
|
|
|
|
{&ibcChainIDFlag, "ibc_chain_id", "", "ChainID for the new blockchain"},
|
|
|
|
{&ibcGenesisFlag, "genesis", "", "Genesis file for the new blockchain"},
|
2017-01-30 06:16:51 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
updateFlags := []Flag2Register{
|
|
|
|
{&ibcHeaderFlag, "header", "", "Block header for an ibc update"},
|
|
|
|
{&ibcCommitFlag, "commit", "", "Block commit for an ibc update"},
|
2017-01-30 06:16:51 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
fromFlagReg := Flag2Register{&ibcFromFlag, "ibc_from", "", "Source ChainID"}
|
2017-01-30 06:16:51 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
packetCreateFlags := []Flag2Register{
|
|
|
|
fromFlagReg,
|
|
|
|
{&ibcToFlag, "to", "", "Destination ChainID"},
|
2017-04-17 18:28:03 -07:00
|
|
|
{&ibcTypeFlag, "type", "", "IBC packet type (eg. coin)"},
|
2017-03-08 23:19:07 -08:00
|
|
|
{&ibcPayloadFlag, "payload", "", "IBC packet payload"},
|
|
|
|
{&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"},
|
2017-01-30 06:16:51 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
packetPostFlags := []Flag2Register{
|
|
|
|
fromFlagReg,
|
|
|
|
{&ibcHeightFlag, "height", 0, "Height the packet became egress in source chain"},
|
|
|
|
{&ibcPacketFlag, "packet", "", "hex-encoded IBC packet"},
|
|
|
|
{&ibcProofFlag, "proof", "", "hex-encoded proof of IBC packet from source chain"},
|
2017-01-30 06:16:51 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
RegisterFlags(IBCRegisterTxCmd, registerFlags)
|
|
|
|
RegisterFlags(IBCUpdateTxCmd, updateFlags)
|
|
|
|
RegisterFlags(IBCPacketCreateTxCmd, packetCreateFlags)
|
|
|
|
RegisterFlags(IBCPacketPostTxCmd, packetPostFlags)
|
|
|
|
|
|
|
|
//register commands
|
|
|
|
IBCTxCmd.AddCommand(IBCRegisterTxCmd, IBCUpdateTxCmd, IBCPacketTxCmd)
|
|
|
|
IBCPacketTxCmd.AddCommand(IBCPacketCreateTxCmd, IBCPacketPostTxCmd)
|
|
|
|
RegisterTxSubcommand(IBCTxCmd)
|
|
|
|
}
|
2017-01-30 06:16:51 -08:00
|
|
|
|
2017-02-07 10:16:41 -08:00
|
|
|
//---------------------------------------------------------------------
|
|
|
|
// ibc command implementations
|
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
func ibcRegisterTxCmd(cmd *cobra.Command, args []string) error {
|
2017-03-08 23:19:07 -08:00
|
|
|
chainID := ibcChainIDFlag
|
|
|
|
genesisFile := ibcGenesisFlag
|
2017-01-29 18:41:37 -08:00
|
|
|
|
|
|
|
genesisBytes, err := ioutil.ReadFile(genesisFile)
|
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Error reading genesis file %v: %v\n", genesisFile, err)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ibcTx := ibc.IBCRegisterChainTx{
|
|
|
|
ibc.BlockchainGenesis{
|
|
|
|
ChainID: chainID,
|
|
|
|
Genesis: string(genesisBytes),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("IBCTx:", string(wire.JSONBytes(ibcTx)))
|
|
|
|
|
2017-01-29 20:06:14 -08:00
|
|
|
data := []byte(wire.BinaryBytes(struct {
|
|
|
|
ibc.IBCTx `json:"unwrap"`
|
|
|
|
}{ibcTx}))
|
|
|
|
name := "IBC"
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
return AppTx(name, data)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
func ibcUpdateTxCmd(cmd *cobra.Command, args []string) error {
|
2017-03-08 23:19:07 -08:00
|
|
|
headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag))
|
2017-01-29 18:41:37 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Header (%v) is invalid hex: %v\n", ibcHeaderFlag, err)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
2017-03-08 23:19:07 -08:00
|
|
|
|
|
|
|
commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag))
|
2017-01-29 18:41:37 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Commit (%v) is invalid hex: %v\n", ibcCommitFlag, err)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
2017-01-29 20:06:14 -08:00
|
|
|
header := new(tmtypes.Header)
|
|
|
|
commit := new(tmtypes.Commit)
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
err = wire.ReadBinaryBytes(headerBytes, &header)
|
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Error unmarshalling header: %v\n", err)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
2017-03-08 23:19:07 -08:00
|
|
|
|
|
|
|
err = wire.ReadBinaryBytes(commitBytes, &commit)
|
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Error unmarshalling commit: %v\n", err)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ibcTx := ibc.IBCUpdateChainTx{
|
2017-01-29 20:06:14 -08:00
|
|
|
Header: *header,
|
|
|
|
Commit: *commit,
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("IBCTx:", string(wire.JSONBytes(ibcTx)))
|
|
|
|
|
2017-01-29 20:06:14 -08:00
|
|
|
data := []byte(wire.BinaryBytes(struct {
|
|
|
|
ibc.IBCTx `json:"unwrap"`
|
|
|
|
}{ibcTx}))
|
|
|
|
name := "IBC"
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
return AppTx(name, data)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) error {
|
2017-03-08 23:19:07 -08:00
|
|
|
fromChain, toChain := ibcFromFlag, ibcToFlag
|
|
|
|
packetType := ibcTypeFlag
|
2017-01-29 19:18:50 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag))
|
2017-01-29 19:18:50 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Payload (%v) is invalid hex: %v\n", ibcPayloadFlag, err)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
sequence, err := ibcSequenceCmd()
|
2017-01-29 19:18:50 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return err
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ibcTx := ibc.IBCPacketCreateTx{
|
|
|
|
Packet: ibc.Packet{
|
|
|
|
SrcChainID: fromChain,
|
|
|
|
DstChainID: toChain,
|
|
|
|
Sequence: sequence,
|
|
|
|
Type: packetType,
|
|
|
|
Payload: payloadBytes,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("IBCTx:", string(wire.JSONBytes(ibcTx)))
|
|
|
|
|
2017-01-29 20:06:14 -08:00
|
|
|
data := []byte(wire.BinaryBytes(struct {
|
|
|
|
ibc.IBCTx `json:"unwrap"`
|
|
|
|
}{ibcTx}))
|
2017-01-29 19:18:50 -08:00
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
return AppTx("IBC", data)
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) error {
|
2017-03-08 23:19:07 -08:00
|
|
|
fromChain, fromHeight := ibcFromFlag, ibcHeightFlag
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag))
|
2017-01-29 19:18:50 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Packet (%v) is invalid hex: %v\n", ibcPacketFlag, err)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
2017-03-08 23:19:07 -08:00
|
|
|
|
|
|
|
proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag))
|
2017-01-29 19:18:50 -08:00
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Proof (%v) is invalid hex: %v\n", ibcProofFlag, err)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
var packet ibc.Packet
|
2017-04-25 22:20:29 -07:00
|
|
|
proof := new(iavl.IAVLProof)
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
err = wire.ReadBinaryBytes(packetBytes, &packet)
|
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Error unmarshalling packet: %v\n", err)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
2017-03-08 23:19:07 -08:00
|
|
|
|
|
|
|
err = wire.ReadBinaryBytes(proofBytes, &proof)
|
|
|
|
if err != nil {
|
2017-04-15 09:07:27 -07:00
|
|
|
return errors.Errorf("Error unmarshalling proof: %v\n", err)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-01-29 19:18:50 -08:00
|
|
|
ibcTx := ibc.IBCPacketPostTx{
|
2017-01-29 18:41:37 -08:00
|
|
|
FromChainID: fromChain,
|
2017-01-29 19:18:50 -08:00
|
|
|
FromChainHeight: uint64(fromHeight),
|
|
|
|
Packet: packet,
|
|
|
|
Proof: proof,
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("IBCTx:", string(wire.JSONBytes(ibcTx)))
|
|
|
|
|
2017-01-29 20:06:14 -08:00
|
|
|
data := []byte(wire.BinaryBytes(struct {
|
|
|
|
ibc.IBCTx `json:"unwrap"`
|
|
|
|
}{ibcTx}))
|
2017-01-29 18:41:37 -08:00
|
|
|
|
2017-04-15 09:07:27 -07:00
|
|
|
return AppTx("IBC", data)
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:19:07 -08:00
|
|
|
func ibcSequenceCmd() (uint64, error) {
|
|
|
|
if ibcSequenceFlag >= 0 {
|
|
|
|
return uint64(ibcSequenceFlag), nil
|
2017-01-29 19:18:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: get sequence
|
|
|
|
return 0, nil
|
2017-01-29 18:41:37 -08:00
|
|
|
}
|