Skip to content

Commit

Permalink
Update keys.go
Browse files Browse the repository at this point in the history
  • Loading branch information
samricotta committed Feb 12, 2025
1 parent 894136a commit 32521de
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
This PR contains a series of PRs on BTC staking integration, with support for OP stack chains and
Cosmos chains.
* [#314](https://github.com/babylonlabs-io/finality-provider/pull/314) nit: Dockerfile AS casing
* [#320](https://github.com/babylonlabs-io/finality-provider/pull/320) chore: show `pubkey_hex` at `eotsd keys show` and `eotsd keys list`

### Bug Fixes

Expand Down
135 changes: 129 additions & 6 deletions eotsmanager/cmd/eotsd/daemon/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,50 @@ func NewKeysCmd() *cobra.Command {
panic("failed to find keys add command")
}

listCmd := util.GetSubCommand(keysCmd, "list")
if listCmd == nil {
panic("failed to find keys list command")
}

listCmd.RunE = runCommandPrintAllKeys
listCmd.Flags().StringP(flags.FlagOutput, "o", flags.OutputFormatText, "Output format (text|json)")

if showCmd := util.GetSubCommand(keysCmd, "show"); showCmd != nil {
showCmd.RunE = func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
// load eots keys
eotsPk, err := eotsmanager.LoadBIP340PubKeyFromKeyName(clientCtx.Keyring, args[0])
if err != nil {
// try by address
records, err := clientCtx.Keyring.List()
if err != nil {
return err
}
for _, r := range records {
addr, err := r.GetAddress()
if err != nil {
continue
}
if addr.String() == args[0] {
eotsPk, err = eotsmanager.LoadBIP340PubKeyFromKeyName(clientCtx.Keyring, r.Name)
if err != nil {
return err
}

return printFromKey(cmd, r.Name, eotsPk)
}
}

return fmt.Errorf("key not found: %s", args[0])
}

return printFromKey(cmd, args[0], eotsPk)
}
}

addCmd.Flags().String(rpcClientFlag, "", "The RPC address of a running eotsd to connect and save new key")

// Override the original RunE function to run almost the same as
Expand Down Expand Up @@ -171,24 +215,88 @@ func CommandPrintAllKeys() *cobra.Command {
RunE: runCommandPrintAllKeys,
}

flags.AddKeyringFlags(cmd.Flags())
cmd.Flags().String(flags.FlagHome, config.DefaultEOTSDir, "The path to the eotsd home directory")

return cmd
}

func runCommandPrintAllKeys(cmd *cobra.Command, _ []string) error {
homePath, err := getHomePath(cmd)
if err != nil {
return err
}

// Initialize keyring
backend, err := cmd.Flags().GetString("keyring-backend")
if err != nil {
return err
}

kr, err := eotsmanager.InitKeyring(homePath, backend, strings.NewReader(""))
if err != nil {
return fmt.Errorf("failed to init keyring: %w", err)
}

eotsKeys, err := getAllEOTSKeys(cmd)
if err != nil {
return err
}

records, err := kr.List()
if err != nil {
return err
}

keyMap := make(map[string]*cryptokeyring.Record)
for _, r := range records {
keyMap[r.Name] = r
}

type keyInfo struct {
Name string `json:"name"`
Address string `json:"address"`
EOTSPK string `json:"eots_pk"`
}

var keys []keyInfo
for keyName, key := range eotsKeys {
pk, err := schnorr.ParsePubKey(key)
if err != nil {
return err
}
eotsPk := types.NewBIP340PubKeyFromBTCPK(pk)
cmd.Printf("Key Name: %s, EOTS PK: %s\n", keyName, eotsPk.MarshalHex())

k, exists := keyMap[keyName]
if !exists {
continue
}

addr, err := k.GetAddress()
if err != nil {
return err
}

keys = append(keys, keyInfo{
Name: keyName,
Address: addr.String(),
EOTSPK: eotsPk.MarshalHex(),
})
}

if cmd.Flag(flags.FlagOutput).Value.String() == flags.OutputFormatJSON {
bz, err := json.MarshalIndent(keys, "", " ")
if err != nil {
return err
}
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(bz))

return err
}

for _, k := range keys {
cmd.Printf("Key Name: %s\nAddress: %s\nEOTS PK: %s\n\n",
k.Name, k.Address, k.EOTSPK)
}

return nil
Expand Down Expand Up @@ -245,8 +353,23 @@ func printFromKey(cmd *cobra.Command, keyName string, eotsPk *types.BIP340PubKey
}

ctx := cmd.Context()
mnemonic := ctx.Value(mnemonicCtxKey).(string) //nolint: forcetypeassert
showMnemonic := ctx.Value(mnemonicShowCtxKey).(bool)
var mnemonic string
var showMnemonic bool

if m := ctx.Value(mnemonicCtxKey); m != nil {
var ok bool
mnemonic, ok = m.(string)
if !ok {
return fmt.Errorf("mnemonic context value is not a string")
}
}
if sm := ctx.Value(mnemonicShowCtxKey); sm != nil {
var ok bool
showMnemonic, ok = sm.(bool)
if !ok {
return fmt.Errorf("show mnemonic context value is not a bool")
}
}

