Skip to content

Commit 6b73f6b

Browse files
committed
Add draft of clearchainctl
1 parent 169e462 commit 6b73f6b

File tree

10 files changed

+341
-22
lines changed

10 files changed

+341
-22
lines changed

cmd/clearchainctl/main.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"os"
6+
7+
"github.com/cosmos/cosmos-sdk/client"
8+
"github.com/cosmos/cosmos-sdk/client/keys"
9+
"github.com/cosmos/cosmos-sdk/client/lcd"
10+
"github.com/cosmos/cosmos-sdk/client/rpc"
11+
"github.com/cosmos/cosmos-sdk/client/tx"
12+
authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands"
13+
"github.com/spf13/cobra"
14+
"github.com/tendermint/clearchain/commands"
15+
"github.com/tendermint/clearchain/types"
16+
"github.com/tendermint/tmlibs/cli"
17+
)
18+
19+
// gaiacliCmd is the entry point for this binary
20+
var (
21+
clearchainctlCmd = &cobra.Command{
22+
Use: "clearchainctl",
23+
Short: "Clearchain light-client",
24+
}
25+
)
26+
27+
func todoNotImplemented(_ *cobra.Command, _ []string) error {
28+
return errors.New("TODO: Command not yet implemented")
29+
}
30+
31+
func main() {
32+
// disable sorting
33+
cobra.EnableCommandSorting = false
34+
35+
// get the codec
36+
cdc := types.MakeCodec()
37+
38+
// add standard rpc, and tx commands
39+
rpc.AddCommands(clearchainctlCmd)
40+
clearchainctlCmd.AddCommand(client.LineBreak)
41+
tx.AddCommands(clearchainctlCmd, cdc)
42+
clearchainctlCmd.AddCommand(client.LineBreak)
43+
44+
// add query/post commands (custom to binary)
45+
clearchainctlCmd.AddCommand(
46+
client.GetCommands(
47+
authcmd.GetAccountCmd("main", cdc, types.GetParseAccount(cdc)),
48+
)...)
49+
clearchainctlCmd.AddCommand(commands.GetPubToHexCmd(cdc))
50+
clearchainctlCmd.AddCommand(
51+
client.PostCommands(
52+
commands.GetCreateAdminTxCmd(cdc),
53+
// bankcmd.SendTxCmd(cdc),
54+
)...)
55+
56+
// add proxy, version and key info
57+
clearchainctlCmd.AddCommand(
58+
client.LineBreak,
59+
lcd.ServeCommand(),
60+
keys.Commands(),
61+
client.LineBreak,
62+
commands.VersionCmd,
63+
)
64+
65+
// prepare and add flags
66+
executor := cli.PrepareMainCmd(clearchainctlCmd, "CC", os.ExpandEnv("$HOME/.clearchainctl"))
67+
executor.Execute()
68+
}

cmd/clearchaind/main.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"github.com/cosmos/cosmos-sdk/server"
1010
"github.com/spf13/cobra"
1111
abci "github.com/tendermint/abci/types"
12-
"github.com/tendermint/clearchain"
1312
"github.com/tendermint/clearchain/app"
13+
"github.com/tendermint/clearchain/commands"
1414
crypto "github.com/tendermint/go-crypto"
1515
"github.com/tendermint/go-crypto/keys"
1616
"github.com/tendermint/go-crypto/keys/words"
@@ -29,29 +29,15 @@ var (
2929
Use: "clearchaind",
3030
Short: "Clearchain Daemon (server)",
3131
}
32-
versionCmd = &cobra.Command{
33-
Use: "version",
34-
Short: "Print the app version",
35-
Run: doVersionCmd,
36-
}
3732
)
3833

