added cli cobra
rebaseFixes int removed ExitOnErr int int int int int added uint64 to RegisterFlags
This commit is contained in:
parent
c6e348e01b
commit
fb3fd1b425
@ -4,17 +4,18 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/cmd/commands"
|
||||
"github.com/tendermint/basecoin/version"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "basecoin"
|
||||
app.Usage = "basecoin [command] [args...]"
|
||||
app.Version = version.Version
|
||||
app.Commands = []cli.Command{
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "basecoin",
|
||||
Short: "A cryptocurrency framework in Golang based on Tendermint-Core",
|
||||
}
|
||||
|
||||
RootCmd.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.StartCmd,
|
||||
commands.TxCmd,
|
||||
@ -24,9 +25,10 @@ func main() {
|
||||
commands.BlockCmd,
|
||||
commands.AccountCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
}
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
commands.VersionCmd,
|
||||
)
|
||||
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// start flags
|
||||
var (
|
||||
AddrFlag = cli.StringFlag{
|
||||
Name: "address",
|
||||
Value: "tcp://0.0.0.0:46658",
|
||||
Usage: "Listen address",
|
||||
}
|
||||
|
||||
EyesFlag = cli.StringFlag{
|
||||
Name: "eyes",
|
||||
Value: "local",
|
||||
Usage: "MerkleEyes address, or 'local' for embedded",
|
||||
}
|
||||
|
||||
// TODO: move to config file
|
||||
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
||||
|
||||
WithoutTendermintFlag = cli.BoolFlag{
|
||||
Name: "without-tendermint",
|
||||
Usage: "Run the Basecoin app without Tendermint",
|
||||
}
|
||||
)
|
||||
|
||||
// tx flags
|
||||
|
||||
var (
|
||||
NodeFlag = cli.StringFlag{
|
||||
Name: "node",
|
||||
Value: "tcp://localhost:46657",
|
||||
Usage: "Tendermint RPC address",
|
||||
}
|
||||
|
||||
ToFlag = cli.StringFlag{
|
||||
Name: "to",
|
||||
Value: "",
|
||||
Usage: "Destination address for the transaction",
|
||||
}
|
||||
|
||||
AmountFlag = cli.StringFlag{
|
||||
Name: "amount",
|
||||
Value: "",
|
||||
Usage: "Coins to send in transaction of the format <amt><coin>,<amt2><coin2>,... (eg: 1btc,2gold,5silver)",
|
||||
}
|
||||
|
||||
FromFlag = cli.StringFlag{
|
||||
Name: "from",
|
||||
Value: "key.json",
|
||||
Usage: "Path to a private key to sign the transaction",
|
||||
}
|
||||
|
||||
SeqFlag = cli.IntFlag{
|
||||
Name: "sequence",
|
||||
Value: 0,
|
||||
Usage: "Sequence number for the account",
|
||||
}
|
||||
|
||||
GasFlag = cli.IntFlag{
|
||||
Name: "gas",
|
||||
Value: 0,
|
||||
Usage: "The amount of gas for the transaction",
|
||||
}
|
||||
|
||||
FeeFlag = cli.StringFlag{
|
||||
Name: "fee",
|
||||
Value: "",
|
||||
Usage: "Coins for the transaction fee of the format <amt><coin>",
|
||||
}
|
||||
|
||||
DataFlag = cli.StringFlag{
|
||||
Name: "data",
|
||||
Value: "",
|
||||
Usage: "Data to send with the transaction",
|
||||
}
|
||||
|
||||
NameFlag = cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Plugin to send the transaction to",
|
||||
}
|
||||
|
||||
ChainIDFlag = cli.StringFlag{
|
||||
Name: "chain_id",
|
||||
Value: "test_chain_id",
|
||||
Usage: "ID of the chain for replay protection",
|
||||
}
|
||||
)
|
||||
|
||||
// proof flags
|
||||
var (
|
||||
ProofFlag = cli.StringFlag{
|
||||
Name: "proof",
|
||||
Usage: "hex-encoded IAVL proof",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
KeyFlag = cli.StringFlag{
|
||||
Name: "key",
|
||||
Usage: "key to the IAVL tree",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
ValueFlag = cli.StringFlag{
|
||||
Name: "value",
|
||||
Usage: "value in the IAVL tree",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
RootFlag = cli.StringFlag{
|
||||
Name: "root",
|
||||
Usage: "root hash of the IAVL tree",
|
||||
Value: "",
|
||||
}
|
||||
)
|
||||
@ -2,11 +2,10 @@ package commands
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/plugins/ibc"
|
||||
|
||||
@ -21,172 +20,110 @@ func NewIBCPlugin() *ibc.IBCPlugin {
|
||||
return ibc.New()
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ibc flags
|
||||
|
||||
//commands
|
||||
var (
|
||||
IbcChainIDFlag = cli.StringFlag{
|
||||
Name: "chain_id",
|
||||
Usage: "ChainID for the new blockchain",
|
||||
Value: "",
|
||||
IBCTxCmd = &cobra.Command{
|
||||
Use: "ibc",
|
||||
Short: "An IBC transaction, for InterBlockchain Communication",
|
||||
}
|
||||
|
||||
IbcGenesisFlag = cli.StringFlag{
|
||||
Name: "genesis",
|
||||
Usage: "Genesis file for the new blockchain",
|
||||
Value: "",
|
||||
IBCRegisterTxCmd = &cobra.Command{
|
||||
Use: "register",
|
||||
Short: "Register a blockchain via IBC",
|
||||
Run: ibcRegisterTxCmd,
|
||||
}
|
||||
|
||||
IbcHeaderFlag = cli.StringFlag{
|
||||
Name: "header",
|
||||
Usage: "Block header for an ibc update",
|
||||
Value: "",
|
||||
IBCUpdateTxCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update the latest state of a blockchain via IBC",
|
||||
Run: ibcUpdateTxCmd,
|
||||
}
|
||||
|
||||
IbcCommitFlag = cli.StringFlag{
|
||||
Name: "commit",
|
||||
Usage: "Block commit for an ibc update",
|
||||
Value: "",
|
||||
IBCPacketTxCmd = &cobra.Command{
|
||||
Use: "packet",
|
||||
Short: "Send a new packet via IBC",
|
||||
}
|
||||
|
||||
IbcFromFlag = cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "Source ChainID",
|
||||
Value: "",
|
||||
IBCPacketCreateTxCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create an egress IBC packet",
|
||||
Run: ibcPacketCreateTxCmd,
|
||||
}
|
||||
|
||||
IbcToFlag = cli.StringFlag{
|
||||
Name: "to",
|
||||
Usage: "Destination ChainID",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
IbcTypeFlag = cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: "IBC packet type (eg. coin)",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
IbcPayloadFlag = cli.StringFlag{
|
||||
Name: "payload",
|
||||
Usage: "IBC packet payload",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
IbcPacketFlag = cli.StringFlag{
|
||||
Name: "packet",
|
||||
Usage: "hex-encoded IBC packet",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
IbcProofFlag = cli.StringFlag{
|
||||
Name: "proof",
|
||||
Usage: "hex-encoded proof of IBC packet from source chain",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
IbcSequenceFlag = cli.IntFlag{
|
||||
Name: "sequence",
|
||||
Usage: "sequence number for IBC packet",
|
||||
Value: 0,
|
||||
}
|
||||
|
||||
IbcHeightFlag = cli.IntFlag{
|
||||
Name: "height",
|
||||
Usage: "Height the packet became egress in source chain",
|
||||
Value: 0,
|
||||
IBCPacketPostTxCmd = &cobra.Command{
|
||||
Use: "post",
|
||||
Short: "Deliver an IBC packet to another chain",
|
||||
Run: ibcPacketPostTxCmd,
|
||||
}
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ibc commands
|
||||
|
||||
//flags
|
||||
var (
|
||||
IbcTxCmd = cli.Command{
|
||||
Name: "ibc",
|
||||
Usage: "an IBC transaction, for InterBlockchain Communication",
|
||||
Flags: TxFlags,
|
||||
Subcommands: []cli.Command{
|
||||
IbcRegisterTxCmd,
|
||||
IbcUpdateTxCmd,
|
||||
IbcPacketTxCmd,
|
||||
},
|
||||
}
|
||||
|
||||
IbcRegisterTxCmd = cli.Command{
|
||||
Name: "register",
|
||||
Usage: "Register a blockchain via IBC",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdIBCRegisterTx(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
IbcChainIDFlag,
|
||||
IbcGenesisFlag,
|
||||
},
|
||||
}
|
||||
|
||||
IbcUpdateTxCmd = cli.Command{
|
||||
Name: "update",
|
||||
Usage: "Update the latest state of a blockchain via IBC",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdIBCUpdateTx(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
IbcHeaderFlag,
|
||||
IbcCommitFlag,
|
||||
},
|
||||
}
|
||||
|
||||
IbcPacketTxCmd = cli.Command{
|
||||
Name: "packet",
|
||||
Usage: "Send a new packet via IBC",
|
||||
Subcommands: []cli.Command{
|
||||
IbcPacketCreateTx,
|
||||
IbcPacketPostTx,
|
||||
},
|
||||
}
|
||||
|
||||
IbcPacketCreateTx = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create an egress IBC packet",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdIBCPacketCreateTx(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
IbcFromFlag,
|
||||
IbcToFlag,
|
||||
IbcTypeFlag,
|
||||
IbcPayloadFlag,
|
||||
IbcSequenceFlag,
|
||||
},
|
||||
}
|
||||
|
||||
IbcPacketPostTx = cli.Command{
|
||||
Name: "post",
|
||||
Usage: "Deliver an IBC packet to another chain",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdIBCPacketPostTx(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
IbcFromFlag,
|
||||
IbcHeightFlag,
|
||||
IbcPacketFlag,
|
||||
IbcProofFlag,
|
||||
},
|
||||
}
|
||||
ibcChainIDFlag string
|
||||
ibcGenesisFlag string
|
||||
ibcHeaderFlag string
|
||||
ibcCommitFlag string
|
||||
ibcFromFlag string
|
||||
ibcToFlag string
|
||||
ibcTypeFlag string
|
||||
ibcPayloadFlag string
|
||||
ibcPacketFlag string
|
||||
ibcProofFlag string
|
||||
ibcSequenceFlag int
|
||||
ibcHeightFlag int
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
// register flags
|
||||
registerFlags := []Flag2Register{
|
||||
{&ibcChainIDFlag, "ibc_chain_id", "", "ChainID for the new blockchain"},
|
||||
{&ibcGenesisFlag, "genesis", "", "Genesis file for the new blockchain"},
|
||||
}
|
||||
|
||||
updateFlags := []Flag2Register{
|
||||
{&ibcHeaderFlag, "header", "", "Block header for an ibc update"},
|
||||
{&ibcCommitFlag, "commit", "", "Block commit for an ibc update"},
|
||||
}
|
||||
|
||||
fromFlagReg := Flag2Register{&ibcFromFlag, "ibc_from", "", "Source ChainID"}
|
||||
|
||||
packetCreateFlags := []Flag2Register{
|
||||
fromFlagReg,
|
||||
{&ibcToFlag, "to", "", "Destination ChainID"},
|
||||
{&ibcTypeFlag, "type", "", "IBC packet type (eg. coin},"},
|
||||
{&ibcPayloadFlag, "payload", "", "IBC packet payload"},
|
||||
{&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"},
|
||||
}
|
||||
|
||||
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"},
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ibc command implementations
|
||||
|
||||
func cmdIBCRegisterTx(c *cli.Context) error {
|
||||
chainID := c.String("chain_id")
|
||||
genesisFile := c.String("genesis")
|
||||
parent := c.Parent()
|
||||
func ibcRegisterTxCmd(cmd *cobra.Command, args []string) {
|
||||
chainID := ibcChainIDFlag
|
||||
genesisFile := ibcGenesisFlag
|
||||
|
||||
genesisBytes, err := ioutil.ReadFile(genesisFile)
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Error reading genesis file %v: %v", genesisFile, err))
|
||||
cmn.Exit(fmt.Sprintf("Error reading genesis file %v: %+v\n", genesisFile, err))
|
||||
}
|
||||
|
||||
ibcTx := ibc.IBCRegisterChainTx{
|
||||
@ -203,27 +140,31 @@ func cmdIBCRegisterTx(c *cli.Context) error {
|
||||
}{ibcTx}))
|
||||
name := "IBC"
|
||||
|
||||
return AppTx(parent, name, data)
|
||||
AppTx(name, data)
|
||||
}
|
||||
|
||||
func cmdIBCUpdateTx(c *cli.Context) error {
|
||||
headerBytes, err := hex.DecodeString(StripHex(c.String("header")))
|
||||
func ibcUpdateTxCmd(cmd *cobra.Command, args []string) {
|
||||
headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Header (%v) is invalid hex: %v", c.String("header"), err))
|
||||
cmn.Exit(fmt.Sprintf("Header (%v) is invalid hex: %+v\n", ibcHeaderFlag, err))
|
||||
}
|
||||
commitBytes, err := hex.DecodeString(StripHex(c.String("commit")))
|
||||
|
||||
commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Commit (%v) is invalid hex: %v", c.String("commit"), err))
|
||||
cmn.Exit(fmt.Sprintf("Commit (%v) is invalid hex: %+v\n", ibcCommitFlag, err))
|
||||
}
|
||||
|
||||
header := new(tmtypes.Header)
|
||||
commit := new(tmtypes.Commit)
|
||||
|
||||
if err := wire.ReadBinaryBytes(headerBytes, &header); err != nil {
|
||||
return errors.New(cmn.Fmt("Error unmarshalling header: %v", err))
|
||||
err = wire.ReadBinaryBytes(headerBytes, &header)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("Error unmarshalling header: %+v\n", err))
|
||||
}
|
||||
if err := wire.ReadBinaryBytes(commitBytes, &commit); err != nil {
|
||||
return errors.New(cmn.Fmt("Error unmarshalling commit: %v", err))
|
||||
|
||||
err = wire.ReadBinaryBytes(commitBytes, &commit)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("Error unmarshalling commit: %+v\n", err))
|
||||
}
|
||||
|
||||
ibcTx := ibc.IBCUpdateChainTx{
|
||||
@ -238,21 +179,21 @@ func cmdIBCUpdateTx(c *cli.Context) error {
|
||||
}{ibcTx}))
|
||||
name := "IBC"
|
||||
|
||||
return AppTx(c.Parent(), name, data)
|
||||
AppTx(name, data)
|
||||
}
|
||||
|
||||
func cmdIBCPacketCreateTx(c *cli.Context) error {
|
||||
fromChain, toChain := c.String("from"), c.String("to")
|
||||
packetType := c.String("type")
|
||||
func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) {
|
||||
fromChain, toChain := ibcFromFlag, ibcToFlag
|
||||
packetType := ibcTypeFlag
|
||||
|
||||
payloadBytes, err := hex.DecodeString(StripHex(c.String("payload")))
|
||||
payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Payload (%v) is invalid hex: %v", c.String("payload"), err))
|
||||
cmn.Exit(fmt.Sprintf("Payload (%v) is invalid hex: %+v\n", ibcPayloadFlag, err))
|
||||
}
|
||||
|
||||
sequence, err := getIBCSequence(c)
|
||||
sequence, err := ibcSequenceCmd()
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
ibcTx := ibc.IBCPacketCreateTx{
|
||||
@ -271,29 +212,33 @@ func cmdIBCPacketCreateTx(c *cli.Context) error {
|
||||
ibc.IBCTx `json:"unwrap"`
|
||||
}{ibcTx}))
|
||||
|
||||
return AppTx(c.Parent().Parent(), "IBC", data)
|
||||
AppTx("IBC", data)
|
||||
}
|
||||
|
||||
func cmdIBCPacketPostTx(c *cli.Context) error {
|
||||
fromChain, fromHeight := c.String("from"), c.Int("height")
|
||||
func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) {
|
||||
fromChain, fromHeight := ibcFromFlag, ibcHeightFlag
|
||||
|
||||
packetBytes, err := hex.DecodeString(StripHex(c.String("packet")))
|
||||
packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Packet (%v) is invalid hex: %v", c.String("packet"), err))
|
||||
cmn.Exit(fmt.Sprintf("Packet (%v) is invalid hex: %+v\n", ibcPacketFlag, err))
|
||||
}
|
||||
proofBytes, err := hex.DecodeString(StripHex(c.String("proof")))
|
||||
|
||||
proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err))
|
||||
cmn.Exit(fmt.Sprintf("Proof (%v) is invalid hex: %+v\n", ibcProofFlag, err))
|
||||
}
|
||||
|
||||
var packet ibc.Packet
|
||||
proof := new(merkle.IAVLProof)
|
||||
|
||||
if err := wire.ReadBinaryBytes(packetBytes, &packet); err != nil {
|
||||
return errors.New(cmn.Fmt("Error unmarshalling packet: %v", err))
|
||||
err = wire.ReadBinaryBytes(packetBytes, &packet)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("Error unmarshalling packet: %+v\n", err))
|
||||
}
|
||||
if err := wire.ReadBinaryBytes(proofBytes, &proof); err != nil {
|
||||
return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err))
|
||||
|
||||
err = wire.ReadBinaryBytes(proofBytes, &proof)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err))
|
||||
}
|
||||
|
||||
ibcTx := ibc.IBCPacketPostTx{
|
||||
@ -309,12 +254,12 @@ func cmdIBCPacketPostTx(c *cli.Context) error {
|
||||
ibc.IBCTx `json:"unwrap"`
|
||||
}{ibcTx}))
|
||||
|
||||
return AppTx(c.Parent().Parent(), "IBC", data)
|
||||
AppTx("IBC", data)
|
||||
}
|
||||
|
||||
func getIBCSequence(c *cli.Context) (uint64, error) {
|
||||
if c.IsSet("sequence") {
|
||||
return uint64(c.Int("sequence")), nil
|
||||
func ibcSequenceCmd() (uint64, error) {
|
||||
if ibcSequenceFlag >= 0 {
|
||||
return uint64(ibcSequenceFlag), nil
|
||||
}
|
||||
|
||||
// TODO: get sequence
|
||||
|
||||
@ -1,27 +1,38 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmn "github.com/tendermint/go-common"
|
||||
)
|
||||
|
||||
var InitCmd = cli.Command{
|
||||
Name: "init",
|
||||
Usage: "Initialize a basecoin blockchain",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdInit(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
ChainIDFlag,
|
||||
},
|
||||
}
|
||||
//commands
|
||||
var (
|
||||
InitCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize a basecoin blockchain",
|
||||
Run: initCmd,
|
||||
}
|
||||
)
|
||||
|
||||
func cmdInit(c *cli.Context) error {
|
||||
//flags
|
||||
//var chainIDFlag string
|
||||
|
||||
//func init() {
|
||||
//
|
||||
// //register flags
|
||||
// flags := []Flag2Register{
|
||||
// {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"},
|
||||
// }
|
||||
// RegisterFlags(InitCmd, flags)
|
||||
//
|
||||
//}
|
||||
|
||||
func initCmd(cmd *cobra.Command, args []string) {
|
||||
rootDir := BasecoinRoot("")
|
||||
|
||||
cmn.EnsureDir(rootDir, 0777)
|
||||
@ -32,22 +43,27 @@ func cmdInit(c *cli.Context) error {
|
||||
key1File := path.Join(rootDir, "key.json")
|
||||
key2File := path.Join(rootDir, "key2.json")
|
||||
|
||||
if err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644); err != nil {
|
||||
return err
|
||||
err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
if err := ioutil.WriteFile(privValFile, []byte(privValJSON), 0400); err != nil {
|
||||
return err
|
||||
|
||||
err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
if err := ioutil.WriteFile(key1File, []byte(key1JSON), 0400); err != nil {
|
||||
return err
|
||||
|
||||
err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
if err := ioutil.WriteFile(key2File, []byte(key2JSON), 0400); err != nil {
|
||||
return err
|
||||
|
||||
err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const privValJSON = `{
|
||||
|
||||
@ -8,38 +8,38 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmn "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
//commands
|
||||
var (
|
||||
KeyCmd = cli.Command{
|
||||
Name: "key",
|
||||
Usage: "Manage keys",
|
||||
ArgsUsage: "",
|
||||
Subcommands: []cli.Command{NewKeyCmd},
|
||||
KeyCmd = &cobra.Command{
|
||||
Use: "key",
|
||||
Short: "Manage keys",
|
||||
}
|
||||
|
||||
NewKeyCmd = cli.Command{
|
||||
Name: "new",
|
||||
Usage: "Create a new private key",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdNewKey(c)
|
||||
},
|
||||
NewKeyCmd = &cobra.Command{
|
||||
Use: "new",
|
||||
Short: "Create a new private key",
|
||||
Run: newKeyCmd,
|
||||
}
|
||||
)
|
||||
|
||||
func cmdNewKey(c *cli.Context) error {
|
||||
func newKeyCmd(cmd *cobra.Command, args []string) {
|
||||
key := genKey()
|
||||
keyJSON, err := json.MarshalIndent(key, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
fmt.Println(string(keyJSON))
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
//register commands
|
||||
KeyCmd.AddCommand(NewKeyCmd)
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
@ -88,12 +88,14 @@ func LoadKey(keyFile string) *Key {
|
||||
filePath := path.Join(BasecoinRoot(""), keyFile)
|
||||
keyJSONBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
key := new(Key)
|
||||
err = json.Unmarshal(keyJSONBytes, key)
|
||||
if err != nil {
|
||||
cmn.Exit(cmn.Fmt("Error reading key from %v: %v\n", filePath, err))
|
||||
cmn.Exit(fmt.Sprintf("Error reading key from %v: %v\n", filePath, err))
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
41
cmd/commands/plugin_util.go
Normal file
41
cmd/commands/plugin_util.go
Normal file
@ -0,0 +1,41 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
type plugin struct {
|
||||
name string
|
||||
newPlugin func() types.Plugin
|
||||
}
|
||||
|
||||
var plugins = []plugin{}
|
||||
|
||||
// RegisterStartPlugin is used to enable a plugin
|
||||
func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
|
||||
plugins = append(plugins, plugin{name: name, newPlugin: newPlugin})
|
||||
}
|
||||
|
||||
// Register a subcommand of QueryCmd for plugin specific query functionality
|
||||
func RegisterQuerySubcommand(cmd *cobra.Command) {
|
||||
QueryCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
// Register a subcommand of TxCmd to craft transactions for plugins
|
||||
func RegisterTxSubcommand(cmd *cobra.Command) {
|
||||
TxCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
//Returns a version command based on version input
|
||||
func QuickVersionCmd(version string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Show version info",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(version)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,10 @@ package commands
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmn "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-merkle"
|
||||
@ -14,85 +13,85 @@ import (
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
//commands
|
||||
var (
|
||||
QueryCmd = cli.Command{
|
||||
Name: "query",
|
||||
Usage: "Query the merkle tree",
|
||||
ArgsUsage: "<key>",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdQuery(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NodeFlag,
|
||||
},
|
||||
QueryCmd = &cobra.Command{
|
||||
Use: "query [key]",
|
||||
Short: "Query the merkle tree",
|
||||
Run: queryCmd,
|
||||
}
|
||||
|
||||
AccountCmd = cli.Command{
|
||||
Name: "account",
|
||||
Usage: "Get details of an account",
|
||||
ArgsUsage: "<address>",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdAccount(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NodeFlag,
|
||||
},
|
||||
AccountCmd = &cobra.Command{
|
||||
Use: "account [address]",
|
||||
Short: "Get details of an account",
|
||||
Run: accountCmd,
|
||||
}
|
||||
|
||||
BlockCmd = cli.Command{
|
||||
Name: "block",
|
||||
Usage: "Get the header and commit of a block",
|
||||
ArgsUsage: "<height>",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdBlock(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NodeFlag,
|
||||
},
|
||||
BlockCmd = &cobra.Command{
|
||||
Use: "block [height]",
|
||||
Short: "Get the header and commit of a block",
|
||||
Run: blockCmd,
|
||||
}
|
||||
|
||||
VerifyCmd = cli.Command{
|
||||
Name: "verify",
|
||||
Usage: "Verify the IAVL proof",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdVerify(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
ProofFlag,
|
||||
KeyFlag,
|
||||
ValueFlag,
|
||||
RootFlag,
|
||||
},
|
||||
VerifyCmd = &cobra.Command{
|
||||
Use: "verify",
|
||||
Short: "Verify the IAVL proof",
|
||||
Run: verifyCmd,
|
||||
}
|
||||
)
|
||||
|
||||
// Register a subcommand of QueryCmd for plugin specific query functionality
|
||||
func RegisterQuerySubcommand(cmd cli.Command) {
|
||||
QueryCmd.Subcommands = append(QueryCmd.Subcommands, cmd)
|
||||
//flags
|
||||
var (
|
||||
nodeFlag string
|
||||
proofFlag string
|
||||
keyFlag string
|
||||
valueFlag string
|
||||
rootFlag string
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
commonFlags := []Flag2Register{
|
||||
{&nodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"},
|
||||
}
|
||||
|
||||
verifyFlags := []Flag2Register{
|
||||
{&proofFlag, "proof", "", "hex-encoded IAVL proof"},
|
||||
{&keyFlag, "key", "", "key to the IAVL tree"},
|
||||
{&valueFlag, "value", "", "value in the IAVL tree"},
|
||||
{&rootFlag, "root", "", "root hash of the IAVL tree"},
|
||||
}
|
||||
|
||||
RegisterFlags(QueryCmd, commonFlags)
|
||||
RegisterFlags(AccountCmd, commonFlags)
|
||||
RegisterFlags(BlockCmd, commonFlags)
|
||||
RegisterFlags(VerifyCmd, verifyFlags)
|
||||
}
|
||||
|
||||
func cmdQuery(c *cli.Context) error {
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.New("query command requires an argument ([key])")
|
||||
func queryCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
if len(args) != 1 {
|
||||
cmn.Exit("query command requires an argument ([key])")
|
||||
}
|
||||
keyString := c.Args()[0]
|
||||
|
||||
keyString := args[0]
|
||||
key := []byte(keyString)
|
||||
if isHex(keyString) {
|
||||
// convert key to bytes
|
||||
var err error
|
||||
key, err = hex.DecodeString(StripHex(keyString))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Query key (%v) is invalid hex: %v", keyString, err))
|
||||
cmn.Exit(fmt.Sprintf("Query key (%v) is invalid hex: %+v\n", keyString, err))
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := Query(c.String("node"), key)
|
||||
resp, err := Query(nodeFlag, key)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("Query returns error: %+v\n", err))
|
||||
}
|
||||
|
||||
if !resp.Code.IsOK() {
|
||||
return errors.New(cmn.Fmt("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log))
|
||||
cmn.Exit(fmt.Sprintf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log))
|
||||
}
|
||||
|
||||
val := resp.Value
|
||||
@ -104,43 +103,44 @@ func cmdQuery(c *cli.Context) error {
|
||||
Proof []byte `json:"proof"`
|
||||
Height uint64 `json:"height"`
|
||||
}{val, proof, height})))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdAccount(c *cli.Context) error {
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.New("account command requires an argument ([address])")
|
||||
func accountCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
if len(args) != 1 {
|
||||
cmn.Exit("account command requires an argument ([address])")
|
||||
}
|
||||
addrHex := StripHex(c.Args()[0])
|
||||
|
||||
addrHex := StripHex(args[0])
|
||||
|
||||
// convert destination address to bytes
|
||||
addr, err := hex.DecodeString(addrHex)
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Account address (%v) is invalid hex: %v", addrHex, err))
|
||||
cmn.Exit(fmt.Sprintf("Account address (%v) is invalid hex: %+v\n", addrHex, err))
|
||||
}
|
||||
|
||||
acc, err := getAcc(c.String("node"), addr)
|
||||
acc, err := getAcc(nodeFlag, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
fmt.Println(string(wire.JSONBytes(acc)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdBlock(c *cli.Context) error {
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.New("block command requires an argument ([height])")
|
||||
}
|
||||
heightString := c.Args()[0]
|
||||
height, err := strconv.Atoi(heightString)
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Height must be an int, got %v: %v", heightString, err))
|
||||
func blockCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
if len(args) != 1 {
|
||||
cmn.Exit("block command requires an argument ([height])")
|
||||
}
|
||||
|
||||
header, commit, err := getHeaderAndCommit(c, height)
|
||||
heightString := args[0]
|
||||
height, err := strconv.Atoi(heightString)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("Height must be an int, got %v: %+v\n", heightString, err))
|
||||
}
|
||||
|
||||
header, commit, err := getHeaderAndCommit(nodeFlag, height)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
fmt.Println(string(wire.JSONBytes(struct {
|
||||
@ -156,8 +156,6 @@ func cmdBlock(c *cli.Context) error {
|
||||
Commit: commit,
|
||||
},
|
||||
})))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type BlockHex struct {
|
||||
@ -170,15 +168,16 @@ type BlockJSON struct {
|
||||
Commit *tmtypes.Commit `json:"commit"`
|
||||
}
|
||||
|
||||
func cmdVerify(c *cli.Context) error {
|
||||
keyString, valueString := c.String("key"), c.String("value")
|
||||
func verifyCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
keyString, valueString := keyFlag, valueFlag
|
||||
|
||||
var err error
|
||||
key := []byte(keyString)
|
||||
if isHex(keyString) {
|
||||
key, err = hex.DecodeString(StripHex(keyString))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Key (%v) is invalid hex: %v", keyString, err))
|
||||
cmn.Exit(fmt.Sprintf("Key (%v) is invalid hex: %+v\n", keyString, err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,29 +185,25 @@ func cmdVerify(c *cli.Context) error {
|
||||
if isHex(valueString) {
|
||||
value, err = hex.DecodeString(StripHex(valueString))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Value (%v) is invalid hex: %v", valueString, err))
|
||||
cmn.Exit(fmt.Sprintf("Value (%v) is invalid hex: %+v\n", valueString, err))
|
||||
}
|
||||
}
|
||||
|
||||
root, err := hex.DecodeString(StripHex(c.String("root")))
|
||||
root, err := hex.DecodeString(StripHex(rootFlag))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Root (%v) is invalid hex: %v", c.String("root"), err))
|
||||
cmn.Exit(fmt.Sprintf("Root (%v) is invalid hex: %+v\n", rootFlag, err))
|
||||
}
|
||||
|
||||
proofBytes, err := hex.DecodeString(StripHex(c.String("proof")))
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err))
|
||||
}
|
||||
proofBytes, err := hex.DecodeString(StripHex(proofFlag))
|
||||
|
||||
proof, err := merkle.ReadProof(proofBytes)
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err))
|
||||
cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err))
|
||||
}
|
||||
|
||||
if proof.Verify(key, value, root) {
|
||||
fmt.Println("OK")
|
||||
} else {
|
||||
return errors.New("Proof does not verify")
|
||||
cmn.Exit(fmt.Sprintf("Proof does not verify"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,47 +1,24 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
tmcfg "github.com/tendermint/tendermint/config/tendermint"
|
||||
types "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
var UnsafeResetAllCmd = cli.Command{
|
||||
Name: "unsafe_reset_all",
|
||||
Usage: "Reset all blockchain data",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdUnsafeResetAll(c)
|
||||
},
|
||||
var UnsafeResetAllCmd = &cobra.Command{
|
||||
Use: "unsafe_reset_all",
|
||||
Short: "Reset all blockchain data",
|
||||
Run: unsafeResetAllCmd,
|
||||
}
|
||||
|
||||
func cmdUnsafeResetAll(c *cli.Context) error {
|
||||
func unsafeResetAllCmd(cmd *cobra.Command, args []string) {
|
||||
basecoinDir := BasecoinRoot("")
|
||||
tmDir := path.Join(basecoinDir)
|
||||
tmConfig := tmcfg.GetConfig(tmDir)
|
||||
|
||||
// Get and Reset PrivValidator
|
||||
var privValidator *types.PrivValidator
|
||||
privValidatorFile := tmConfig.GetString("priv_validator_file")
|
||||
if _, err := os.Stat(privValidatorFile); err == nil {
|
||||
privValidator = types.LoadPrivValidator(privValidatorFile)
|
||||
privValidator.Reset()
|
||||
log.Notice("Reset PrivValidator", "file", privValidatorFile)
|
||||
} else {
|
||||
privValidator = types.GenPrivValidator()
|
||||
privValidator.SetFile(privValidatorFile)
|
||||
privValidator.Save()
|
||||
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
||||
}
|
||||
|
||||
// Remove all tendermint data
|
||||
tmDataDir := tmConfig.GetString("db_dir")
|
||||
os.RemoveAll(tmDataDir)
|
||||
log.Notice("Removed all data", "dir", tmDataDir)
|
||||
|
||||
return nil
|
||||
commands.ResetAll(tmConfig, log)
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
@ -18,50 +17,51 @@ import (
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/tendermint/basecoin/app"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
var StartCmd = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start basecoin",
|
||||
Run: startCmd,
|
||||
}
|
||||
|
||||
//flags
|
||||
var (
|
||||
addrFlag string
|
||||
eyesFlag string
|
||||
dirFlag string
|
||||
withoutTendermintFlag bool
|
||||
)
|
||||
|
||||
// TODO: move to config file
|
||||
const EyesCacheSize = 10000
|
||||
|
||||
var StartCmd = cli.Command{
|
||||
Name: "start",
|
||||
Usage: "Start basecoin",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdStart(c)
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
AddrFlag,
|
||||
EyesFlag,
|
||||
WithoutTendermintFlag,
|
||||
ChainIDFlag,
|
||||
},
|
||||
func init() {
|
||||
|
||||
flags := []Flag2Register{
|
||||
{&addrFlag, "address", "tcp://0.0.0.0:46658", "Listen address"},
|
||||
{&eyesFlag, "eyes", "local", "MerkleEyes address, or 'local' for embedded"},
|
||||
{&dirFlag, "dir", ".", "Root directory"},
|
||||
{&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"},
|
||||
}
|
||||
RegisterFlags(StartCmd, flags)
|
||||
|
||||
// TODO: move to config file
|
||||
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
||||
}
|
||||
|
||||
type plugin struct {
|
||||
name string
|
||||
newPlugin func() types.Plugin
|
||||
}
|
||||
|
||||
var plugins = []plugin{}
|
||||
|
||||
// RegisterStartPlugin is used to enable a plugin
|
||||
func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
|
||||
plugins = append(plugins, plugin{name: name, newPlugin: newPlugin})
|
||||
}
|
||||
|
||||
func cmdStart(c *cli.Context) error {
|
||||
func startCmd(cmd *cobra.Command, args []string) {
|
||||
basecoinDir := BasecoinRoot("")
|
||||
|
||||
// Connect to MerkleEyes
|
||||
var eyesCli *eyes.Client
|
||||
if c.String("eyes") == "local" {
|
||||
if eyesFlag == "local" {
|
||||
eyesCli = eyes.NewLocalClient(path.Join(basecoinDir, "data", "merkleeyes.db"), EyesCacheSize)
|
||||
} else {
|
||||
var err error
|
||||
eyesCli, err = eyes.NewClient(c.String("eyes"))
|
||||
eyesCli, err = eyes.NewClient(eyesFlag)
|
||||
if err != nil {
|
||||
return errors.New("connect to MerkleEyes: " + err.Error())
|
||||
cmn.Exit(fmt.Sprintf("Error connecting to MerkleEyes: %+v\n", err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ func cmdStart(c *cli.Context) error {
|
||||
if _, err := os.Stat(genesisFile); err == nil {
|
||||
err := basecoinApp.LoadGenesis(genesisFile)
|
||||
if err != nil {
|
||||
return errors.New(cmn.Fmt("%+v", err))
|
||||
cmn.Exit(fmt.Sprintf("Error in LoadGenesis: %+v\n", err))
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("No genesis file at %s, skipping...\n", genesisFile)
|
||||
@ -92,40 +92,37 @@ func cmdStart(c *cli.Context) error {
|
||||
}
|
||||
|
||||
chainID := basecoinApp.GetState().GetChainID()
|
||||
if c.Bool("without-tendermint") {
|
||||
if withoutTendermintFlag {
|
||||
log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID)
|
||||
// run just the abci app/server
|
||||
return startBasecoinABCI(c, basecoinApp)
|
||||
startBasecoinABCI(basecoinApp)
|
||||
} else {
|
||||
log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID)
|
||||
// start the app with tendermint in-process
|
||||
return startTendermint(basecoinDir, basecoinApp)
|
||||
startTendermint(basecoinDir, basecoinApp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startBasecoinABCI(c *cli.Context, basecoinApp *app.Basecoin) error {
|
||||
func startBasecoinABCI(basecoinApp *app.Basecoin) {
|
||||
|
||||
// Start the ABCI listener
|
||||
svr, err := server.NewServer(c.String("address"), "socket", basecoinApp)
|
||||
svr, err := server.NewServer(addrFlag, "socket", basecoinApp)
|
||||
if err != nil {
|
||||
return errors.New("create listener: " + err.Error())
|
||||
cmn.Exit(fmt.Sprintf("Error creating listener: %+v\n", err))
|
||||
}
|
||||
|
||||
// Wait forever
|
||||
cmn.TrapSignal(func() {
|
||||
// Cleanup
|
||||
svr.Stop()
|
||||
})
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||
func startTendermint(dir string, basecoinApp *app.Basecoin) {
|
||||
|
||||
// Get configuration
|
||||
tmConfig := tmcfg.GetConfig(dir)
|
||||
|
||||
// logger.SetLogLevel("notice") //config.GetString("log_level"))
|
||||
|
||||
// parseFlags(config, args[1:]) // Command line overrides
|
||||
|
||||
// Create & start tendermint node
|
||||
@ -135,7 +132,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||
|
||||
_, err := n.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
// Wait forever
|
||||
@ -143,6 +140,4 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||
// Cleanup
|
||||
n.Stop()
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -2,10 +2,10 @@ package commands
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
@ -16,211 +16,215 @@ import (
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
var TxFlags = []cli.Flag{
|
||||
NodeFlag,
|
||||
ChainIDFlag,
|
||||
|
||||
FromFlag,
|
||||
|
||||
AmountFlag,
|
||||
GasFlag,
|
||||
FeeFlag,
|
||||
SeqFlag,
|
||||
}
|
||||
|
||||
//commands
|
||||
var (
|
||||
TxCmd = cli.Command{
|
||||
Name: "tx",
|
||||
Usage: "Create, sign, and broadcast a transaction",
|
||||
ArgsUsage: "",
|
||||
Subcommands: []cli.Command{
|
||||
SendTxCmd,
|
||||
AppTxCmd,
|
||||
IbcTxCmd,
|
||||
},
|
||||
TxCmd = &cobra.Command{
|
||||
Use: "tx",
|
||||
Short: "Create, sign, and broadcast a transaction",
|
||||
}
|
||||
|
||||
SendTxCmd = cli.Command{
|
||||
Name: "send",
|
||||
Usage: "a SendTx transaction, for sending tokens around",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdSendTx(c)
|
||||
},
|
||||
Flags: append(TxFlags, ToFlag),
|
||||
SendTxCmd = &cobra.Command{
|
||||
Use: "send",
|
||||
Short: "A SendTx transaction, for sending tokens around",
|
||||
Run: sendTxCmd,
|
||||
}
|
||||
|
||||
AppTxCmd = cli.Command{
|
||||
Name: "app",
|
||||
Usage: "an AppTx transaction, for sending raw data to plugins",
|
||||
ArgsUsage: "",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdAppTx(c)
|
||||
},
|
||||
Flags: append(TxFlags, NameFlag, DataFlag),
|
||||
// Subcommands are dynamically registered with plugins as needed
|
||||
Subcommands: []cli.Command{},
|
||||
AppTxCmd = &cobra.Command{
|
||||
Use: "app",
|
||||
Short: "An AppTx transaction, for sending raw data to plugins",
|
||||
Run: appTxCmd,
|
||||
}
|
||||
)
|
||||
|
||||
// Register a subcommand of TxCmd to craft transactions for plugins
|
||||
func RegisterTxSubcommand(cmd cli.Command) {
|
||||
TxCmd.Subcommands = append(TxCmd.Subcommands, cmd)
|
||||
//flags
|
||||
var (
|
||||
txNodeFlag string
|
||||
toFlag string
|
||||
amountFlag string
|
||||
fromFlag string
|
||||
seqFlag int
|
||||
gasFlag int
|
||||
feeFlag string
|
||||
dataFlag string
|
||||
nameFlag string
|
||||
chainIDFlag string
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
// register flags
|
||||
cmdTxFlags := []Flag2Register{
|
||||
{&txNodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"},
|
||||
{&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"},
|
||||
{&fromFlag, "from", "key.json", "Path to a private key to sign the transaction"},
|
||||
{&amountFlag, "amount", "", "Coins to send in transaction of the format <amt><coin>,<amt2><coin2>,... (eg: 1btc,2gold,5silver},"},
|
||||
{&gasFlag, "gas", 0, "The amount of gas for the transaction"},
|
||||
{&feeFlag, "fee", "", "Coins for the transaction fee of the format <amt><coin>"},
|
||||
{&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate},"},
|
||||
}
|
||||
|
||||
sendTxFlags := []Flag2Register{
|
||||
{&toFlag, "to", "", "Destination address for the transaction"},
|
||||
}
|
||||
|
||||
appTxFlags := []Flag2Register{
|
||||
{&nameFlag, "name", "", "Plugin to send the transaction to"},
|
||||
{&dataFlag, "data", "", "Data to send with the transaction"},
|
||||
}
|
||||
|
||||
RegisterPersistentFlags(TxCmd, cmdTxFlags)
|
||||
RegisterFlags(SendTxCmd, sendTxFlags)
|
||||
RegisterFlags(AppTxCmd, appTxFlags)
|
||||
|
||||
//register commands
|
||||
TxCmd.AddCommand(SendTxCmd, AppTxCmd)
|
||||
}
|
||||
|
||||
func cmdSendTx(c *cli.Context) error {
|
||||
toHex := c.String("to")
|
||||
fromFile := c.String("from")
|
||||
amount := c.String("amount")
|
||||
gas := int64(c.Int("gas"))
|
||||
fee := c.String("fee")
|
||||
chainID := c.String("chain_id")
|
||||
func sendTxCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
// convert destination address to bytes
|
||||
to, err := hex.DecodeString(StripHex(toHex))
|
||||
to, err := hex.DecodeString(StripHex(toFlag))
|
||||
if err != nil {
|
||||
return errors.New("To address is invalid hex: " + err.Error())
|
||||
cmn.Exit(fmt.Sprintf("To address is invalid hex: %+v\n", err))
|
||||
}
|
||||
|
||||
// load the priv key
|
||||
privKey := LoadKey(fromFile)
|
||||
privKey := LoadKey(fromFlag)
|
||||
|
||||
// get the sequence number for the tx
|
||||
sequence, err := getSeq(c, privKey.Address[:])
|
||||
sequence, err := getSeq(privKey.Address[:])
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := types.ParseCoin(fee)
|
||||
feeCoin, err := types.ParseCoin(feeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
amountCoins, err := types.ParseCoins(amount)
|
||||
amountCoins, err := types.ParseCoins(amountFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
// craft the tx
|
||||
input := types.NewTxInput(privKey.PubKey, amountCoins, sequence)
|
||||
output := newOutput(to, amountCoins)
|
||||
tx := &types.SendTx{
|
||||
Gas: gas,
|
||||
Gas: int64(gasFlag),
|
||||
Fee: feeCoin,
|
||||
Inputs: []types.TxInput{input},
|
||||
Outputs: []types.TxOutput{output},
|
||||
}
|
||||
|
||||
// sign that puppy
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
signBytes := tx.SignBytes(chainIDFlag)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{privKey.Sign(signBytes)}
|
||||
|
||||
fmt.Println("Signed SendTx:")
|
||||
fmt.Println(string(wire.JSONBytes(tx)))
|
||||
|
||||
// broadcast the transaction to tendermint
|
||||
data, log, err := broadcastTx(c, tx)
|
||||
data, log, err := broadcastTx(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
fmt.Printf("Response: %X ; %s\n", data, log)
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdAppTx(c *cli.Context) error {
|
||||
func appTxCmd(cmd *cobra.Command, args []string) {
|
||||
// convert data to bytes
|
||||
dataString := c.String("data")
|
||||
data := []byte(dataString)
|
||||
if isHex(dataString) {
|
||||
data, _ = hex.DecodeString(dataString)
|
||||
data := []byte(dataFlag)
|
||||
if isHex(dataFlag) {
|
||||
data, _ = hex.DecodeString(dataFlag)
|
||||
}
|
||||
name := c.String("name")
|
||||
return AppTx(c, name, data)
|
||||
name := nameFlag
|
||||
AppTx(name, data)
|
||||
}
|
||||
|
||||
func AppTx(c *cli.Context, name string, data []byte) error {
|
||||
fromFile := c.String("from")
|
||||
amount := c.String("amount")
|
||||
fee := c.String("fee")
|
||||
gas := int64(c.Int("gas"))
|
||||
chainID := c.String("chain_id")
|
||||
func AppTx(name string, data []byte) {
|
||||
|
||||
privKey := LoadKey(fromFile)
|
||||
privKey := LoadKey(fromFlag)
|
||||
|
||||
sequence, err := getSeq(c, privKey.Address[:])
|
||||
sequence, err := getSeq(privKey.Address[:])
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
//parse the fee and amounts into coin types
|
||||
feeCoin, err := types.ParseCoin(fee)
|
||||
feeCoin, err := types.ParseCoin(feeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
amountCoins, err := types.ParseCoins(amount)
|
||||
|
||||
amountCoins, err := types.ParseCoins(amountFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
|
||||
input := types.NewTxInput(privKey.PubKey, amountCoins, sequence)
|
||||
tx := &types.AppTx{
|
||||
Gas: gas,
|
||||
Gas: int64(gasFlag),
|
||||
Fee: feeCoin,
|
||||
Name: name,
|
||||
Input: input,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainID))}
|
||||
tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainIDFlag))}
|
||||
|
||||
fmt.Println("Signed AppTx:")
|
||||
fmt.Println(string(wire.JSONBytes(tx)))
|
||||
|
||||
data, log, err := broadcastTx(c, tx)
|
||||
data, log, err := broadcastTx(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
fmt.Printf("Response: %X ; %s\n", data, log)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// broadcast the transaction to tendermint
|
||||
func broadcastTx(c *cli.Context, tx types.Tx) ([]byte, string, error) {
|
||||
func broadcastTx(tx types.Tx) ([]byte, string, error) {
|
||||
|
||||
tmResult := new(ctypes.TMResult)
|
||||
tmAddr := c.String("node")
|
||||
uriClient := client.NewURIClient(tmAddr)
|
||||
uriClient := client.NewURIClient(txNodeFlag)
|
||||
|
||||
// Don't you hate having to do this?
|
||||
// How many times have I lost an hour over this trick?!
|
||||
txBytes := []byte(wire.BinaryBytes(struct {
|
||||
types.Tx `json:"unwrap"`
|
||||
}{tx}))
|
||||
|
||||
_, err := uriClient.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult)
|
||||
if err != nil {
|
||||
return nil, "", errors.New(cmn.Fmt("Error on broadcast tx: %v", err))
|
||||
}
|
||||
|
||||
res := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
|
||||
|
||||
// if it fails check, we don't even get a delivertx back!
|
||||
if !res.CheckTx.Code.IsOK() {
|
||||
r := res.CheckTx
|
||||
return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log))
|
||||
}
|
||||
|
||||
if !res.DeliverTx.Code.IsOK() {
|
||||
r := res.DeliverTx
|
||||
return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log))
|
||||
}
|
||||
|
||||
return res.DeliverTx.Data, res.DeliverTx.Log, nil
|
||||
}
|
||||
|
||||
// if the sequence flag is set, return it;
|
||||
// else, fetch the account by querying the app and return the sequence number
|
||||
func getSeq(c *cli.Context, address []byte) (int, error) {
|
||||
if c.IsSet("sequence") {
|
||||
return c.Int("sequence"), nil
|
||||
func getSeq(address []byte) (int, error) {
|
||||
|
||||
if seqFlag >= 0 {
|
||||
return seqFlag, nil
|
||||
}
|
||||
tmAddr := c.String("node")
|
||||
acc, err := getAcc(tmAddr, address)
|
||||
|
||||
acc, err := getAcc(txNodeFlag, address)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -232,5 +236,4 @@ func newOutput(to []byte, amount types.Coins) types.TxOutput {
|
||||
Address: to,
|
||||
Coins: amount,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,16 +2,17 @@ package commands
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
client "github.com/tendermint/go-rpc/client"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
@ -28,6 +29,60 @@ func BasecoinRoot(rootDir string) string {
|
||||
return rootDir
|
||||
}
|
||||
|
||||
type Flag2Register struct {
|
||||
Pointer interface{}
|
||||
Use string
|
||||
Value interface{}
|
||||
Desc string
|
||||
}
|
||||
|
||||
//register flag utils
|
||||
func RegisterFlags(c *cobra.Command, flags []Flag2Register) {
|
||||
registerFlags(c, flags, false)
|
||||
}
|
||||
|
||||
func RegisterPersistentFlags(c *cobra.Command, flags []Flag2Register) {
|
||||
registerFlags(c, flags, true)
|
||||
}
|
||||
|
||||
func registerFlags(c *cobra.Command, flags []Flag2Register, persistent bool) {
|
||||
|
||||
var flagset *pflag.FlagSet
|
||||
if persistent {
|
||||
flagset = c.PersistentFlags()
|
||||
} else {
|
||||
flagset = c.Flags()
|
||||
}
|
||||
|
||||
for _, f := range flags {
|
||||
|
||||
ok := false
|
||||
|
||||
switch f.Value.(type) {
|
||||
case string:
|
||||
if _, ok = f.Pointer.(*string); ok {
|
||||
flagset.StringVar(f.Pointer.(*string), f.Use, f.Value.(string), f.Desc)
|
||||
}
|
||||
case int:
|
||||
if _, ok = f.Pointer.(*int); ok {
|
||||
flagset.IntVar(f.Pointer.(*int), f.Use, f.Value.(int), f.Desc)
|
||||
}
|
||||
case uint64:
|
||||
if _, ok = f.Pointer.(*uint64); ok {
|
||||
flagset.Uint64Var(f.Pointer.(*uint64), f.Use, f.Value.(uint64), f.Desc)
|
||||
}
|
||||
case bool:
|
||||
if _, ok = f.Pointer.(*bool); ok {
|
||||
flagset.BoolVar(f.Pointer.(*bool), f.Use, f.Value.(bool), f.Desc)
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
panic("improper use of RegisterFlags")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true for non-empty hex-string prefixed with "0x"
|
||||
func isHex(s string) bool {
|
||||
if len(s) > 2 && s[:2] == "0x" {
|
||||
@ -58,11 +113,11 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) {
|
||||
}
|
||||
_, err := uriClient.Call("abci_query", params, tmResult)
|
||||
if err != nil {
|
||||
return nil, errors.New(cmn.Fmt("Error calling /abci_query: %v", err))
|
||||
return nil, errors.New(fmt.Sprintf("Error calling /abci_query: %v", err))
|
||||
}
|
||||
res := (*tmResult).(*ctypes.ResultABCIQuery)
|
||||
if !res.Response.Code.IsOK() {
|
||||
return nil, errors.New(cmn.Fmt("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log))
|
||||
return nil, errors.New(fmt.Sprintf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log))
|
||||
}
|
||||
return &res.Response, nil
|
||||
}
|
||||
@ -79,28 +134,27 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) {
|
||||
accountBytes := response.Value
|
||||
|
||||
if len(accountBytes) == 0 {
|
||||
return nil, errors.New(cmn.Fmt("Account bytes are empty for address: %X ", address))
|
||||
return nil, errors.New(fmt.Sprintf("Account bytes are empty for address: %X ", address))
|
||||
}
|
||||
|
||||
var acc *types.Account
|
||||
err = wire.ReadBinaryBytes(accountBytes, &acc)
|
||||
if err != nil {
|
||||
return nil, errors.New(cmn.Fmt("Error reading account %X error: %v",
|
||||
return nil, errors.New(fmt.Sprintf("Error reading account %X error: %v",
|
||||
accountBytes, err.Error()))
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) {
|
||||
func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Commit, error) {
|
||||
tmResult := new(ctypes.TMResult)
|
||||
tmAddr := c.String("node")
|
||||
uriClient := client.NewURIClient(tmAddr)
|
||||
|
||||
method := "commit"
|
||||
_, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult)
|
||||
if err != nil {
|
||||
return nil, nil, errors.New(cmn.Fmt("Error on %s: %v", method, err))
|
||||
return nil, nil, errors.New(fmt.Sprintf("Error on %s: %v", method, err))
|
||||
}
|
||||
resCommit := (*tmResult).(*ctypes.ResultCommit)
|
||||
header := resCommit.Header
|
||||
|
||||
17
cmd/commands/version.go
Normal file
17
cmd/commands/version.go
Normal file
@ -0,0 +1,17 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/version"
|
||||
)
|
||||
|
||||
var VersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Show version info",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(version.Version)
|
||||
},
|
||||
}
|
||||
@ -3,46 +3,47 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tendermint/basecoin/cmd/commands"
|
||||
"github.com/tendermint/basecoin/plugins/counter"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
)
|
||||
|
||||
//commands
|
||||
var CounterTxCmd = &cobra.Command{
|
||||
Use: "counter",
|
||||
Short: "Create, sign, and broadcast a transaction to the counter plugin",
|
||||
Run: counterTxCmd,
|
||||
}
|
||||
|
||||
//flags
|
||||
var (
|
||||
validFlag bool
|
||||
countFeeFlag string
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
CounterTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set valid field in CounterTx")
|
||||
CounterTxCmd.Flags().StringVar(&countFeeFlag, "countfee", "", "Coins for the counter fee of the format <amt><coin>")
|
||||
|
||||
commands.RegisterTxSubcommand(CounterTxCmd)
|
||||
commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() })
|
||||
}
|
||||
|
||||
var (
|
||||
ValidFlag = cli.BoolFlag{
|
||||
Name: "valid",
|
||||
Usage: "Set valid field in CounterTx",
|
||||
}
|
||||
func counterTxCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
CounterTxCmd = cli.Command{
|
||||
Name: "counter",
|
||||
Usage: "Create, sign, and broadcast a transaction to the counter plugin",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdCounterTx(c)
|
||||
},
|
||||
Flags: append(commands.TxFlags, ValidFlag),
|
||||
countFee, err := commands.ParseCoins(countFeeFlag)
|
||||
if err != nil {
|
||||
cmn.Exit(fmt.Sprintf("%+v\n", err))
|
||||
}
|
||||
)
|
||||
|
||||
func cmdCounterTx(c *cli.Context) error {
|
||||
valid := c.Bool("valid")
|
||||
|
||||
counterTx := counter.CounterTx{
|
||||
Valid: valid,
|
||||
Fee: types.Coins{
|
||||
{
|
||||
Denom: c.String("coin"),
|
||||
Amount: int64(c.Int("fee")),
|
||||
},
|
||||
},
|
||||
Valid: validFlag,
|
||||
Fee: countFee,
|
||||
}
|
||||
|
||||
fmt.Println("CounterTx:", string(wire.JSONBytes(counterTx)))
|
||||
@ -50,5 +51,5 @@ func cmdCounterTx(c *cli.Context) error {
|
||||
data := wire.BinaryBytes(counterTx)
|
||||
name := "counter"
|
||||
|
||||
return commands.AppTx(c, name, data)
|
||||
commands.AppTx(name, data)
|
||||
}
|
||||
|
||||
@ -1,23 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/cmd/commands"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "counter"
|
||||
app.Usage = "counter [command] [args...]"
|
||||
app.Version = "0.1.0"
|
||||
app.Commands = []cli.Command{
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "counter",
|
||||
Short: "demo plugin for basecoin",
|
||||
}
|
||||
|
||||
RootCmd.AddCommand(
|
||||
commands.StartCmd,
|
||||
commands.TxCmd,
|
||||
commands.KeyCmd,
|
||||
commands.QueryCmd,
|
||||
commands.KeyCmd,
|
||||
commands.VerifyCmd,
|
||||
commands.BlockCmd,
|
||||
commands.AccountCmd,
|
||||
commands.QuickVersionCmd("0.1.0"),
|
||||
)
|
||||
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
||||
@ -103,14 +103,14 @@ sleep 3
|
||||
echo "... registering chain1 on chain2"
|
||||
echo ""
|
||||
# register chain1 on chain2
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --ibc_chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
|
||||
|
||||
echo ""
|
||||
echo "... creating egress packet on chain1"
|
||||
echo ""
|
||||
# create a packet on chain1 destined for chain2
|
||||
PAYLOAD="DEADBEEF" #TODO
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --sequence 1
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --ibc_from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --ibc_sequence 1
|
||||
|
||||
echo ""
|
||||
echo "... querying for packet data"
|
||||
@ -162,7 +162,7 @@ echo ""
|
||||
echo "... posting packet from chain1 on chain2"
|
||||
echo ""
|
||||
# post the packet from chain1 to chain2
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF
|
||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --ibc_from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF
|
||||
|
||||
echo ""
|
||||
echo "... checking if the packet is present on chain2"
|
||||
|
||||
@ -25,18 +25,30 @@ The `main.go` is very simple and does not need to be changed:
|
||||
|
||||
```golang
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "example-plugin"
|
||||
app.Usage = "example-plugin [command] [args...]"
|
||||
app.Version = "0.1.0"
|
||||
app.Commands = []cli.Command{
|
||||
//Initialize example-plugin root command
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "example-plugin",
|
||||
Short: "example-plugin usage description",
|
||||
}
|
||||
|
||||
//Add the default basecoin commands to the root command
|
||||
RootCmd.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.StartCmd,
|
||||
commands.TxCmd,
|
||||
commands.KeyCmd,
|
||||
commands.QueryCmd,
|
||||
commands.KeyCmd,
|
||||
commands.VerifyCmd,
|
||||
commands.BlockCmd,
|
||||
commands.AccountCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
)
|
||||
|
||||
//Run the root command
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
app.Run(os.Args)
|
||||
}
|
||||
```
|
||||
|
||||
@ -49,19 +61,40 @@ This is where the `cmd.go` comes in.
|
||||
|
||||
### cmd.go
|
||||
|
||||
First, we register the plugin:
|
||||
First we define the new command and associated flag variables
|
||||
|
||||
```golang
|
||||
var (
|
||||
//CLI Flags
|
||||
validFlag bool
|
||||
|
||||
//CLI Plugin Commands
|
||||
ExamplePluginTxCmd = &cobra.Command{
|
||||
Use: "example",
|
||||
Short: "Create, sign, and broadcast a transaction to the example plugin",
|
||||
Run: examplePluginTxCmd,
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Next we register the plugin:
|
||||
|
||||
```golang
|
||||
func init() {
|
||||
|
||||
//Set the Plugin Flags
|
||||
ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid")
|
||||
|
||||
//Register a plugin specific CLI command as a subcommand of the tx command
|
||||
commands.RegisterTxSubcommand(ExamplePluginTxCmd)
|
||||
|
||||
//Register the example with basecoin at start
|
||||
commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() })
|
||||
}
|
||||
```
|
||||
|
||||
This creates a new subcommand under `tx` (defined below),
|
||||
and ensures the plugin is activated when we start the app.
|
||||
Now we actually define the new command:
|
||||
|
||||
```golang
|
||||
var (
|
||||
|
||||
@ -1,16 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
wire "github.com/tendermint/go-wire"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tendermint/basecoin/cmd/commands"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
)
|
||||
|
||||
var (
|
||||
//CLI Flags
|
||||
validFlag bool
|
||||
|
||||
//CLI Plugin Commands
|
||||
ExamplePluginTxCmd = &cobra.Command{
|
||||
Use: "example",
|
||||
Short: "Create, sign, and broadcast a transaction to the example plugin",
|
||||
Run: examplePluginTxCmd,
|
||||
}
|
||||
)
|
||||
|
||||
//Called during CLI initialization
|
||||
func init() {
|
||||
|
||||
//Set the Plugin Flags
|
||||
ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid")
|
||||
|
||||
//Register a plugin specific CLI command as a subcommand of the tx command
|
||||
commands.RegisterTxSubcommand(ExamplePluginTxCmd)
|
||||
|
||||
@ -18,32 +34,12 @@ func init() {
|
||||
commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() })
|
||||
}
|
||||
|
||||
var (
|
||||
//CLI Flags
|
||||
ExampleFlag = cli.BoolFlag{
|
||||
Name: "valid",
|
||||
Usage: "Set this to make the transaction valid",
|
||||
}
|
||||
|
||||
//CLI Plugin Commands
|
||||
ExamplePluginTxCmd = cli.Command{
|
||||
Name: "example",
|
||||
Usage: "Create, sign, and broadcast a transaction to the example plugin",
|
||||
Action: func(c *cli.Context) error {
|
||||
return cmdExamplePluginTx(c)
|
||||
},
|
||||
Flags: append(commands.TxFlags, ExampleFlag),
|
||||
}
|
||||
)
|
||||
|
||||
//Send a transaction
|
||||
func cmdExamplePluginTx(c *cli.Context) error {
|
||||
//Retrieve any flag results
|
||||
exampleFlag := c.Bool("valid")
|
||||
func examplePluginTxCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
// Create a transaction using the flag.
|
||||
// The tx passes on custom information to the plugin
|
||||
exampleTx := ExamplePluginTx{exampleFlag}
|
||||
exampleTx := ExamplePluginTx{validFlag}
|
||||
|
||||
// The tx is passed to the plugin in the form of
|
||||
// a byte array. This is achieved by serializing the object using go-wire.
|
||||
@ -62,5 +58,5 @@ func cmdExamplePluginTx(c *cli.Context) error {
|
||||
// - Once deserialized, the tx is passed to `state.ExecTx` (state/execution.go)
|
||||
// - If the tx passes various checks, the `tx.Data` is forwarded as `txBytes` to `plugin.RunTx` (docs/guide/src/example-plugin/plugin.go)
|
||||
// - Finally, it deserialized back to the ExamplePluginTx
|
||||
return commands.AppTx(c, "example-plugin", exampleTxBytes)
|
||||
commands.AppTx("example-plugin", exampleTxBytes)
|
||||
}
|
||||
|
||||
@ -1,24 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/basecoin/cmd/commands"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//Initialize an instance of basecoin with default basecoin commands
|
||||
app := cli.NewApp()
|
||||
app.Name = "example-plugin"
|
||||
app.Usage = "example-plugin [command] [args...]"
|
||||
app.Version = "0.1.0"
|
||||
app.Commands = []cli.Command{
|
||||
|
||||
//Initialize example-plugin root command
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "example-plugin",
|
||||
Short: "example-plugin usage description",
|
||||
}
|
||||
|
||||
//Add the default basecoin commands to the root command
|
||||
RootCmd.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.StartCmd,
|
||||
commands.TxCmd,
|
||||
commands.KeyCmd,
|
||||
commands.QueryCmd,
|
||||
commands.KeyCmd,
|
||||
commands.VerifyCmd,
|
||||
commands.BlockCmd,
|
||||
commands.AccountCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
)
|
||||
|
||||
//Run the root command
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
||||
27
glide.lock
generated
27
glide.lock
generated
@ -1,5 +1,5 @@
|
||||
hash: c023dbd97e1ea0a525e33738f03afd6be61f997f1c2592a5d9928fdcecc71361
|
||||
updated: 2017-04-21T17:38:13.194966906+02:00
|
||||
hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600
|
||||
updated: 2017-04-13T18:07:44.07521907-04:00
|
||||
imports:
|
||||
- name: github.com/btcsuite/btcd
|
||||
version: 583684b21bfbde9b5fc4403916fd7c807feb0289
|
||||
@ -19,6 +19,8 @@ imports:
|
||||
version: 553a641470496b2327abcac10b36396bd98e45c9
|
||||
- name: github.com/gorilla/websocket
|
||||
version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
|
||||
- name: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
- name: github.com/jmhodges/levigo
|
||||
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
|
||||
- name: github.com/mattn/go-colorable
|
||||
@ -26,7 +28,11 @@ imports:
|
||||
- name: github.com/mattn/go-isatty
|
||||
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
|
||||
- name: github.com/pkg/errors
|
||||
version: bfd5150e4e41705ded2129ec33379de1cb90b513
|
||||
version: 645ef00459ed84a119197bfb8d8205042c6df63d
|
||||
- name: github.com/spf13/cobra
|
||||
version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c
|
||||
- name: github.com/spf13/pflag
|
||||
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
|
||||
- name: github.com/syndtr/goleveldb
|
||||
version: 3c5717caf1475fd25964109a0fc640bd150fce43
|
||||
subpackages:
|
||||
@ -43,7 +49,7 @@ imports:
|
||||
- leveldb/table
|
||||
- leveldb/util
|
||||
- name: github.com/tendermint/abci
|
||||
version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998
|
||||
version: af792eac777de757cd496349a5f6b5313738fcbc
|
||||
subpackages:
|
||||
- client
|
||||
- example/dummy
|
||||
@ -59,11 +65,11 @@ imports:
|
||||
- name: github.com/tendermint/go-clist
|
||||
version: 3baa390bbaf7634251c42ad69a8682e7e3990552
|
||||
- name: github.com/tendermint/go-common
|
||||
version: f9e3db037330c8a8d61d3966de8473eaf01154fa
|
||||
version: dcb015dff6c7af21e65c8e2f3b450df19d38c777
|
||||
- name: github.com/tendermint/go-config
|
||||
version: 620dcbbd7d587cf3599dedbf329b64311b0c307a
|
||||
- name: github.com/tendermint/go-crypto
|
||||
version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da
|
||||
version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a
|
||||
- name: github.com/tendermint/go-data
|
||||
version: e7fcc6d081ec8518912fcdc103188275f83a3ee5
|
||||
- name: github.com/tendermint/go-db
|
||||
@ -83,13 +89,13 @@ imports:
|
||||
subpackages:
|
||||
- upnp
|
||||
- name: github.com/tendermint/go-rpc
|
||||
version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6
|
||||
version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7
|
||||
subpackages:
|
||||
- client
|
||||
- server
|
||||
- types
|
||||
- name: github.com/tendermint/go-wire
|
||||
version: c1c9a57ab8038448ddea1714c0698f8051e5748c
|
||||
version: f530b7af7a8b06e612c2063bff6ace49060a085e
|
||||
- name: github.com/tendermint/log15
|
||||
version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6
|
||||
subpackages:
|
||||
@ -100,9 +106,10 @@ imports:
|
||||
- app
|
||||
- client
|
||||
- name: github.com/tendermint/tendermint
|
||||
version: 7cf773e2d37b2b5a08bc94fb125cfd346b834824
|
||||
version: 022a5509181a19f78995a3dd9bba470333fe2d63
|
||||
subpackages:
|
||||
- blockchain
|
||||
- cmd/tendermint/commands
|
||||
- config/tendermint
|
||||
- consensus
|
||||
- mempool
|
||||
@ -117,8 +124,6 @@ imports:
|
||||
- state/txindex/null
|
||||
- types
|
||||
- version
|
||||
- name: github.com/urfave/cli
|
||||
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
|
||||
- name: golang.org/x/crypto
|
||||
version: 728b753d0135da6801d45a38e6f43ff55779c5c2
|
||||
subpackages:
|
||||
|
||||
20
glide.yaml
20
glide.yaml
@ -1,22 +1,24 @@
|
||||
package: github.com/tendermint/basecoin
|
||||
import:
|
||||
- package: github.com/tendermint/go-common
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/go-crypto
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/go-events
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/go-logger
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/go-data
|
||||
version: master
|
||||
- package: github.com/tendermint/go-rpc
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/go-wire
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/merkleeyes
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/tendermint/tendermint
|
||||
version: develop
|
||||
version: cli_change
|
||||
- package: github.com/tendermint/abci
|
||||
version: develop
|
||||
version: master
|
||||
- package: github.com/gorilla/websocket
|
||||
version: v1.1.0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user