Skip to content

Commit 8269906

Browse files
committed
Merge branch 'main' into minhd-vu/flag-loader
2 parents 2a5db56 + f511643 commit 8269906

File tree

8 files changed

+105
-131
lines changed

8 files changed

+105
-131
lines changed

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ The tool supports configuration via:
147147
f.IntVar(&count, "count", 0, "description")
148148
```
149149

150+
### Cobra Command Arguments
151+
- Prefer to use Cobra built-in validators (`cobra.NoArgs`, `cobra.ExactArgs(n)`, `cobra.MinimumNArgs(n)`, `cobra.MaximumNArgs(n)`, `cobra.ArbitraryArgs`) instead of custom `Args: func(cmd *cobra.Command, args []string) error` functions, and move argument parsing/validation logic to `PreRunE` hook
152+
150153
### Cobra Commands
151154
- Command `Short` descriptions: sentence case with ending period, e.g., `"Generate a node list to seed a node."`
152155
- Command `Long` descriptions: consider using embedded usage.md file via `//go:embed usage.md` pattern; when using inline strings, use sentence case with ending period for complete sentences

cmd/dbbench/dbbench.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@ var DBBenchCmd = &cobra.Command{
140140
Use: "dbbench [flags]",
141141
Short: "Perform a level/pebble db benchmark.",
142142
Long: usage,
143+
Args: cobra.NoArgs,
144+
PreRunE: func(cmd *cobra.Command, args []string) error {
145+
var err error
146+
sizeDistribution, err = parseRawSizeDistribution(rawSizeDistribution)
147+
if err != nil {
148+
return err
149+
}
150+
if keySize > 64 {
151+
return fmt.Errorf("max supported key size is 64 bytes. %d is too big", keySize)
152+
}
153+
return nil
154+
},
143155
RunE: func(cmd *cobra.Command, args []string) error {
144156
log.Info().Msg("Starting db test")
145157
var kvdb KeyValueDB
@@ -217,17 +229,6 @@ var DBBenchCmd = &cobra.Command{
217229

218230
return printSummary(trs)
219231
},
220-
Args: func(cmd *cobra.Command, args []string) error {
221-
var err error
222-
sizeDistribution, err = parseRawSizeDistribution(rawSizeDistribution)
223-
if err != nil {
224-
return err
225-
}
226-
if keySize > 64 {
227-
return fmt.Errorf(" max supported key size is 64 bytes. %d is too big", keySize)
228-
}
229-
return nil
230-
},
231232
}
232233

233234
func printSummary(trs []*TestResult) error {

cmd/dumpblocks/dumpblocks.go

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ var DumpblocksCmd = &cobra.Command{
5555
Use: "dumpblocks start end",
5656
Short: "Export a range of blocks from a JSON-RPC endpoint.",
5757
Long: usage,
58+
Args: cobra.MinimumNArgs(2),
5859
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
5960
inputDumpblocks.RpcUrl, err = flag.GetRPCURL(cmd)
6061
if err != nil {
6162
return err
6263
}
63-
return nil
64+
return checkFlags(args)
6465
},
6566
RunE: func(cmd *cobra.Command, args []string) error {
6667
ctx := cmd.Context()
@@ -136,50 +137,6 @@ var DumpblocksCmd = &cobra.Command{
136137
wg.Wait()
137138
log.Info().Msg("Done")
138139

139-
return nil
140-
},
141-
Args: func(cmd *cobra.Command, args []string) error {
142-
if len(args) < 2 {
143-
return fmt.Errorf("command needs at least two arguments. A start block and an end block")
144-
}
145-
146-
start, err := strconv.ParseInt(args[0], 10, 64)
147-
if err != nil {
148-
return err
149-
}
150-
end, err := strconv.ParseInt(args[1], 10, 64)
151-
if err != nil {
152-
return err
153-
}
154-
if start < 0 || end < 0 {
155-
return fmt.Errorf("the start and end parameters need to be positive")
156-
}
157-
if end < start {
158-
start, end = end, start
159-
}
160-
161-
inputDumpblocks.Start = uint64(start)
162-
inputDumpblocks.End = uint64(end)
163-
164-
if inputDumpblocks.Threads == 0 {
165-
inputDumpblocks.Threads = 1
166-
}
167-
if !slices.Contains([]string{"json", "proto"}, inputDumpblocks.Mode) {
168-
return fmt.Errorf("output format must one of [json, proto]")
169-
}
170-
171-
if err := json.Unmarshal([]byte(inputDumpblocks.FilterStr), &inputDumpblocks.filter); err != nil {
172-
return fmt.Errorf("could not unmarshal filter string")
173-
}
174-
175-
// Make sure the filters are all lowercase.
176-
for i := 0; i < len(inputDumpblocks.filter.To); i++ {
177-
inputDumpblocks.filter.To[i] = strings.ToLower(inputDumpblocks.filter.To[i])
178-
}
179-
for i := 0; i < len(inputDumpblocks.filter.From); i++ {
180-
inputDumpblocks.filter.From[i] = strings.ToLower(inputDumpblocks.filter.From[i])
181-
}
182-
183140
return nil
184141
},
185142
}
@@ -196,6 +153,48 @@ func init() {
196153
f.StringVarP(&inputDumpblocks.FilterStr, "filter", "F", "{}", "filter output based on tx to and from (not setting a filter means all are allowed)")
197154
}
198155

156+
func checkFlags(args []string) error {
157+
// Parse start and end blocks
158+
start, err := strconv.ParseInt(args[0], 10, 64)
159+
if err != nil {
160+
return err
161+
}
162+
end, err := strconv.ParseInt(args[1], 10, 64)
163+
if err != nil {
164+
return err
165+
}
166+
if start < 0 || end < 0 {
167+
return fmt.Errorf("the start and end parameters need to be positive")
168+
}
169+
if end < start {
170+
start, end = end, start
171+
}
172+
173+
inputDumpblocks.Start = uint64(start)
174+
inputDumpblocks.End = uint64(end)
175+
176+
if inputDumpblocks.Threads == 0 {
177+
inputDumpblocks.Threads = 1
178+
}
179+
if !slices.Contains([]string{"json", "proto"}, inputDumpblocks.Mode) {
180+
return fmt.Errorf("output format must one of [json, proto]")
181+
}
182+
183+
if err := json.Unmarshal([]byte(inputDumpblocks.FilterStr), &inputDumpblocks.filter); err != nil {
184+
return fmt.Errorf("could not unmarshal filter string")
185+
}
186+
187+
// Make sure the filters are all lowercase.
188+
for i := 0; i < len(inputDumpblocks.filter.To); i++ {
189+
inputDumpblocks.filter.To[i] = strings.ToLower(inputDumpblocks.filter.To[i])
190+
}
191+
for i := 0; i < len(inputDumpblocks.filter.From); i++ {
192+
inputDumpblocks.filter.From[i] = strings.ToLower(inputDumpblocks.filter.From[i])
193+
}
194+
195+
return nil
196+
}
197+
199198
// writeResponses writes the data to either stdout or a file if one is provided.
200199
// The message type can be either "block" or "transaction". The format of the
201200
// output is either "json" or "proto" depending on the mode.

cmd/foldtrace/foldtrace.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ var FoldTraceCmd = &cobra.Command{
3737
Use: "fold-trace",
3838
Short: "Trace an execution trace and fold it for visualization.",
3939
Long: usage,
40+
Args: cobra.ArbitraryArgs,
41+
PreRunE: func(cmd *cobra.Command, args []string) error {
42+
return validateInputMetric()
43+
},
4044
RunE: func(cmd *cobra.Command, args []string) error {
4145
data, err := getInputData(cmd, args)
4246
if err != nil {
@@ -100,13 +104,6 @@ var FoldTraceCmd = &cobra.Command{
100104

101105
return nil
102106
},
103-
Args: func(cmd *cobra.Command, args []string) error {
104-
err := validateInputMetric()
105-
if err != nil {
106-
return err
107-
}
108-
return nil
109-
},
110107
}
111108

112109
func getActualUsedGas(index int, td *TraceData) uint64 {

cmd/fork/fork.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ var ForkCmd = &cobra.Command{
2828
Use: "fork blockhash url",
2929
Short: "Take a forked block and walk up the chain to do analysis.",
3030
Long: "",
31+
Args: cobra.ExactArgs(2),
32+
PreRunE: func(cmd *cobra.Command, args []string) error {
33+
blockHash = ethcommon.HexToHash(args[0])
34+
rpcURL = args[1]
35+
return nil
36+
},
3137
RunE: func(cmd *cobra.Command, args []string) error {
3238
log.Info().Str("rpc", rpcURL).Str("blockHash", blockHash.String()).Msg("Starting Analysis")
3339
c, err := ethclient.Dial(rpcURL)
@@ -37,14 +43,6 @@ var ForkCmd = &cobra.Command{
3743
}
3844
return walkTheBlocks(blockHash, c)
3945
},
40-
Args: func(cmd *cobra.Command, args []string) error {
41-
if len(args) != 2 {
42-
return fmt.Errorf("two arguments required a block hash and an RPC URL")
43-
}
44-
blockHash = ethcommon.HexToHash(args[0])
45-
rpcURL = args[1]
46-
return nil
47-
},
4846
}
4947

5048
func walkTheBlocks(inputBlockHash ethcommon.Hash, client *ethclient.Client) error {

cmd/nodekey/nodekey.go

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
libp2ppeer "github.com/libp2p/go-libp2p/core/peer"
2323
"github.com/spf13/cobra"
2424
"github.com/spf13/pflag"
25-
"golang.org/x/exp/slices"
2625
)
2726

2827
// libp2p (substrate/avail) - https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md
@@ -66,12 +65,35 @@ var NodekeyCmd = &cobra.Command{
6665
Use: "nodekey",
6766
Short: "Generate node keys for different blockchain clients and protocols.",
6867
Long: usage,
68+
Args: cobra.NoArgs,
6969
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
7070
inputNodeKeyPrivateKey, err = flag.GetPrivateKey(cmd)
7171
if err != nil {
7272
return err
7373
}
74-
return nil
74+
75+
switch inputNodeKeyProtocol {
76+
case "devp2p":
77+
invalidFlags := []string{"seed", "marshal-protobuf"}
78+
return validateNodeKeyFlags(cmd, invalidFlags)
79+
case "libp2p":
80+
invalidFlags := []string{"file", "ip", "tcp", "udp", "sign", "seed"}
81+
return validateNodeKeyFlags(cmd, invalidFlags)
82+
case "seed-libp2p":
83+
invalidFlags := []string{"file", "ip", "tcp", "udp", "sign"}
84+
if err := validateNodeKeyFlags(cmd, invalidFlags); err != nil {
85+
return err
86+
}
87+
if inputNodeKeyType == "rsa" {
88+
return fmt.Errorf("the RSA key type doesn't support manual key seeding")
89+
}
90+
if inputNodeKeyType == "secp256k1" {
91+
return fmt.Errorf("the secp256k1 key type doesn't support manual key seeding")
92+
}
93+
return nil
94+
default:
95+
return fmt.Errorf("the protocol %s is not implemented", inputNodeKeyProtocol)
96+
}
7597
},
7698
RunE: func(cmd *cobra.Command, args []string) error {
7799
var nko nodeKeyOut
@@ -118,46 +140,6 @@ var NodekeyCmd = &cobra.Command{
118140

119141
return nil
120142
},
121-
Args: func(cmd *cobra.Command, args []string) error {
122-
if len(args) != 0 {
123-
return fmt.Errorf("this command expects no arguments")
124-
}
125-
126-
validProtocols := []string{"devp2p", "libp2p", "seed-libp2p"}
127-
ok := slices.Contains(validProtocols, inputNodeKeyProtocol)
128-
if !ok {
129-
return fmt.Errorf("the protocol %s is not implemented", inputNodeKeyProtocol)
130-
}
131-
132-
if inputNodeKeyProtocol == "devp2p" {
133-
invalidFlags := []string{"seed", "marshal-protobuf"}
134-
err := validateNodeKeyFlags(cmd, invalidFlags)
135-
if err != nil {
136-
return err
137-
}
138-
}
139-
if inputNodeKeyProtocol == "libp2p" {
140-
invalidFlags := []string{"file", "ip", "tcp", "udp", "sign", "seed"}
141-
err := validateNodeKeyFlags(cmd, invalidFlags)
142-
if err != nil {
143-
return err
144-
}
145-
}
146-
if inputNodeKeyProtocol == "seed-libp2p" {
147-
invalidFlags := []string{"file", "ip", "tcp", "udp", "sign"}
148-
err := validateNodeKeyFlags(cmd, invalidFlags)
149-
if err != nil {
150-
return err
151-
}
152-
if inputNodeKeyType == "rsa" {
153-
return fmt.Errorf("the RSA key type doesn't support manual key seeding")
154-
}
155-
if inputNodeKeyType == "secp256k1" {
156-
return fmt.Errorf("the secp256k1 key type doesn't support manual key seeding")
157-
}
158-
}
159-
return nil
160-
},
161143
}
162144

163145
func validateNodeKeyFlags(cmd *cobra.Command, invalidFlags []string) error {

cmd/wallet/wallet.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,17 @@ var (
2929

3030
// WalletCmd represents the wallet command
3131
var WalletCmd = &cobra.Command{
32-
Use: "wallet [create|inspect]",
33-
Short: "Create or inspect BIP39(ish) wallets.",
34-
Long: usage,
32+
Use: "wallet [create|inspect]",
33+
Short: "Create or inspect BIP39(ish) wallets.",
34+
Long: usage,
35+
Args: cobra.ExactArgs(1),
36+
ValidArgs: []string{"create", "inspect"},
37+
PreRunE: func(cmd *cobra.Command, args []string) error {
38+
if args[0] != "create" && args[0] != "inspect" {
39+
return fmt.Errorf("expected argument to be create or inspect. Got: %s", args[0])
40+
}
41+
return nil
42+
},
3543
RunE: func(cmd *cobra.Command, args []string) error {
3644
mode := args[0]
3745
var err error
@@ -91,15 +99,6 @@ var WalletCmd = &cobra.Command{
9199
fmt.Println(string(out))
92100
return nil
93101
},
94-
Args: func(cmd *cobra.Command, args []string) error {
95-
if len(args) != 1 {
96-
return fmt.Errorf("expected exactly one argument: create or inspect")
97-
}
98-
if args[0] != "create" && args[0] != "inspect" {
99-
return fmt.Errorf("expected argument to be create or inspect. Got: %s", args[0])
100-
}
101-
return nil
102-
},
103102
}
104103

105104
func getFileOrFlag(filename string, flag string) (string, error) {

cmd/wrapcontract/wrapcontract.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@ var WrapContractCmd = &cobra.Command{
3737
fmt.Println(createBytecode)
3838
return nil
3939
},
40-
Args: func(cmd *cobra.Command, args []string) error {
41-
if len(args) > 1 {
42-
return fmt.Errorf("expected at most one argument: bytecode")
43-
}
44-
return nil
45-
},
40+
Args: cobra.MaximumNArgs(1),
4641
}
4742

4843
func init() {

0 commit comments

Comments
 (0)