Skip to content

Commit

Permalink
Merge branch 'main' into gai/add-randomness-ahead-height
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry committed Dec 20, 2024
2 parents 6ee90fc + 7140c9e commit 0f43759
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 8 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/)
* [#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
* [#233](https://github.com/babylonlabs-io/finality-provider/pull/233) Refactor CommitPubRand
* [#234](https://github.com/babylonlabs-io/finality-provider/pull/234) eotsd ls command

## v0.13.1

Expand Down
57 changes: 54 additions & 3 deletions docs/finality-provider-operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ gain an overall understanding of the finality provider.
2. [Withdrawing Rewards](#52-withdrawing-rewards)
3. [Jailing and Unjailing](#53-jailing-and-unjailing)
4. [Slashing](#54-slashing)
5. [Prometheus Metrics](#55-prometheus-metrics)
6. [Withdrawing Rewards](#56-withdrawing-rewards)

## 1. A note about Phase-1 Finality Providers

Expand Down Expand Up @@ -493,7 +495,7 @@ saves the finality provider information in the database.
fpd create-finality-provider \
--chain-id bbn-test-5 \
--eots-pk <eots-pk-hex> \
--commission 0.05 \
--commission-rate 0.05 \
--key-name finality-provider \
--moniker "MyFinalityProvider" \
--website "https://myfinalityprovider.com" \
Expand Down Expand Up @@ -598,7 +600,8 @@ When jailed, the following happens to a finality provider:
- Delegator rewards stop

To unjail a finality provider, you must complete the following steps:
1. Fix the underlying issue that caused jailing (e.g., ensure your node is properly synced and voting)
1. Fix the underlying issue that caused jailing (e.g., ensure your node is
properly synced and voting)
2. Wait for the jailing period to pass (defined by finality module parameters)
3. Send the unjail transaction to the Babylon chain using the following command:

Expand Down Expand Up @@ -626,7 +629,7 @@ removal from the active set.
> ⚠️ **Critical**: Slashing is irreversible and results in
> permanent removal from the network.
### 5.5 Prometheus
### 5.5. Prometheus Metrics

The finality provider exposes Prometheus metrics for monitoring your
finality provider. The metrics endpoint is configurable in `fpd.conf`:
Expand Down Expand Up @@ -657,3 +660,51 @@ For a complete list of available metrics, see:
- Finality Provider metrics: [fp_collectors.go](../metrics/fp_collectors.go)
- EOTS metrics: [eots_collectors.go](../metrics/eots_collectors.go)

### 5.6. Withdrawing Rewards

When you are ready to withdraw your rewards, you have the option first to set
the address to withdraw your rewards to.

```shell
fpd set-withdraw-addr <new-address> --from <registered-bbn-address>
--keyring-backend test --home <home-dir> --fees <fees>
```

Parameters:
- `<new-address>`: The new address to withdraw rewards to.
- `--from`: The finality provider's registered Babylon address.
- `--keyring-backend`: The keyring backend to use.
- `--home`: The home directory for the finality provider.
- `--fees`: The fees to pay for the transaction, should be over `400ubbn`.
These fees are paid from the account specified in `--from`.

This command should ask you to
`confirm transaction before signing and broadcasting [y/N]:` and output the
transaction hash.

Once you have set the address, you can withdraw your rewards by running the
following command:

```shell
fpd withdraw-reward <type> --from <registered-bbn-address>
--keyring-backend test --home <home-dir> --fees <fees>
```

Parameters:
- `<type>`: The type of reward to withdraw (one of `finality_provider`,
`btc_delegation`)
- `--from`: The finality provider's registered Babylon address.
- `--keyring-backend`: The keyring backend to use.
- `--home`: The home directory for the finality provider.
- `--fees`: The fees to pay for the transaction, should be over `400ubbn`.
These fees are paid from the account specified in `--from`.

Again, this command should ask you to
`confirm transaction before signing and broadcasting [y/N]:` and output the
transaction hash.

This will withdraw **ALL** accumulated rewards to the address you set in the
`set-withdraw-addr` command if you set one. If no withdrawal address was set,
the rewards will be withdrawn to your finality provider address.

Congratulations! You have successfully set up and operated a finality provider.
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: "list",
Aliases: []string{"ls"},
Short: "Print all EOTS key names and public keys mapping from database.",
Example: `eotsd list --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)
}
})
}
57 changes: 52 additions & 5 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package e2etest

import (
"bytes"
"encoding/json"
"errors"
"fmt"
Expand All @@ -13,17 +14,19 @@ import (
"testing"
"time"

"github.com/babylonlabs-io/finality-provider/finality-provider/store"

bbntypes "github.com/babylonlabs-io/babylon/types"
bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"

sdkmath "cosmossdk.io/math"
"github.com/babylonlabs-io/babylon/testutil/datagen"
bbntypes "github.com/babylonlabs-io/babylon/types"
bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/jessevdk/go-flags"
"github.com/stretchr/testify/require"

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/cmd/fpd/daemon"
"github.com/babylonlabs-io/finality-provider/finality-provider/store"
"github.com/babylonlabs-io/finality-provider/types"
)

Expand Down Expand Up @@ -356,3 +359,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

0 comments on commit 0f43759

Please sign in to comment.