39-
func doVersionCmd(cmd *cobra.Command, args []string) {
40-
v := clearchain.Version
41-
if len(v) == 0 {
42-
fmt.Fprintln(os.Stderr, "unset")
43-
return
44-
}
45-
fmt.Fprintln(os.Stderr, v)
46-
}
47-
4834
func main() {
4935
logger := log.NewTMLogger(log.NewSyncWriter(os.Stderr)).With("module", "main")
5036
clearchaindCmd.AddCommand(
5137
server.InitCmd(defaultOptions, logger),
5238
server.StartCmd(generateApp, logger),
5339
server.UnsafeResetAllCmd(logger),
54-
versionCmd,
40+
commands.VersionCmd,
5541
)
5642
// prepare and add flags
5743
rootDir := os.ExpandEnv(defaultConfigBaseDir)

commands/createAdmin.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package commands
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/pkg/errors"
8+
"github.com/spf13/cobra"
9+
"github.com/spf13/viper"
10+
"github.com/tendermint/clearchain/types"
11+
12+
crypto "github.com/tendermint/go-crypto"
13+
wire "github.com/tendermint/go-wire"
14+
15+
"github.com/cosmos/cosmos-sdk/client"
16+
"github.com/cosmos/cosmos-sdk/client/keys"
17+
sdk "github.com/cosmos/cosmos-sdk/types"
18+
)
19+
20+
const (
21+
flagPubKey = "pubkey"
22+
flagEntityName = "entityname"
23+
flagEntityType = "entitytype"
24+
25+
// flagSequence = "seq"
26+
)
27+
28+
// GetCreateAdminTxCmd returns a CreateAdminTxCmd.
29+
func GetCreateAdminTxCmd(cdc *wire.Codec) *cobra.Command {
30+
cmdr := commander{cdc}
31+
cmd := &cobra.Command{
32+
Use: "createadmin",
33+
Short: "Create and sign a CreateAdminTx",
34+
RunE: cmdr.createAdminTxCmd,
35+
}
36+
cmd.Flags().String(flagPubKey, "", "New admin's pubkey")
37+
cmd.Flags().String(flagEntityName, "", "New admin's entity name")
38+
cmd.Flags().String(flagEntityType, "", "New admin's entity type")
39+
return cmd
40+
}
41+
42+
type commander struct {
43+
cdc *wire.Codec
44+
}
45+
46+
func (c commander) createAdminTxCmd(cmd *cobra.Command, args []string) error {
47+
txBytes, err := c.buildTx()
48+
if err != nil {
49+
return err
50+
}
51+
52+
res, err := client.BroadcastTx(txBytes)
53+
if err != nil {
54+
return err
55+
}
56+
57+
fmt.Fprintf(os.Stderr, "Committed at block %d. Hash: %s\n", res.Height, res.Hash.String())
58+
return nil
59+
}
60+
61+
func (c commander) buildTx() ([]byte, error) {
62+
keybase, err := keys.GetKeyBase()
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
name := viper.GetString(client.FlagName)
68+
info, err := keybase.Get(name)
69+
if err != nil {
70+
return nil, errors.Errorf("No key for: %s", name)
71+
}
72+
creator := info.PubKey.Address()
73+
74+
msg, err := buildMsg(creator)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
// sign and build
80+
bz := msg.GetSignBytes()
81+
buf := client.BufferStdin()
82+
prompt := fmt.Sprintf("Password to sign with '%s':", name)
83+
passphrase, err := client.GetPassword(prompt, buf)
84+
if err != nil {
85+
return nil, err
86+
}
87+
sig, pubkey, err := keybase.Sign(name, passphrase, bz)
88+
if err != nil {
89+
return nil, err
90+
}
91+
sigs := []sdk.StdSignature{{
92+
PubKey: pubkey,
93+
Signature: sig,
94+
//Sequence: viper.GetInt64(flagSequence),
95+
}}
96+
97+
// marshal bytes
98+
tx := sdk.NewStdTx(msg, sigs)
99+
100+
txBytes, err := c.cdc.MarshalBinary(tx)
101+
if err != nil {
102+
return nil, err
103+
}
104+
return txBytes, nil
105+
}
106+
107+
func buildMsg(creator crypto.Address) (sdk.Msg, error) {
108+
109+
// parse inputs
110+
entityName := viper.GetString(flagEntityName)
111+
entityType := viper.GetString(flagEntityType)
112+
113+
// parse new account pubkey
114+
pubKey, err := types.PubKeyFromHexString(viper.GetString(flagPubKey))
115+
if err != nil {
116+
return nil, err
117+
}
118+
119+
msg := types.NewCreateAdminMsg(creator, pubKey, entityName, entityType)
120+
return msg, nil
121+
}

commands/pubKeyToHex.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package commands
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
7+
"github.com/cosmos/cosmos-sdk/client/keys"
8+
"github.com/pkg/errors"
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/viper"
11+
wire "github.com/tendermint/go-wire"
12+
)
13+
14+
const (
15+
flagName = "name"
16+
)
17+
18+
func GetPubToHexCmd(cdc *wire.Codec) *cobra.Command {
19+
cmd := &cobra.Command{
20+
Use: "pub2hex",
21+
RunE: pubToHexCmd,
22+
}
23+
cmd.Flags().String(flagName, "", "Account's pubkey")
24+
return cmd
25+
}
26+
27+
func pubToHexCmd(cmd *cobra.Command, args []string) error {
28+
keybase, err := keys.GetKeyBase()
29+
if err != nil {
30+
return err
31+
}
32+
name := viper.GetString(flagName)
33+
info, err := keybase.Get(name)
34+
if err != nil {
35+
return errors.Errorf("No key for: %s", name)
36+
}
37+
fmt.Println(hex.EncodeToString(info.PubKey.Bytes()))
38+
return nil
39+
}

