From 047500ae23a12469ce3e458c6a58a642716041b7 Mon Sep 17 00:00:00 2001 From: Rasmus Dahlberg Date: Sat, 23 Apr 2022 18:19:25 +0200 Subject: add drafty tool named sigsum-debug Meant to be used for debugging and tests only. Replaces cmd/tmp/* in log-go, expect for the DNS command which is redundant. Use `dig -t txt $domain_hint` to debug domain hints. --- cmd/sigsum-debug/head/consistency/consistency.go | 9 ++ cmd/sigsum-debug/head/head.go | 103 ++++++++++++++++++++ cmd/sigsum-debug/head/sign/sign.go | 41 ++++++++ cmd/sigsum-debug/head/verify/verify.go | 9 ++ cmd/sigsum-debug/key/hash/hash.go | 29 ++++++ cmd/sigsum-debug/key/key.go | 51 ++++++++++ cmd/sigsum-debug/key/private/private.go | 29 ++++++ cmd/sigsum-debug/key/public/public.go | 32 ++++++ cmd/sigsum-debug/leaf/hash/hash.go | 42 ++++++++ cmd/sigsum-debug/leaf/inclusion/inclusion.go | 9 ++ cmd/sigsum-debug/leaf/leaf.go | 119 +++++++++++++++++++++++ cmd/sigsum-debug/leaf/sign/sign.go | 37 +++++++ cmd/sigsum-debug/leaf/verify/verify.go | 9 ++ cmd/sigsum-debug/main.go | 65 +++++++++++++ internal/fmtio/fmtio.go | 79 +++++++++++++++ internal/options/options.go | 65 +++++++++++++ 16 files changed, 728 insertions(+) create mode 100644 cmd/sigsum-debug/head/consistency/consistency.go create mode 100644 cmd/sigsum-debug/head/head.go create mode 100644 cmd/sigsum-debug/head/sign/sign.go create mode 100644 cmd/sigsum-debug/head/verify/verify.go create mode 100644 cmd/sigsum-debug/key/hash/hash.go create mode 100644 cmd/sigsum-debug/key/key.go create mode 100644 cmd/sigsum-debug/key/private/private.go create mode 100644 cmd/sigsum-debug/key/public/public.go create mode 100644 cmd/sigsum-debug/leaf/hash/hash.go create mode 100644 cmd/sigsum-debug/leaf/inclusion/inclusion.go create mode 100644 cmd/sigsum-debug/leaf/leaf.go create mode 100644 cmd/sigsum-debug/leaf/sign/sign.go create mode 100644 cmd/sigsum-debug/leaf/verify/verify.go create mode 100644 cmd/sigsum-debug/main.go create mode 100644 internal/fmtio/fmtio.go create mode 100644 internal/options/options.go diff --git a/cmd/sigsum-debug/head/consistency/consistency.go b/cmd/sigsum-debug/head/consistency/consistency.go new file mode 100644 index 0000000..18fbdd6 --- /dev/null +++ b/cmd/sigsum-debug/head/consistency/consistency.go @@ -0,0 +1,9 @@ +package consistency + +import ( + "fmt" +) + +func Main(args []string, oldSize, newSize uint64, oldRoot, newRoot string) error { + return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/head/head.go b/cmd/sigsum-debug/head/head.go new file mode 100644 index 0000000..b1b3044 --- /dev/null +++ b/cmd/sigsum-debug/head/head.go @@ -0,0 +1,103 @@ +package head + +import ( + "flag" + "fmt" + "log" + + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/consistency" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/sign" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/verify" + "git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug head signs and verifies tree heads. + +Usage: + + sigsum-debug head help + Outputs a usage message + + sigsum-debug head sign -k PRIVATE_KEY -h KEY_HASH + Reads an ascii signed tree head from stdin and outputs a new signature + + sigsum-debug head verify -k PUBLIC_KEY + Reads an ascii signed tree head from stdin and verifies it + + sigsum-debug head consistency -n OLD_SIZE -N NEW_SIZE -r OLD_ROOT -R NEW_ROOT + Reads an ascii consistency proof from stdin and verifies it + +` + +var ( + optPrivateKey, optPublicKey, optKeyHash, optOldRoot, optNewRoot string + optOldSize, optNewSize uint64 +) + +func Main(args []string) error { + var err error + + opt := options.New(args, func() { log.Printf(usage[1:]) }, setOptions) + err = checkOptions(opt.Name()) + if err == nil { + switch opt.Name() { + case "help": + opt.Usage() + case "sign": + err = sign.Main(opt.Args(), optPrivateKey, optKeyHash) + case "verify": + err = verify.Main(opt.Args(), optPublicKey) + case "consistency": + err = consistency.Main(opt.Args(), optOldSize, optNewSize, optOldRoot, optNewRoot) + default: + err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) + } + } + if err != nil { + format := " %s: %w" + if len(opt.Name()) == 0 { + format = "%s: %w" + } + err = fmt.Errorf(format, opt.Name(), err) + } + + return err +} + +func setOptions(fs *flag.FlagSet) { + switch cmd := fs.Name(); cmd { + case "help": + case "sign": + options.AddString(fs, &optPrivateKey, "k", "private-key", options.DefaultString) + options.AddString(fs, &optKeyHash, "h", "key-hash", options.DefaultString) + case "verify": + options.AddString(fs, &optPublicKey, "k", "public-key", options.DefaultString) + case "consistency": + options.AddUint64(fs, &optOldSize, "n", "old-size", options.DefaultUint64) + options.AddUint64(fs, &optNewSize, "N", "new-size", options.DefaultUint64) + options.AddString(fs, &optOldRoot, "r", "old-root", options.DefaultString) + options.AddString(fs, &optNewRoot, "R", "new-root", options.DefaultString) + } +} + +// checkOptions checks that options with required arguments were set +func checkOptions(cmd string) error { + var err error + + switch cmd { + case "help": + case "sign": + err = options.CheckString("private key", optPrivateKey, err) + err = options.CheckString("key hash", optKeyHash, err) + case "verify": + err = options.CheckString("public key", optPublicKey, err) + case "consistency": + err = options.CheckUint64("old size", optOldSize, err) + err = options.CheckUint64("new size", optNewSize, err) + err = options.CheckString("old root", optOldRoot, err) + err = options.CheckString("new root", optNewRoot, err) + } + + return err +} diff --git a/cmd/sigsum-debug/head/sign/sign.go b/cmd/sigsum-debug/head/sign/sign.go new file mode 100644 index 0000000..572af9a --- /dev/null +++ b/cmd/sigsum-debug/head/sign/sign.go @@ -0,0 +1,41 @@ +package sign + +import ( + "bytes" + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/internal/fmtio" + "git.sigsum.org/sigsum-go/pkg/hex" + "git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optPrivateKey, optKeyHash string) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + b, err := fmtio.BytesFromStdin() + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + priv, err := fmtio.SignerFromHex(optPrivateKey) + if err != nil { + return fmt.Errorf("parse private key: %v", err) + } + keyHash, err := fmtio.KeyHashFromHex(optKeyHash) + if err != nil { + return fmt.Errorf("parse key hash: %v", err) + } + + var input types.SignedTreeHead + if err := input.FromASCII(bytes.NewBuffer(b)); err != nil { + return fmt.Errorf("parse signed tree head: %v", err) + } + output, err := input.TreeHead.Sign(priv, &keyHash) + if err != nil { + return fmt.Errorf("sign tree head: %v", err) + } + + fmt.Printf("%s\n", hex.Serialize(output.Signature[:])) + return nil +} diff --git a/cmd/sigsum-debug/head/verify/verify.go b/cmd/sigsum-debug/head/verify/verify.go new file mode 100644 index 0000000..69b20aa --- /dev/null +++ b/cmd/sigsum-debug/head/verify/verify.go @@ -0,0 +1,9 @@ +package verify + +import ( + "fmt" +) + +func Main(args []string, optPublicKey string) error { + return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/key/hash/hash.go b/cmd/sigsum-debug/key/hash/hash.go new file mode 100644 index 0000000..0431dfc --- /dev/null +++ b/cmd/sigsum-debug/key/hash/hash.go @@ -0,0 +1,29 @@ +package hash + +import ( + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/internal/fmtio" + "git.sigsum.org/sigsum-go/pkg/hex" + "git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + s, err := fmtio.StringFromStdin() + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + pub, err := fmtio.PublicKeyFromHex(s) + if err != nil { + return fmt.Errorf("parse key: %w", err) + } + + keyHash := types.HashFn(pub[:]) + + fmt.Printf("%s\n", hex.Serialize(keyHash[:])) + return nil +} diff --git a/cmd/sigsum-debug/key/key.go b/cmd/sigsum-debug/key/key.go new file mode 100644 index 0000000..88973f2 --- /dev/null +++ b/cmd/sigsum-debug/key/key.go @@ -0,0 +1,51 @@ +package key + +import ( + "flag" + "fmt" + "log" + + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/hash" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/private" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/public" + "git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug key generates private keys, public keys, and key hashes. + +Usage: + + sigsum-debug key help Outputs a usage message + sigsum-debug key private Outputs a new private key + sigsum-debug key public Outputs a public key for a private key on stdin + sigsum-debug key hash Outputs a key hash for a public key on stdin + +` + +func Main(args []string) error { + var err error + + opt := options.New(args, func() { log.Printf(usage[1:]) }, func(_ *flag.FlagSet) {}) + switch opt.Name() { + case "help": + opt.Usage() + case "private": + err = private.Main(opt.Args()) + case "public": + err = public.Main(opt.Args()) + case "hash": + err = hash.Main(opt.Args()) + default: + err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) + } + if err != nil { + format := " %s: %w" + if len(opt.Name()) == 0 { + format = "%s: %w" + } + err = fmt.Errorf(format, opt.Name(), err) + } + + return err +} diff --git a/cmd/sigsum-debug/key/private/private.go b/cmd/sigsum-debug/key/private/private.go new file mode 100644 index 0000000..3928f56 --- /dev/null +++ b/cmd/sigsum-debug/key/private/private.go @@ -0,0 +1,29 @@ +package private + +import ( + "crypto/ed25519" + "crypto/rand" + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/pkg/hex" +) + +const privateKeySize = 64 + +func Main(args []string) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + + _, priv, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return fmt.Errorf("generate key: %w", err) + } + if len(priv) != privateKeySize { + return fmt.Errorf("invalid key size %d", len(priv)) + } + + fmt.Printf("%s\n", hex.Serialize(priv[:])) + return nil +} diff --git a/cmd/sigsum-debug/key/public/public.go b/cmd/sigsum-debug/key/public/public.go new file mode 100644 index 0000000..b03d0b9 --- /dev/null +++ b/cmd/sigsum-debug/key/public/public.go @@ -0,0 +1,32 @@ +package public + +import ( + "crypto/ed25519" + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/internal/fmtio" + "git.sigsum.org/sigsum-go/pkg/hex" +) + +func Main(args []string) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + s, err := fmtio.StringFromStdin() + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + + priv, err := fmtio.SignerFromHex(s) + if err != nil { + return fmt.Errorf("parse key: %w", err) + } + pub, ok := priv.Public().(ed25519.PublicKey) + if !ok { + return fmt.Errorf("not an ed25519 key") + } + + fmt.Printf("%s\n", hex.Serialize(pub[:])) + return nil +} diff --git a/cmd/sigsum-debug/leaf/hash/hash.go b/cmd/sigsum-debug/leaf/hash/hash.go new file mode 100644 index 0000000..9bc845e --- /dev/null +++ b/cmd/sigsum-debug/leaf/hash/hash.go @@ -0,0 +1,42 @@ +package hash + +import ( + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/internal/fmtio" + "git.sigsum.org/sigsum-go/pkg/hex" + "git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optKeyHash, optSignature string, optShardHint uint64) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + data, err := fmtio.BytesFromStdin() + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + keyHash, err := fmtio.KeyHashFromHex(optKeyHash) + if err != nil { + return fmt.Errorf("parse key hash: %w", err) + } + sig, err := fmtio.SignatureFromHex(optSignature) + if err != nil { + return fmt.Errorf("parse signature: %w", err) + } + + preimage := types.HashFn(data) + leaf := types.Leaf{ + Statement: types.Statement{ + ShardHint: optShardHint, + Checksum: *types.HashFn(preimage[:]), + }, + Signature: sig, + KeyHash: keyHash, + } + leafHash := types.LeafHash(leaf.ToBinary()) + + fmt.Printf("%s\n", hex.Serialize(leafHash[:])) + return nil +} diff --git a/cmd/sigsum-debug/leaf/inclusion/inclusion.go b/cmd/sigsum-debug/leaf/inclusion/inclusion.go new file mode 100644 index 0000000..f9aeb68 --- /dev/null +++ b/cmd/sigsum-debug/leaf/inclusion/inclusion.go @@ -0,0 +1,9 @@ +package inclusion + +import ( + "fmt" +) + +func Main(args []string, optLeafHash, optRootHash string, optTreeSize uint64) error { + return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/leaf/leaf.go b/cmd/sigsum-debug/leaf/leaf.go new file mode 100644 index 0000000..97de37e --- /dev/null +++ b/cmd/sigsum-debug/leaf/leaf.go @@ -0,0 +1,119 @@ +package leaf + +import ( + "flag" + "fmt" + "log" + + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/hash" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/inclusion" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/sign" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/verify" + "git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug leaf signs, verifies, and hashes Merkle tree leaves. + +Usage: + + sigsum-debug leaf help + Outputs a usage message + + sigsum-debug leaf sign -k PRIVATE_KEY -h SHARD_HINT + Reads data from stdin and outputs a signature + + sigsum-debug leaf verify -k PUBLIC_KEY -s SIGNATURE -h SHARD_HINT + Reads data from stdin and verifies its signature + + sigsum-debug leaf hash -k KEY_HASH -s SIGNATURE -h SHARD_HINT + Reads data from stdin and outputs a leaf hash + + sigsum-debug leaf inclusion -l LEAF_HASH -n TREE_SIZE -r ROOT_HASH + Reads an inclusion proof from stdin and verifies it + +` + +var ( + optPrivateKey, optPublicKey, optKeyHash, optLeafHash, optRootHash, optSignature string + optShardHint, optTreeSize uint64 +) + +func Main(args []string) error { + var err error + + opt := options.New(args, func() { log.Printf(usage[1:]) }, setOptions) + err = checkOptions(opt.Name()) + if err == nil { + switch opt.Name() { + case "help": + opt.Usage() + case "sign": + err = sign.Main(opt.Args(), optPrivateKey, optShardHint) + case "verify": + err = verify.Main(opt.Args(), optPublicKey, optSignature, optShardHint) + case "hash": + err = hash.Main(opt.Args(), optKeyHash, optSignature, optShardHint) + case "inclusion": + err = inclusion.Main(opt.Args(), optLeafHash, optRootHash, optTreeSize) + default: + err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) + } + } + if err != nil { + format := " %s: %w" + if len(opt.Name()) == 0 { + format = "%s: %w" + } + err = fmt.Errorf(format, opt.Name(), err) + } + + return err +} + +func setOptions(fs *flag.FlagSet) { + switch cmd := fs.Name(); cmd { + case "help": + case "sign": + options.AddString(fs, &optPrivateKey, "k", "private-key", options.DefaultString) + options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) + case "verify": + options.AddString(fs, &optPublicKey, "k", "public-key", options.DefaultString) + options.AddString(fs, &optSignature, "s", "signature", options.DefaultString) + options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) + case "hash": + options.AddString(fs, &optKeyHash, "k", "key-hash", options.DefaultString) + options.AddString(fs, &optSignature, "s", "signature", options.DefaultString) + options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) + case "inclusion": + options.AddString(fs, &optLeafHash, "l", "leaf-hash", options.DefaultString) + options.AddUint64(fs, &optTreeSize, "n", "tree-size", options.DefaultUint64) + options.AddString(fs, &optRootHash, "r", "root-hash", options.DefaultString) + } +} + +// checkOptions checks that options with required arguments were set +func checkOptions(cmd string) error { + var err error + + switch cmd { + case "help": + case "sign": + err = options.CheckString("private key", optPrivateKey, err) + err = options.CheckUint64("shard hint", optShardHint, err) + case "verify": + err = options.CheckString("public key", optPublicKey, err) + err = options.CheckString("signature", optSignature, err) + err = options.CheckUint64("shard hint", optShardHint, err) + case "hash": + err = options.CheckString("key hash", optKeyHash, err) + err = options.CheckString("signature", optSignature, err) + err = options.CheckUint64("shard hint", optShardHint, err) + case "inclusion": + err = options.CheckString("leaf hash", optLeafHash, err) + err = options.CheckUint64("tree size", optTreeSize, err) + err = options.CheckString("root hash", optRootHash, err) + } + + return err +} diff --git a/cmd/sigsum-debug/leaf/sign/sign.go b/cmd/sigsum-debug/leaf/sign/sign.go new file mode 100644 index 0000000..348ae23 --- /dev/null +++ b/cmd/sigsum-debug/leaf/sign/sign.go @@ -0,0 +1,37 @@ +package sign + +import ( + "fmt" + "strings" + + "git.sigsum.org/sigsum-go/internal/fmtio" + "git.sigsum.org/sigsum-go/pkg/hex" + "git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optPrivateKey string, optShardHint uint64) error { + if len(args) != 0 { + return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) + } + data, err := fmtio.BytesFromStdin() + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + priv, err := fmtio.SignerFromHex(optPrivateKey) + if err != nil { + return fmt.Errorf("parse private key: %w", err) + } + + preimage := types.HashFn(data) + stm := types.Statement{ + ShardHint: optShardHint, + Checksum: *types.HashFn(preimage[:]), + } + sig, err := stm.Sign(priv) + if err != nil { + fmt.Errorf("sign leaf: %w", err) + } + + fmt.Printf("%s\n", hex.Serialize(sig[:])) + return nil +} diff --git a/cmd/sigsum-debug/leaf/verify/verify.go b/cmd/sigsum-debug/leaf/verify/verify.go new file mode 100644 index 0000000..a00791a --- /dev/null +++ b/cmd/sigsum-debug/leaf/verify/verify.go @@ -0,0 +1,9 @@ +package verify + +import ( + "fmt" +) + +func Main(args []string, optPublicKey, optSignature string, optShardHint uint64) error { + return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/main.go b/cmd/sigsum-debug/main.go new file mode 100644 index 0000000..7a1c894 --- /dev/null +++ b/cmd/sigsum-debug/main.go @@ -0,0 +1,65 @@ +// package main provides a tool named sigsum-debug +// +// Install: +// +// $ go install git.sigsum.org/sigsum-go/cmd/sigsum-debug@latest +// +// Usage: +// +// $ sigsum-debug help +// +package main + +import ( + "flag" + "fmt" + "log" + "os" + + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/head" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/key" + "git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf" + "git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug is a tool that helps debug sigsum logs on the command-line. +It is meant to be used in conjuction with other utilities such as curl. + +Usage: + + sigsum-debug help Usage message + sigsum-debug key Private and public key utilities + sigsum-debug leaf Hash, sign, and verify tree leaves + sigsum-debug head Sign and verify tree heads + +` + +func main() { + var err error + + log.SetFlags(0) + opt := options.New(os.Args[1:], func() { log.Printf(usage[1:]) }, func(_ *flag.FlagSet) {}) + switch opt.Name() { + case "help": + opt.Usage() + case "key": + err = key.Main(opt.Args()) + case "leaf": + err = leaf.Main(opt.Args()) + case "head": + err = head.Main(opt.Args()) + default: + err = fmt.Errorf(": invalid command %q, try \"help\"", opt.Name()) + } + + if err != nil { + format := "sigsum-debug %s%s" + if len(opt.Name()) == 0 { + format = "sigsum-debug%s%s" + } + + log.Printf(format, opt.Name(), err.Error()) + os.Exit(1) + } +} diff --git a/internal/fmtio/fmtio.go b/internal/fmtio/fmtio.go new file mode 100644 index 0000000..0e252d4 --- /dev/null +++ b/internal/fmtio/fmtio.go @@ -0,0 +1,79 @@ +// package fmtio provides basic utilities to format input and output +package fmtio + +import ( + "bytes" + "crypto" + "crypto/ed25519" + "fmt" + "io/ioutil" + "os" + + "git.sigsum.org/sigsum-go/pkg/hex" + "git.sigsum.org/sigsum-go/pkg/types" +) + +func BytesFromStdin() ([]byte, error) { + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return nil, err + } + return b, nil +} + +// StringFromStdin reads bytes from stdin, parsing them as a string without +// leading and trailing white space +func StringFromStdin() (string, error) { + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return "", err + } + return string(bytes.TrimSpace(b)), nil +} + +func SignerFromHex(s string) (crypto.Signer, error) { + b, err := hex.Deserialize(s) + if err != nil { + return nil, err + } + if n := len(b); n != ed25519.PrivateKeySize { + return nil, fmt.Errorf("invalid size %d", n) + } + return ed25519.PrivateKey(b), nil +} + +func PublicKeyFromHex(s string) (pub types.PublicKey, err error) { + b, err := hex.Deserialize(s) + if err != nil { + return pub, err + } + if n := len(b); n != types.PublicKeySize { + return pub, fmt.Errorf("invalid size %d", n) + } + copy(pub[:], b) + return +} + +func KeyHashFromHex(s string) (h types.Hash, err error) { + b, err := hex.Deserialize(s) + if err != nil { + return h, err + } + if n := len(b); n != types.HashSize { + return h, fmt.Errorf("invalid size %d", n) + } + copy(h[:], b) + return +} + +func SignatureFromHex(s string) (sig types.Signature, err error) { + b, err := hex.Deserialize(s) + if err != nil { + return sig, err + } + if n := len(b); n != types.SignatureSize { + return sig, fmt.Errorf("invalid size %d", n) + } + copy(sig[:], b) + return +} diff --git a/internal/options/options.go b/internal/options/options.go new file mode 100644 index 0000000..cc8e02a --- /dev/null +++ b/internal/options/options.go @@ -0,0 +1,65 @@ +package options + +import ( + "flag" + "fmt" +) + +const ( + DefaultString = "default string" + DefaultUint64 = 18446744073709551615 +) + +// New initializes a flag set using the provided arguments. +// +// - args should start with the (sub)command's name +// - usage is a function that prints a usage message +// - set is a function that sets the command's flag arguments +// +func New(args []string, usage func(), set func(*flag.FlagSet)) *flag.FlagSet { + if len(args) == 0 { + args = append(args, "") + } + + fs := flag.NewFlagSet(args[0], flag.ExitOnError) + fs.Usage = func() { + usage() + } + set(fs) + fs.Parse(args[1:]) + return fs +} + +// AddString adds a string option to a flag set +func AddString(fs *flag.FlagSet, opt *string, short, long, value string) { + fs.StringVar(opt, short, value, "") + fs.StringVar(opt, long, value, "") +} + +// AdUint64 adds an uint64 option to a flag set +func AddUint64(fs *flag.FlagSet, opt *uint64, short, long string, value uint64) { + fs.Uint64Var(opt, short, value, "") + fs.Uint64Var(opt, long, value, "") +} + +// CheckString checks that a string option has a non-default value +func CheckString(optionName, value string, err error) error { + if err != nil { + return err + } + if value == DefaultString { + return fmt.Errorf("%s is a required option", optionName) + } + return nil +} + +// CheckUint checks that an uint64 option has a non-default value +func CheckUint64(optionName string, value uint64, err error) error { + if err != nil { + return err + } + if value == DefaultUint64 { + return fmt.Errorf("%s is a required option", optionName) + } + return nil +} -- cgit v1.2.3 From b270a4c0d10947fe480bad7330b31bb793225968 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Thu, 28 Apr 2022 15:43:08 +0200 Subject: fix typos We should consider stop writing function names in comments. They don't add much. Actually they don't add anything except potentially confusion when they don't match the actualy name which is checked by the compiler. --- internal/options/options.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/options/options.go b/internal/options/options.go index cc8e02a..8e4ab0c 100644 --- a/internal/options/options.go +++ b/internal/options/options.go @@ -36,7 +36,7 @@ func AddString(fs *flag.FlagSet, opt *string, short, long, value string) { fs.StringVar(opt, long, value, "") } -// AdUint64 adds an uint64 option to a flag set +// AddUint64 adds an uint64 option to a flag set func AddUint64(fs *flag.FlagSet, opt *uint64, short, long string, value uint64) { fs.Uint64Var(opt, short, value, "") fs.Uint64Var(opt, long, value, "") @@ -53,7 +53,7 @@ func CheckString(optionName, value string, err error) error { return nil } -// CheckUint checks that an uint64 option has a non-default value +// CheckUint64 checks that an uint64 option has a non-default value func CheckUint64(optionName string, value uint64, err error) error { if err != nil { return err -- cgit v1.2.3