Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: list all keys in store #234

Merged
merged 4 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* [#228](https://github.com/babylonlabs-io/finality-provider/pull/228) Save key name mapping in eotsd import commands
* [#227](https://github.com/babylonlabs-io/finality-provider/pull/227) Fix FP submission loop
* [#226](https://github.com/babylonlabs-io/finality-provider/pull/226) Update local fp before register
* [#234](https://github.com/babylonlabs-io/finality-provider/pull/234) eotsd ls command

## v0.13.1

Expand Down
74 changes: 74 additions & 0 deletions eotsmanager/cmd/eotsd/daemon/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"io"

"github.com/babylonlabs-io/babylon/types"
Expand Down Expand Up @@ -124,6 +125,79 @@ func saveKeyNameMapping(cmd *cobra.Command, keyName string) (*types.BIP340PubKey
return eotsPk, nil
}

// CommandPrintAllKeys prints all EOTS keys
func CommandPrintAllKeys() *cobra.Command {
var cmd = &cobra.Command{
Use: "ls",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be list?

Aliases: []string{"ls"},
Short: "Print all EOTS keys from database",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Short: "Print all EOTS keys from database",
Short: "Print all EOTS key names and public keys mapping from database",

Example: `eotsd ls --home=/path/to/cfg`,
Args: cobra.NoArgs,
RunE: runCommandPrintAllKeys,
}

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

return cmd
}

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

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())
}

return nil
}

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

// Load configuration
cfg, err := config.LoadConfig(homePath)
if err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}

// Setup logger
logger, err := log.NewRootLoggerWithFile(config.LogFile(homePath), cfg.LogLevel)
if err != nil {
return nil, fmt.Errorf("failed to load the logger: %w", err)
}

// Get database backend
dbBackend, err := cfg.DatabaseConfig.GetDBBackend()
if err != nil {
return nil, fmt.Errorf("failed to create db backend: %w", err)
}
defer dbBackend.Close()

// Create EOTS manager
eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, cfg.KeyringBackend, dbBackend, logger)
if err != nil {
return nil, fmt.Errorf("failed to create EOTS manager: %w", err)
}

res, err := eotsManager.ListEOTSKeys()
if err != nil {
return nil, fmt.Errorf("failed to get keys from db: %w", err)
}

return res, nil
}

func printFromKey(cmd *cobra.Command, keyName string, eotsPk *types.BIP340PubKey) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions eotsmanager/cmd/eotsd/daemon/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func NewRootCmd() *cobra.Command {
NewKeysCmd(),
NewStartCmd(),
version.CommandVersion("eotsd"),
CommandPrintAllKeys(),
)

return rootCmd
Expand Down
4 changes: 4 additions & 0 deletions eotsmanager/localmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,7 @@ func (lm *LocalEOTSManager) keyExists(name string) bool {
_, err := lm.kr.Key(name)
return err == nil
}

func (lm *LocalEOTSManager) ListEOTSKeys() (map[string][]byte, error) {
return lm.es.GetAllEOTSKeyNames()
}
28 changes: 28 additions & 0 deletions eotsmanager/store/eotsstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,34 @@ func (s *EOTSStore) GetEOTSKeyName(pk []byte) (string, error) {
return keyName, nil
}

// GetAllEOTSKeyNames retrieves all keys and values.
// Returns keyName -> btcPK
func (s *EOTSStore) GetAllEOTSKeyNames() (map[string][]byte, error) {
result := make(map[string][]byte)

err := s.db.View(func(tx kvdb.RTx) error {
eotsBucket := tx.ReadBucket(eotsBucketName)
if eotsBucket == nil {
return ErrCorruptedEOTSDb
}

return eotsBucket.ForEach(func(k, v []byte) error {
if k == nil || v == nil {
return fmt.Errorf("encountered invalid key or value in bucket")
}
result[string(v)] = k

return nil
})
}, func() {})

if err != nil {
return nil, err
}

return result, nil
}

func (s *EOTSStore) SaveSignRecord(
height uint64,
chainID []byte,
Expand Down
51 changes: 51 additions & 0 deletions eotsmanager/store/eotsstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,54 @@ func FuzzSignStore(f *testing.F) {
require.False(t, found)
})
}