commands/version.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package commands
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/spf13/cobra"
8+
"github.com/tendermint/clearchain"
9+
)
10+
11+
var (
12+
// VersionCmd prints the program's version to stderr and exits.
13+
VersionCmd = &cobra.Command{
14+
Use: "version",
15+
Short: "Print the app version",
16+
Run: doVersionCmd,
17+
}
18+
)
19+
20+
func doVersionCmd(cmd *cobra.Command, args []string) {
21+
v := clearchain.Version
22+
if len(v) == 0 {
23+
fmt.Fprintln(os.Stderr, "unset")
24+
return
25+
}
26+
fmt.Fprintln(os.Stderr, v)
27+
}

types/account.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
sdk "github.com/cosmos/cosmos-sdk/types"
77
"github.com/cosmos/cosmos-sdk/x/auth"
88
crypto "github.com/tendermint/go-crypto"
9+
wire "github.com/tendermint/go-wire"
910
)
1011

1112
// EntityType string identifiers
@@ -113,6 +114,15 @@ func AccountMapper(capKey sdk.StoreKey) sdk.AccountMapper {
113114
return res
114115
}
115116

117+
// GetParseAccount returns the ParseAccount function for the custom AppAccount.
118+
func GetParseAccount(cdc *wire.Codec) sdk.ParseAccount {
119+
return func(accBytes []byte) (res sdk.Account, err error) {
120+
acct := new(AppAccount)
121+
err = cdc.UnmarshalBinary(accBytes, acct)
122+
return acct, err
123+
}
124+
}
125+
116126
func accountEqual(a1, a2 *AppAccount) bool {
117127
return ((a1.AccountType == a2.AccountType) &&
118128
(a1.Admin == a2.Admin) &&

types/genesis.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,24 @@ type GenesisAccount struct {
2020
// ToClearingHouseAdmin converts a GenesisAccount into an AppAccount (a Clearing House admin user)
2121
func (ga *GenesisAccount) ToClearingHouseAdmin() (acc *AppAccount, err error) {
2222
// Done manually since JSON Unmarshalling does not create a PubKey from a hexa value
23-
pubBytes, err := hex.DecodeString(ga.PubKeyHexa)
23+
publicKey, err := PubKeyFromHexString(ga.PubKeyHexa)
2424
if err != nil {
2525
return nil, err
2626
}
27-
publicKey, err := crypto.PubKeyFromBytes(pubBytes)
27+
adminUser := NewAdminUser(publicKey, nil, ga.EntityName, EntityClearingHouse)
28+
return adminUser, nil
29+
}
30+
31+
// PubKeyFromHexString converts a hexadecimal string representation of
32+
// a public key into a crypto.PubKey instance.
33+
func PubKeyFromHexString(s string) (crypto.PubKey, error) {
34+
bytes, err := hex.DecodeString(s)
2835
if err != nil {
2936
return nil, err
3037
}
31-
32-
adminUser := NewAdminUser(publicKey, nil, ga.EntityName, EntityClearingHouse)
33-
return adminUser, nil
38+
pub, err := crypto.PubKeyFromBytes(bytes)
39+
if err != nil {
40+
return nil, err
41+
}
42+
return pub, err
3443
}

types/genesis_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/assert"
8-
98
crypto "github.com/tendermint/go-crypto"
109
)
1110

@@ -66,3 +65,24 @@ func Test_ToClearingHouseAdmin(t *testing.T) {
6665
})
6766
}
6867
}
68+
69+
func TestPubKeyFromHexString(t *testing.T) {
70+
type args struct {
71+
s string
72+
}
73+
tests := []struct {
74+
name string
75+
args args
76+
wantErr bool
77+
}{
78+
{"good key", args{"328eaf5937458f6c39c54ee3624137cabe7af88226454fd30180c8da6c711ad6de7f6053"}, false},
79+
{"bad key", args{"24137cabe7af88226454fd30180c8da6c711ad6de7f6053"}, true},
80+
{"nil", args{""}, true},
81+
}
82+
for _, tt := range tests {
83+
t.Run(tt.name, func(t *testing.T) {
84+
_, err := PubKeyFromHexString(tt.args.s)
85+
assert.Equal(t, (err != nil), tt.wantErr)
86+
})
87+
}
88+
}

0 commit comments

Comments
 (0)