Skip to content

Commit

Permalink
chore: opt to set eots pk in fpd create-finality-provider (#51)
Browse files Browse the repository at this point in the history
New flag to command `create-finality-provider` to allow specify eots-pk
as hex in the parameters to avoid creation of new EOTS key to store in
database

This will be useful for finality providers that are in Phase-1 and will
need to transition to Phase-2.
During Phase-1, only EOTS keys were generated for Phase-2 these finality
providers will need to use the same EOTS pk to load and start their
finality provider
  • Loading branch information
RafilxTenfen authored Sep 12, 2024
1 parent f9c8130 commit d06cde5
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 21 deletions.
2 changes: 1 addition & 1 deletion eotsmanager/proto/eotsmanager.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions finality-provider/cmd/fpd/daemon/daemon_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"

"cosmossdk.io/math"
"github.com/babylonlabs-io/babylon/types"
bbntypes "github.com/babylonlabs-io/babylon/types"
"github.com/cosmos/cosmos-sdk/client"
sdkflags "github.com/cosmos/cosmos-sdk/client/flags"
Expand Down Expand Up @@ -66,6 +67,12 @@ func CommandCreateFP() *cobra.Command {
Use: "create-finality-provider",
Aliases: []string{"cfp"},
Short: "Create a finality provider object and save it in database.",
Long: fmt.Sprintf(`
Create a new finality provider object and store it in the finality provider database.
It needs to have an operating EOTS manager available and running.
If the flag %s is set, it will ask for the key record from the EOTS manager for the
corresponding EOTS public key. If it is not set, it will create a new EOTS key`, fpEotsPkFlag),
Example: fmt.Sprintf(`fpd create-finality-provider --daemon-address %s ...`, defaultFpdDaemonAddress),
Args: cobra.NoArgs,
RunE: fpcmd.RunEWithClientCtx(runCommandCreateFP),
Expand All @@ -84,6 +91,7 @@ func CommandCreateFP() *cobra.Command {
f.String(websiteFlag, "", "An optional website link")
f.String(securityContactFlag, "", "An email for security contact")
f.String(detailsFlag, "", "Other optional details")
f.String(fpEotsPkFlag, "", "Optional hex EOTS public key, if not provided a new one will be created")

return cmd
}
Expand Down Expand Up @@ -135,10 +143,24 @@ func runCommandCreateFP(ctx client.Context, cmd *cobra.Command, _ []string) erro
return fmt.Errorf("failed to read flag %s: %w", hdPathFlag, err)
}

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

if len(eotsPkHex) > 0 {
// if is set, validate before the creation request
_, err := types.NewBIP340PubKeyFromHex(eotsPkHex)
if err != nil {
return fmt.Errorf("invalid eots public key %s: %w", eotsPkHex, err)
}
}

info, err := client.CreateFinalityProvider(
context.Background(),
keyName,
chainId,
eotsPkHex,
passphrase,
hdPath,
description,
Expand Down
2 changes: 1 addition & 1 deletion finality-provider/cmd/fpd/daemon/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func runInitCmd(ctx client.Context, cmd *cobra.Command, args []string) error {
homePath = util.CleanAndExpandPath(homePath)
force, err := cmd.Flags().GetBool(forceFlag)
if err != nil {
return fmt.Errorf("failed to read flag %s: %w", fpEotsPkFlag, err)
return fmt.Errorf("failed to read flag %s: %w", forceFlag, err)
}

if util.FileExists(homePath) && !force {
Expand Down
19 changes: 16 additions & 3 deletions finality-provider/proto/finality_providers.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions finality-provider/proto/finality_providers.proto
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ message CreateFinalityProviderRequest {
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// eots_pk_hex it is the optional EOTS public key and used to ask for
// the key record from the EOTS manager for the corresponding EOTS public key.
// If this property is not set, it will create a new EOTS key.
string eots_pk_hex = 7;
}

message CreateFinalityProviderResponse {
Expand Down
20 changes: 13 additions & 7 deletions finality-provider/service/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ func (app *FinalityProviderApp) Stop() error {

func (app *FinalityProviderApp) CreateFinalityProvider(
keyName, chainID, passPhrase, hdPath string,
eotsPk *bbntypes.BIP340PubKey,
description *stakingtypes.Description,
commission *sdkmath.LegacyDec,
) (*CreateFinalityProviderResult, error) {
Expand All @@ -360,6 +361,7 @@ func (app *FinalityProviderApp) CreateFinalityProvider(
chainID: chainID,
passPhrase: passPhrase,
hdPath: hdPath,
eotsPk: eotsPk,
description: description,
commission: commission,
errResponse: make(chan error, 1),
Expand Down Expand Up @@ -398,14 +400,18 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF
}

// 2. create EOTS key
fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath)
if err != nil {
return nil, err
}
fpPk, err := bbntypes.NewBIP340PubKey(fpPkBytes)
if err != nil {
return nil, err
fpPk := req.eotsPk
if req.eotsPk == nil {
fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath)
if err != nil {
return nil, err
}
fpPk, err = bbntypes.NewBIP340PubKey(fpPkBytes)
if err != nil {
return nil, err
}
}

fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), req.passPhrase)
if err != nil {
return nil, fmt.Errorf("failed to get finality-provider record: %w", err)
Expand Down
18 changes: 17 additions & 1 deletion finality-provider/service/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,24 @@ func FuzzRegisterFinalityProvider(f *testing.F) {
require.NoError(t, err)
}()

var eotsPk *bbntypes.BIP340PubKey
eotsPk = nil
generateEotsKeyBefore := r.Int31n(10) > 5
if generateEotsKeyBefore {
// sometimes uses the previously generated EOTS pk
eotsKeyName := testutil.GenRandomHexStr(r, 4)
eotsPkBz, err := em.CreateKey(eotsKeyName, passphrase, hdPath)
require.NoError(t, err)
eotsPk, err = bbntypes.NewBIP340PubKey(eotsPkBz)
require.NoError(t, err)
}

// create a finality-provider object and save it to db
fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath)
fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath, eotsPk)
if generateEotsKeyBefore {
require.Equal(t, eotsPk, bbntypes.NewBIP340PubKeyFromBTCPK(fp.BtcPk))
}

btcSig := new(bbntypes.BIP340Signature)
err = btcSig.Unmarshal(fp.Pop.BtcSig)
require.NoError(t, err)
Expand Down
3 changes: 2 additions & 1 deletion finality-provider/service/client/rpcclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (c *FinalityProviderServiceGRpcClient) RegisterFinalityProvider(

func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider(
ctx context.Context,
keyName, chainID, passphrase, hdPath string,
keyName, chainID, eotsPkHex, passphrase, hdPath string,
description types.Description,
commission *sdkmath.LegacyDec,
) (*proto.CreateFinalityProviderResponse, error) {
Expand All @@ -77,6 +77,7 @@ func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider(
HdPath: hdPath,
Description: descBytes,
Commission: commission.String(),
EotsPkHex: eotsPkHex,
}

res, err := c.client.CreateFinalityProvider(ctx, req)
Expand Down
2 changes: 1 addition & 1 deletion finality-provider/service/fp_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc cli
require.NoError(t, err)

// create registered finality-provider
fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath)
fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath, nil)
pubRandProofStore := app.GetPubRandProofStore()
fpStore := app.GetFinalityProviderStore()
err = fpStore.SetFpStatus(fp.BtcPk, proto.FinalityProviderStatus_REGISTERED)
Expand Down
1 change: 1 addition & 0 deletions finality-provider/service/fp_store_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type createFinalityProviderRequest struct {
passPhrase string
hdPath string
chainID string
eotsPk *bbntypes.BIP340PubKey
description *stakingtypes.Description
commission *sdkmath.LegacyDec
errResponse chan error
Expand Down
20 changes: 17 additions & 3 deletions finality-provider/service/rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetI
}

// CreateFinalityProvider generates a finality-provider object and saves it in the database
func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.CreateFinalityProviderRequest) (
*proto.CreateFinalityProviderResponse, error) {

func (r *rpcServer) CreateFinalityProvider(
ctx context.Context,
req *proto.CreateFinalityProviderRequest,
) (*proto.CreateFinalityProviderResponse, error) {
commissionRate, err := math.LegacyNewDecFromStr(req.Commission)
if err != nil {
return nil, err
Expand All @@ -94,11 +95,17 @@ func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.Creat
return nil, err
}

eotsPk, err := parseOptEotsPk(req.EotsPkHex)
if err != nil {
return nil, err
}

result, err := r.app.CreateFinalityProvider(
req.KeyName,
req.ChainId,
req.Passphrase,
req.HdPath,
eotsPk,
&description,
&commissionRate,
)
Expand Down Expand Up @@ -218,3 +225,10 @@ func (r *rpcServer) SignMessageFromChainKey(ctx context.Context, req *proto.Sign

return &proto.SignMessageFromChainKeyResponse{Signature: signature}, nil
}

func parseOptEotsPk(eotsPkHex string) (*bbntypes.BIP340PubKey, error) {
if len(eotsPkHex) > 0 {
return bbntypes.NewBIP340PubKeyFromHex(eotsPkHex)
}
return nil, nil
}
2 changes: 1 addition & 1 deletion itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser
err = tm.BabylonHandler.BabylonNode.TxBankSend(fpBbnKeyInfo.AccAddress.String(), "1000000ubbn")
require.NoError(t, err)

res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, desc, &commission)
res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, nil, desc, &commission)
require.NoError(t, err)
fpPk, err := bbntypes.NewBIP340PubKeyFromHex(res.FpInfo.BtcPkHex)
require.NoError(t, err)
Expand Down
5 changes: 3 additions & 2 deletions testutil/datagen.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
sdkmath "cosmossdk.io/math"
"github.com/babylonlabs-io/babylon/testutil/datagen"
bbn "github.com/babylonlabs-io/babylon/types"
bbntypes "github.com/babylonlabs-io/babylon/types"
bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/btcsuite/btcd/chaincfg"
"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -104,7 +105,7 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo {
}

// GenStoredFinalityProvider generates a random finality-provider from the keyring and store it in DB
func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.FinalityProviderApp, passphrase, hdPath string) *store.StoredFinalityProvider {
func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.FinalityProviderApp, passphrase, hdPath string, eotsPk *bbntypes.BIP340PubKey) *store.StoredFinalityProvider {
// generate keyring
keyName := GenRandomHexStr(r, 4)
chainID := GenRandomHexStr(r, 4)
Expand All @@ -113,7 +114,7 @@ func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.Finality
_, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, keyName, keyring.BackendTest, passphrase, hdPath, "")
require.NoError(t, err)

res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, RandomDescription(r), ZeroCommissionRate())
res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, eotsPk, RandomDescription(r), ZeroCommissionRate())
require.NoError(t, err)

btcPk, err := bbn.NewBIP340PubKeyFromHex(res.FpInfo.BtcPkHex)
Expand Down

0 comments on commit d06cde5

Please sign in to comment.