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(cmd): edit finality provider description #90

Merged
merged 19 commits into from
Oct 15, 2024
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## Unreleased

### Improvements

* [#90](https://github.com/babylonlabs-io/finality-provider/pull/90) CLI edit finality provider
62 changes: 62 additions & 0 deletions clientcontroller/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package clientcontroller
import (
"context"
"fmt"
"github.com/babylonlabs-io/finality-provider/finality-provider/proto"
"strings"
"time"

sdkErr "cosmossdk.io/errors"
Expand Down Expand Up @@ -510,6 +512,66 @@ func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.Finali
return fps, nil
}

func (bc *BabylonController) QueryFinalityProvider(fpPk *btcec.PublicKey) (*btcstakingtypes.QueryFinalityProviderResponse, error) {
fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk)
res, err := bc.bbnClient.QueryClient.FinalityProvider(fpPubKey.MarshalHex())
if err != nil {
return nil, fmt.Errorf("failed to query the finality provider %s: %v", fpPubKey.MarshalHex(), err)
}

return res, nil
}

func (bc *BabylonController) EditFinalityProvider(fpPk *btcec.PublicKey,
rate *sdkmath.LegacyDec, reqDesc *proto.Description) (*btcstakingtypes.MsgEditFinalityProvider, error) {
fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk)

fpRes, err := bc.QueryFinalityProvider(fpPk)
Lazar955 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

if !strings.EqualFold(fpRes.FinalityProvider.Addr, bc.mustGetTxSigner()) {
return nil, fmt.Errorf("the signer does not correspond to the finality provider's "+
"Babylon address, expected %s got %s", bc.mustGetTxSigner(), fpRes.FinalityProvider.Addr)
}

getValueOrDefault := func(reqValue, defaultValue string) string {
if reqValue != "" {
return reqValue
}
return defaultValue
}

resDesc := fpRes.FinalityProvider.Description

desc := &sttypes.Description{
Moniker: getValueOrDefault(reqDesc.Moniker, resDesc.Moniker),
Identity: getValueOrDefault(reqDesc.Identity, resDesc.Identity),
Website: getValueOrDefault(reqDesc.Website, resDesc.Website),
SecurityContact: getValueOrDefault(reqDesc.SecurityContact, resDesc.SecurityContact),
Details: getValueOrDefault(reqDesc.Details, resDesc.Details),
}

msg := &btcstakingtypes.MsgEditFinalityProvider{
Addr: bc.mustGetTxSigner(),
BtcPk: fpPubKey.MustMarshal(),
Description: desc,
Commission: fpRes.FinalityProvider.Commission,
}

if rate != nil {
msg.Commission = rate
}

_, err = bc.reliablySendMsg(msg, emptyErrs, emptyErrs)
if err != nil {
return nil, fmt.Errorf("failed to query the finality provider %s: %v", fpPk.SerializeCompressed(), err)
}

return msg, nil
}