// FuzzListKeysEOTSStore tests getting all keys from store
func FuzzListKeysEOTSStore(f *testing.F) {
testutil.AddRandomSeedsToFuzzer(f, 10)
f.Fuzz(func(t *testing.T, seed int64) {
t.Parallel()
r := rand.New(rand.NewSource(seed))

homePath := t.TempDir()
cfg := config.DefaultDBConfigWithHomePath(homePath)

dbBackend, err := cfg.GetDBBackend()
require.NoError(t, err)

vs, err := store.NewEOTSStore(dbBackend)
require.NoError(t, err)

defer func() {
dbBackend.Close()
}()

expected := make(map[string][]byte)
for i := 0; i < r.Intn(10); i++ {
expectedKeyName := testutil.GenRandomHexStr(r, 10)
_, btcPk, err := datagen.GenRandomBTCKeyPair(r)
require.NoError(t, err)
expected[expectedKeyName] = schnorr.SerializePubKey(btcPk)

err = vs.AddEOTSKeyName(
btcPk,
expectedKeyName,
)
require.NoError(t, err)
}

keys, err := vs.GetAllEOTSKeyNames()
require.NoError(t, err)

for keyName, btcPk := range expected {
gotBtcPk, ok := keys[keyName]
require.True(t, ok)

parsedGot, err := schnorr.ParsePubKey(gotBtcPk)
require.NoError(t, err)
parsedExpected, err := schnorr.ParsePubKey(btcPk)
require.NoError(t, err)

require.Equal(t, parsedExpected, parsedGot)
}
})
}
49 changes: 49 additions & 0 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package e2etest

import (
"bytes"
"encoding/json"
"errors"
"fmt"
eotscmd "github.com/babylonlabs-io/finality-provider/eotsmanager/cmd/eotsd/daemon"
eotscfg "github.com/babylonlabs-io/finality-provider/eotsmanager/config"
"github.com/babylonlabs-io/finality-provider/finality-provider/store"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/jessevdk/go-flags"
"log"
"math/rand"
"os"
Expand Down Expand Up @@ -352,3 +357,47 @@ func TestRemoveMerkleProofsCmd(t *testing.T) {
return errors.Is(err, store.ErrPubRandProofNotFound)
}, eventuallyWaitTimeOut, eventuallyPollTime)
}

func TestPrintEotsCmd(t *testing.T) {
tm := StartManager(t)
r := rand.New(rand.NewSource(time.Now().Unix()))
defer tm.Stop(t)

expected := make(map[string]string)
for i := 0; i < r.Intn(10); i++ {
eotsKeyName := fmt.Sprintf("eots-key-%s", datagen.GenRandomHexStr(r, 4))
ekey, err := tm.EOTSClient.CreateKey(eotsKeyName, passphrase, hdPath)
require.NoError(t, err)
pk, err := schnorr.ParsePubKey(ekey)
require.NoError(t, err)
expected[eotsKeyName] = bbntypes.NewBIP340PubKeyFromBTCPK(pk).MarshalHex()
}

tm.EOTSServerHandler.Stop()

cmd := eotscmd.CommandPrintAllKeys()

defaultConfig := eotscfg.DefaultConfigWithHomePath(tm.EOTSHomeDir)
fileParser := flags.NewParser(defaultConfig, flags.Default)
err := flags.NewIniParser(fileParser).WriteFile(eotscfg.CfgFile(tm.EOTSHomeDir), flags.IniIncludeDefaults)
require.NoError(t, err)

cmd.SetArgs([]string{
"--home=" + tm.EOTSHomeDir,
})

var outputBuffer bytes.Buffer
cmd.SetOut(&outputBuffer)
cmd.SetErr(&outputBuffer)

err = cmd.Execute()
require.NoError(t, err)

output := outputBuffer.String()
t.Logf("Captured output: %s", output)

for keyName, eotsPK := range expected {
require.Contains(t, output, keyName)
require.Contains(t, output, eotsPK)
}
}
2 changes: 2 additions & 0 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ var (
type TestManager struct {
Wg sync.WaitGroup
EOTSServerHandler *EOTSServerHandler
EOTSHomeDir string
FpConfig *fpcfg.Config
Fps []*service.FinalityProviderApp
EOTSClient *client.EOTSManagerGRpcClient
Expand Down Expand Up @@ -138,6 +139,7 @@ func StartManager(t *testing.T) *TestManager {

tm := &TestManager{
EOTSServerHandler: eh,
EOTSHomeDir: eotsHomeDir,
FpConfig: cfg,
EOTSClient: eotsCli,
BBNClient: bc,
Expand Down
Loading