return printCreatePubKeyHex(cmd, k, eotsPk, showMnemonic, mnemonic, clientCtx.OutputFormat)
}
Expand All @@ -256,7 +379,7 @@ func printCreatePubKeyHex(cmd *cobra.Command, k *cryptokeyring.Record, eotsPk *t
if err != nil {
return err
}
keyOutput := newKeyOutputWithPubKeyHex(out, eotsPk)
keyOutput := newKeyOutputWithPubKeyHex(out, eotsPk.MarshalHex())

switch outputFormat {
case flags.OutputFormatText:
Expand Down Expand Up @@ -290,10 +413,10 @@ func printCreatePubKeyHex(cmd *cobra.Command, k *cryptokeyring.Record, eotsPk *t
return nil
}

func newKeyOutputWithPubKeyHex(k keys.KeyOutput, eotsPk *types.BIP340PubKey) KeyOutputWithPubKeyHex {
func newKeyOutputWithPubKeyHex(k keys.KeyOutput, eotsPk string) KeyOutputWithPubKeyHex {
return KeyOutputWithPubKeyHex{
KeyOutput: k,
PubKeyHex: eotsPk.MarshalHex(),
PubKeyHex: eotsPk,
}
}

Expand Down
58 changes: 31 additions & 27 deletions eotsmanager/cmd/eotsd/daemon/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"go.uber.org/zap"

"github.com/babylonlabs-io/finality-provider/eotsmanager"
eotscfg "github.com/babylonlabs-io/finality-provider/eotsmanager/config"
"github.com/babylonlabs-io/finality-provider/eotsmanager/config"
"github.com/babylonlabs-io/finality-provider/testutil"
)

Expand All @@ -30,31 +30,42 @@ func FuzzNewKeysCmd(f *testing.F) {
tDir := t.TempDir()
tempHome := filepath.Join(tDir, "homeeots")
homeFlagFilled := fmt.Sprintf("--%s=%s", sdkflags.FlagHome, tempHome)
rootCmdBuff := new(bytes.Buffer)
keyringBackendFlagFilled := fmt.Sprintf("--%s=%s", sdkflags.FlagKeyringBackend, keyring.BackendTest)

// Create separate buffers for stdout and stderr
stdoutBuf := new(bytes.Buffer)
stderrBuf := new(bytes.Buffer)

root.SetOut(stdoutBuf)
root.SetErr(stderrBuf)

defer func() {
err := os.RemoveAll(tempHome)
require.NoError(t, err)
}()

// Initialize the EOTS manager
_, _ = exec(t, root, rootCmdBuff, "init", homeFlagFilled)
_, _ = exec(t, root, "init", homeFlagFilled)

// Generate a random key name
keyName := testutil.GenRandomHexStr(r, 5)

// Execute the keys add command
keyringBackendFlagFilled := fmt.Sprintf("--%s=%s", sdkflags.FlagKeyringBackend, keyring.BackendTest)
_, _ = exec(t, root, rootCmdBuff, "keys", "add", keyName, homeFlagFilled, keyringBackendFlagFilled)
// Execute the keys add command with keyring backend
_, _ = exec(t, root, "keys", "add", keyName, homeFlagFilled, keyringBackendFlagFilled)

// Execute the keys list command with keyring backend
_, _ = exec(t, root, "keys", "list", homeFlagFilled, keyringBackendFlagFilled)

// Execute the keys list command
_, listOutput := exec(t, root, rootCmdBuff, "keys", "list", homeFlagFilled)
// Log output for debugging
t.Logf("Stdout: %q", stdoutBuf.String())
t.Logf("Stderr: %q", stderrBuf.String())

// Check if the added key is in the list
require.Contains(t, listOutput, keyName)
// Basic check - key name should be in output
require.Contains(t, stdoutBuf.String(), keyName, "List output should contain the key name")

// Load the EOTS manager and verify the key existence
eotsCfg := eotscfg.DefaultConfigWithHomePath(tempHome)
dbBackend, err := eotsCfg.DatabaseConfig.GetDBBackend()
cfg := config.DefaultConfigWithHomePath(tempHome)
dbBackend, err := cfg.DatabaseConfig.GetDBBackend()
require.NoError(t, err)
defer func() {
err := dbBackend.Close()
Expand All @@ -64,29 +75,22 @@ func FuzzNewKeysCmd(f *testing.F) {
eotsManager, err := eotsmanager.NewLocalEOTSManager(tempHome, "test", dbBackend, zap.NewNop())
require.NoError(t, err, "Should be able to create EOTS manager")

// Verify the key exists and has correct BIP340 public key
pubKey, err := eotsManager.LoadBIP340PubKeyFromKeyName(keyName)
require.NoError(t, err, "Should be able to load public key")
require.NotNil(t, pubKey, "Public key should not be nil")

// Verify the public key is in the output
hexPk := pubKey.MarshalHex()
require.Contains(t, stdoutBuf.String(), hexPk, "List output should contain the BIP340 public key hex")
})
}

// exec executes a command based on the cmd passed, the args should only search for subcommands, not parent commands
func exec(t *testing.T, root *cobra.Command, rootCmdBuf *bytes.Buffer, args ...string) (c *cobra.Command, output string) {
buf := new(bytes.Buffer)
root.SetOut(buf)
root.SetErr(buf)
// exec executes a command based on the cmd passed
func exec(t *testing.T, root *cobra.Command, args ...string) (*cobra.Command, error) {
root.SetArgs(args)

c, err := root.ExecuteC()
require.NoError(t, err)

outStr := buf.String()
if len(outStr) > 0 {
return c, outStr
}

_, err = buf.Write(rootCmdBuf.Bytes())
require.NoError(t, err)

return c, buf.String()
return c, err
}

0 comments on commit 32521de

Please sign in to comment.