Skip to content

Commit

Permalink
Retrieve params based on inclusion block height
Browse files Browse the repository at this point in the history
  • Loading branch information
KonradStaniec committed Dec 5, 2024
1 parent 0eead4d commit 11f4d31
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 52 deletions.
177 changes: 141 additions & 36 deletions babylonclient/babyloncontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,19 @@ func (bc *BabylonController) Stop() error {
return bc.bbnClient.Stop()
}

func (bc *BabylonController) Params() (*StakingParams, error) {
// TODO: it would probably be good to have separate methods for those
var bccParams *btcctypes.Params
func (bc *BabylonController) btccheckpointParamsWithRetry() (*BTCCheckpointParams, error) {
var bccParams *BTCCheckpointParams
if err := retry.Do(func() error {
response, err := bc.bbnClient.BTCCheckpointParams()
if err != nil {
return err
}
bccParams = &response.Params

bccParams = &BTCCheckpointParams{
ConfirmationTimeBlocks: response.Params.BtcConfirmationDepth,
FinalizationTimeoutBlocks: response.Params.CheckpointFinalizationTimeout,
}

return nil
}, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) {
bc.logger.WithFields(logrus.Fields{
Expand All @@ -153,6 +157,20 @@ func (bc *BabylonController) Params() (*StakingParams, error) {
return nil, err
}

return bccParams, nil
}

func (bc *BabylonController) BTCCheckpointParams() (*BTCCheckpointParams, error) {
return bc.btccheckpointParamsWithRetry()
}

func (bc *BabylonController) Params() (*StakingParams, error) {
bccParams, err := bc.btccheckpointParamsWithRetry()

if err != nil {
return nil, err
}

var stakingTrackerParams *StakingTrackerResponse
if err := retry.Do(func() error {
trackerParams, err := bc.QueryStakingTracker()
Expand All @@ -172,8 +190,8 @@ func (bc *BabylonController) Params() (*StakingParams, error) {
}

return &StakingParams{
ConfirmationTimeBlocks: bccParams.BtcConfirmationDepth,
FinalizationTimeoutBlocks: bccParams.CheckpointFinalizationTimeout,
ConfirmationTimeBlocks: bccParams.ConfirmationTimeBlocks,
FinalizationTimeoutBlocks: bccParams.FinalizationTimeoutBlocks,
SlashingPkScript: stakingTrackerParams.SlashingPkScript,
CovenantPks: stakingTrackerParams.CovenantPks,
MinSlashingTxFeeSat: stakingTrackerParams.MinSlashingFee,
Expand All @@ -189,6 +207,71 @@ func (bc *BabylonController) Params() (*StakingParams, error) {
}, nil
}

func (bc *BabylonController) ParamsByBtcHeight(btcHeight uint32) (*StakingParams, error) {
bccParams, err := bc.btccheckpointParamsWithRetry()

if err != nil {
return nil, err
}

var stakingTrackerParams *StakingTrackerResponse
if err := retry.Do(func() error {
trackerParams, err := bc.QueryStakingTrackerByBtcHeight(btcHeight)
if err != nil {
return err
}
stakingTrackerParams = trackerParams
return nil
}, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) {
bc.logger.WithFields(logrus.Fields{
"attempt": n + 1,
"max_attempts": RtyAttNum,
"error": err,
}).Error("Failed to query babylon client for staking tracker params")
})); err != nil {
return nil, err
}

return &StakingParams{
ConfirmationTimeBlocks: bccParams.ConfirmationTimeBlocks,
FinalizationTimeoutBlocks: bccParams.FinalizationTimeoutBlocks,
SlashingPkScript: stakingTrackerParams.SlashingPkScript,
CovenantPks: stakingTrackerParams.CovenantPks,
MinSlashingTxFeeSat: stakingTrackerParams.MinSlashingFee,
SlashingRate: stakingTrackerParams.SlashingRate,
CovenantQuruomThreshold: stakingTrackerParams.CovenantQuruomThreshold,
UnbondingTime: stakingTrackerParams.UnbondingTime,
UnbondingFee: stakingTrackerParams.UnbondingFee,
MinStakingTime: stakingTrackerParams.MinStakingTime,
MaxStakingTime: stakingTrackerParams.MaxStakingTime,
MinStakingValue: stakingTrackerParams.MinStakingValue,
MaxStakingValue: stakingTrackerParams.MaxStakingValue,
AllowListExpirationHeight: stakingTrackerParams.AllowListExpirationHeight,
}, nil
}

func (bc *BabylonController) StakingTrackerByBtcHeight(btcHeight uint32) (*StakingTrackerResponse, error) {
var stakingTrackerParams *StakingTrackerResponse
if err := retry.Do(func() error {
trackerParams, err := bc.QueryStakingTrackerByBtcHeight(btcHeight)
if err != nil {
return err
}
stakingTrackerParams = trackerParams
return nil
}, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) {
bc.logger.WithFields(logrus.Fields{
"attempt": n + 1,
"max_attempts": RtyAttNum,
"error": err,
}).Error("Failed to query babylon client for staking tracker params")
})); err != nil {
return nil, err
}

return stakingTrackerParams, nil
}

func (bc *BabylonController) GetKeyAddress() sdk.AccAddress {
// get key address, retrieves address based on key name which is configured in
// cfg *stakercfg.BBNConfig. If this fails, it means we have misconfiguration problem
Expand Down Expand Up @@ -444,84 +527,106 @@ func getQueryContext(timeout time.Duration) (context.Context, context.CancelFunc
return ctx, cancel
}

func (bc *BabylonController) QueryStakingTracker() (*StakingTrackerResponse, error) {
ctx, cancel := getQueryContext(bc.cfg.Timeout)
defer cancel()

clientCtx := client.Context{Client: bc.bbnClient.RPCClient}
queryClient := btcstypes.NewQueryClient(clientCtx)

response, err := queryClient.Params(ctx, &btcstypes.QueryParamsRequest{})
if err != nil {
return nil, err
}

func parseParams(params *btcstypes.Params) (*StakingTrackerResponse, error) {
// check early that the covenant config makes sense, so that rest of the
// code can assume that:
// 1. covenant quorum is less or equal to number of covenant pks
// 2. covenant pks are not empty
if len(response.Params.CovenantPks) == 0 {
if len(params.CovenantPks) == 0 {
return nil, fmt.Errorf("empty list of covenant pks: %w", ErrInvalidValueReceivedFromBabylonNode)
}

if int(response.Params.CovenantQuorum) > len(response.Params.CovenantPks) {
if int(params.CovenantQuorum) > len(params.CovenantPks) {
return nil, fmt.Errorf("covenant quorum is bigger than number of covenant pks: %w", ErrInvalidValueReceivedFromBabylonNode)
}

var covenantPks []*btcec.PublicKey

for _, covenantPk := range response.Params.CovenantPks {
for _, covenantPk := range params.CovenantPks {
covenantBtcPk, err := covenantPk.ToBTCPK()
if err != nil {
return nil, err
}
covenantPks = append(covenantPks, covenantBtcPk)
}

unbondingTime := response.Params.UnbondingTimeBlocks
unbondingTime := params.UnbondingTimeBlocks
if unbondingTime > math.MaxUint16 {
return nil, fmt.Errorf("unbonding time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode)
}

minStakingTimeBlocksU32 := response.Params.MinStakingTimeBlocks
minStakingTimeBlocksU32 := params.MinStakingTimeBlocks
if minStakingTimeBlocksU32 > math.MaxUint16 {
return nil, fmt.Errorf("min staking time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode)
}

maxStakingTimeBlocksU32 := response.Params.MaxStakingTimeBlocks
maxStakingTimeBlocksU32 := params.MaxStakingTimeBlocks
if maxStakingTimeBlocksU32 > math.MaxUint16 {
return nil, fmt.Errorf("max staking time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode)
}

if response.Params.MinStakingValueSat < 0 {
if params.MinStakingValueSat < 0 {
return nil, fmt.Errorf("min staking value is negative: %w", ErrInvalidValueReceivedFromBabylonNode)
}

if response.Params.MaxStakingValueSat < 0 {
if params.MaxStakingValueSat < 0 {
return nil, fmt.Errorf("max staking value is negative: %w", ErrInvalidValueReceivedFromBabylonNode)
}

if response.Params.UnbondingFeeSat < 0 {
if params.UnbondingFeeSat < 0 {
return nil, fmt.Errorf("unbonding fee is negative: %w", ErrInvalidValueReceivedFromBabylonNode)
}

return &StakingTrackerResponse{
SlashingPkScript: response.Params.SlashingPkScript,
SlashingRate: response.Params.SlashingRate,
MinComissionRate: response.Params.MinCommissionRate,
SlashingPkScript: params.SlashingPkScript,
SlashingRate: params.SlashingRate,
MinComissionRate: params.MinCommissionRate,
CovenantPks: covenantPks,
MinSlashingFee: btcutil.Amount(response.Params.MinSlashingTxFeeSat),
CovenantQuruomThreshold: response.Params.CovenantQuorum,
MinSlashingFee: btcutil.Amount(params.MinSlashingTxFeeSat),
CovenantQuruomThreshold: params.CovenantQuorum,
UnbondingTime: uint16(unbondingTime),
UnbondingFee: btcutil.Amount(response.Params.UnbondingFeeSat),
UnbondingFee: btcutil.Amount(params.UnbondingFeeSat),
MinStakingTime: uint16(minStakingTimeBlocksU32),
MaxStakingTime: uint16(maxStakingTimeBlocksU32),
MinStakingValue: btcutil.Amount(response.Params.MinStakingValueSat),
MaxStakingValue: btcutil.Amount(response.Params.MaxStakingValueSat),
AllowListExpirationHeight: response.Params.AllowListExpirationHeight,
MinStakingValue: btcutil.Amount(params.MinStakingValueSat),
MaxStakingValue: btcutil.Amount(params.MaxStakingValueSat),
AllowListExpirationHeight: params.AllowListExpirationHeight,
}, nil
}

func (bc *BabylonController) QueryStakingTracker() (*StakingTrackerResponse, error) {
ctx, cancel := getQueryContext(bc.cfg.Timeout)
defer cancel()

clientCtx := client.Context{Client: bc.bbnClient.RPCClient}
queryClient := btcstypes.NewQueryClient(clientCtx)

response, err := queryClient.Params(ctx, &btcstypes.QueryParamsRequest{})
if err != nil {
return nil, err
}

return parseParams(&response.Params)
}

func (bc *BabylonController) QueryStakingTrackerByBtcHeight(btcHeight uint32) (*StakingTrackerResponse, error) {
ctx, cancel := getQueryContext(bc.cfg.Timeout)
defer cancel()

clientCtx := client.Context{Client: bc.bbnClient.RPCClient}
queryClient := btcstypes.NewQueryClient(clientCtx)

response, err := queryClient.ParamsByBTCHeight(ctx, &btcstypes.QueryParamsByBTCHeightRequest{
BtcHeight: btcHeight,
})

if err != nil {
return nil, err
}

return parseParams(&response.Params)
}

func (bc *BabylonController) QueryFinalityProviders(
limit uint64,
offset uint64) (*FinalityProvidersClientResponse, error) {
Expand Down
25 changes: 25 additions & 0 deletions babylonclient/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import (
pv "github.com/cosmos/relayer/v2/relayer/provider"
)

type BTCCheckpointParams struct {
// K-deep
ConfirmationTimeBlocks uint32
// W-deep
FinalizationTimeoutBlocks uint32
}

type StakingParams struct {
// K-deep
ConfirmationTimeBlocks uint32
Expand Down Expand Up @@ -68,7 +75,10 @@ type SingleKeyKeyring interface {

type BabylonClient interface {
SingleKeyKeyring
BTCCheckpointParams() (*BTCCheckpointParams, error)
Params() (*StakingParams, error)
ParamsByBtcHeight(btcHeight uint32) (*StakingParams, error)
StakingTrackerByBtcHeight(btcHeight uint32) (*StakingTrackerResponse, error)
Delegate(dg *DelegationData) (*pv.RelayerTxResponse, error)
QueryFinalityProviders(limit uint64, offset uint64) (*FinalityProvidersClientResponse, error)
QueryFinalityProvider(btcPubKey *btcec.PublicKey) (*FinalityProviderClientResponse, error)
Expand All @@ -91,6 +101,21 @@ func (m *MockBabylonClient) Params() (*StakingParams, error) {
return m.ClientParams, nil
}

func (m *MockBabylonClient) ParamsByBtcHeight(btcHeight uint32) (*StakingParams, error) {

Check failure on line 104 in babylonclient/interface.go

View workflow job for this annotation

GitHub Actions / lint_test / lint

unused-parameter: parameter 'btcHeight' seems to be unused, consider removing or renaming it as _ (revive)
return m.ClientParams, nil
}

func (m *MockBabylonClient) BTCCheckpointParams() (*BTCCheckpointParams, error) {
return &BTCCheckpointParams{
ConfirmationTimeBlocks: m.ClientParams.ConfirmationTimeBlocks,
FinalizationTimeoutBlocks: m.ClientParams.FinalizationTimeoutBlocks,
}, nil
}

func (m *MockBabylonClient) StakingTrackerByBtcHeight(btcHeight uint32) (*StakingTrackerResponse, error) {

Check failure on line 115 in babylonclient/interface.go

View workflow job for this annotation

GitHub Actions / lint_test / lint

unused-parameter: parameter 'btcHeight' seems to be unused, consider removing or renaming it as _ (revive)
return &StakingTrackerResponse{}, nil
}

func (m *MockBabylonClient) Sign(msg []byte) ([]byte, error) {
sig, err := m.babylonKey.Sign(msg)

Expand Down
9 changes: 5 additions & 4 deletions staker/babylontypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import (
// retrieving data from babylon chain, sending data to babylon chain, queuing data to be send etc.

type inclusionInfo struct {
txIndex uint32
inclusionBlock *wire.MsgBlock
inclusionProof []byte
txIndex uint32
inclusionBlock *wire.MsgBlock
inclusionBlockBtcHeight uint32
inclusionProof []byte
}

type sendDelegationRequest struct {
Expand All @@ -39,7 +40,7 @@ func (app *App) buildOwnedDelegation(
stakerAddress btcutil.Address,
storedTx *stakerdb.StoredTransaction,
) (*cl.DelegationData, error) {
externalData, err := app.retrieveExternalDelegationData(stakerAddress)
externalData, err := app.retrieveExternalDelegationData(stakerAddress, req.inclusionInfo)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 11f4d31

Please sign in to comment.