func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfoResponse, error) {
res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip()
if err != nil {
Expand Down
9 changes: 7 additions & 2 deletions clientcontroller/interface.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package clientcontroller

import (
"fmt"

"cosmossdk.io/math"
sdkmath "cosmossdk.io/math"
"fmt"
btcstakingtypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/babylonlabs-io/finality-provider/finality-provider/proto"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/chaincfg"
Expand Down Expand Up @@ -49,6 +51,9 @@ type ClientController interface {
// QueryFinalityProviderSlashedOrJailed queries if the finality provider is slashed or jailed
QueryFinalityProviderSlashedOrJailed(fpPk *btcec.PublicKey) (slashed bool, jailed bool, err error)

// EditFinalityProvider edits description and commission of a finality provider
EditFinalityProvider(fpPk *btcec.PublicKey, rate *sdkmath.LegacyDec, reqDesc *proto.Description) (*btcstakingtypes.MsgEditFinalityProvider, error)
Lazar955 marked this conversation as resolved.
Show resolved Hide resolved

// QueryLatestFinalizedBlocks returns the latest finalized blocks
QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error)

Expand Down
76 changes: 72 additions & 4 deletions finality-provider/cmd/fpd/daemon/daemon_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/babylonlabs-io/finality-provider/finality-provider/proto"
"strconv"

"cosmossdk.io/math"
"github.com/babylonlabs-io/babylon/types"
bbntypes "github.com/babylonlabs-io/babylon/types"
fpcmd "github.com/babylonlabs-io/finality-provider/finality-provider/cmd"
fpcfg "github.com/babylonlabs-io/finality-provider/finality-provider/config"
dc "github.com/babylonlabs-io/finality-provider/finality-provider/service/client"
"github.com/cosmos/cosmos-sdk/client"
sdkflags "github.com/cosmos/cosmos-sdk/client/flags"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

fpcmd "github.com/babylonlabs-io/finality-provider/finality-provider/cmd"
fpcfg "github.com/babylonlabs-io/finality-provider/finality-provider/config"
dc "github.com/babylonlabs-io/finality-provider/finality-provider/service/client"
)

var (
Expand Down Expand Up @@ -446,6 +446,74 @@ func runCommandAddFinalitySig(cmd *cobra.Command, args []string) error {
return nil
}

// CommandEditFinalityDescription edits description of finality provider
func CommandEditFinalityDescription() *cobra.Command {
var cmd = &cobra.Command{
Use: "edit-finality-provider [btc_pk]",
Aliases: []string{"efp"},
Short: "Edit finality provider data without resetting unchanged fields",
Long: "Edit the details of a finality provider using the specified BTC public key. " +
"\nIf one or more optional flags are passed (such as --moniker, --website, etc.), " +
"the corresponding values are updated, while unchanged fields retain their current values from the Babylon Node.",
Lazar955 marked this conversation as resolved.
Show resolved Hide resolved
Example: fmt.Sprintf(`fpd edit-finality-provider [btc_pk] --daemon-address %s --moniker "new-moniker"`, defaultFpdDaemonAddress),
Args: cobra.ExactArgs(1),
RunE: runCommandEditFinalityDescription,
}
cmd.Flags().String(fpdDaemonAddressFlag, defaultFpdDaemonAddress, "The RPC server address of fpd")
cmd.Flags().String(monikerFlag, "", "The finality provider's (optional) moniker")
cmd.Flags().String(websiteFlag, "", "The finality provider's (optional) website")
cmd.Flags().String(securityContactFlag, "", "The finality provider's (optional) security contact email")
cmd.Flags().String(detailsFlag, "", "The finality provider's (optional) details")
cmd.Flags().String(identityFlag, "", "The (optional) identity signature (ex. UPort or Keybase)")
cmd.Flags().String(commissionRateFlag, "", "The (optional) commission rate percentage (ex. 0.2)")

return cmd
}

func runCommandEditFinalityDescription(cmd *cobra.Command, args []string) error {
fpPk, err := bbntypes.NewBIP340PubKeyFromHex(args[0])
if err != nil {
return err
}

flags := cmd.Flags()
daemonAddress, err := flags.GetString(fpdDaemonAddressFlag)
if err != nil {
return fmt.Errorf("failed to read flag %s: %w", fpdDaemonAddressFlag, err)
}

grpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress)
if err != nil {
return err
}
defer func() {
if err := cleanUp(); err != nil {
fmt.Printf("Failed to clean up grpc client: %v\n", err)
}
}()

moniker, _ := cmd.Flags().GetString(monikerFlag)
website, _ := cmd.Flags().GetString(websiteFlag)
securityContact, _ := cmd.Flags().GetString(securityContactFlag)
details, _ := cmd.Flags().GetString(detailsFlag)
identity, _ := cmd.Flags().GetString(identityFlag)
rate, _ := cmd.Flags().GetString(commissionRateFlag)

desc := &proto.Description{
Moniker: moniker,
Identity: identity,
Website: website,
SecurityContact: securityContact,
Details: details,
}

if err := grpcClient.EditFinalityProvider(cmd.Context(), fpPk, desc, rate); err != nil {
return fmt.Errorf("failed to edit finality provider %v err %v", fpPk.MarshalHex(), err)
}

return nil
}

func printRespJSON(resp interface{}) {
jsonBytes, err := json.MarshalIndent(resp, "", " ")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion finality-provider/cmd/fpd/daemon/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ const (
websiteFlag = "website"
securityContactFlag = "security-contact"
detailsFlag = "details"
commissionRateFlag = "commission"
commissionRateFlag = "commission-rate"
)
1 change: 1 addition & 0 deletions finality-provider/cmd/fpd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func main() {
daemon.CommandGetDaemonInfo(), daemon.CommandCreateFP(), daemon.CommandLsFP(),
daemon.CommandInfoFP(), daemon.CommandRegisterFP(), daemon.CommandAddFinalitySig(),
daemon.CommandExportFP(), daemon.CommandTxs(), daemon.CommandUnjailFP(),
daemon.CommandEditFinalityDescription(),
)

if err := cmd.Execute(); err != nil {
Expand Down
Loading