Skip to content

Commit

Permalink
chore: add inception time in db (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
gusin13 authored Nov 21, 2024
1 parent de4f514 commit 21a4158
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 70 deletions.
16 changes: 16 additions & 0 deletions internal/clients/bbnclient/bbnclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,22 @@ func (c *BBNClient) GetBlockResults(
return blockResults, nil
}

func (c *BBNClient) GetBlock(ctx context.Context, blockHeight *int64) (*ctypes.ResultBlock, error) {
callForBlock := func() (*ctypes.ResultBlock, error) {
resp, err := c.queryClient.RPCClient.Block(ctx, blockHeight)
if err != nil {
return nil, err
}
return resp, nil
}

block, err := clientCallWithRetry(callForBlock, c.cfg)
if err != nil {
return nil, err
}
return block, nil
}

func (c *BBNClient) Subscribe(subscriber, query string, outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) {
return c.queryClient.RPCClient.Subscribe(context.Background(), subscriber, query, outCapacity...)
}
Expand Down
1 change: 1 addition & 0 deletions internal/clients/bbnclient/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type BbnInterface interface {
GetCheckpointParams(ctx context.Context) (*CheckpointParams, error)
GetAllStakingParams(ctx context.Context) (map[uint32]*StakingParams, error)
GetLatestBlockNumber(ctx context.Context) (int64, error)
GetBlock(ctx context.Context, blockHeight *int64) (*ctypes.ResultBlock, error)
GetBlockResults(ctx context.Context, blockHeight *int64) (*ctypes.ResultBlockResults, error)
Subscribe(subscriber, query string, outCapacity ...int) (out <-chan ctypes.ResultEvent, err error)
UnsubscribeAll(subscriber string) error
Expand Down
2 changes: 1 addition & 1 deletion internal/db/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (db *Database) SaveBTCDelegationUnbondingCovenantSignature(
filter := bson.M{"_id": stakingTxHash}
update := bson.M{
"$push": bson.M{
"covenant_signatures": bson.M{
"covenant_unbonding_signatures": bson.M{
"covenant_btc_pk_hex": covenantBtcPkHex,
"signature_hex": signatureHex,
},
Expand Down
40 changes: 26 additions & 14 deletions internal/db/model/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,33 @@ type CovenantSignature struct {
SignatureHex string `bson:"signature_hex"`
}

type BTCDelegationCreatedBbnBlock struct {
Height int64 `bson:"height"`
Timestamp int64 `bson:"timestamp"` // epoch time in seconds
}

type BTCDelegationDetails struct {
StakingTxHashHex string `bson:"_id"` // Primary key
StakingTxHex string `bson:"staking_tx_hex"`
StakingTime uint32 `bson:"staking_time"`
StakingAmount uint64 `bson:"staking_amount"`
StakingOutputIdx uint32 `bson:"staking_output_idx"`
StakerBtcPkHex string `bson:"staker_btc_pk_hex"`
FinalityProviderBtcPksHex []string `bson:"finality_provider_btc_pks_hex"`
StartHeight uint32 `bson:"start_height"`
EndHeight uint32 `bson:"end_height"`
State types.DelegationState `bson:"state"`
ParamsVersion uint32 `bson:"params_version"`
UnbondingTime uint32 `bson:"unbonding_time"`
UnbondingTx string `bson:"unbonding_tx"`
CovenantUnbondingSignatures []CovenantSignature `bson:"covenant_unbonding_signatures"`
StakingTxHashHex string `bson:"_id"` // Primary key
StakingTxHex string `bson:"staking_tx_hex"`
StakingTime uint32 `bson:"staking_time"`
StakingAmount uint64 `bson:"staking_amount"`
StakingOutputIdx uint32 `bson:"staking_output_idx"`
StakerBtcPkHex string `bson:"staker_btc_pk_hex"`
FinalityProviderBtcPksHex []string `bson:"finality_provider_btc_pks_hex"`
StartHeight uint32 `bson:"start_height"`
EndHeight uint32 `bson:"end_height"`
State types.DelegationState `bson:"state"`
ParamsVersion uint32 `bson:"params_version"`
UnbondingTime uint32 `bson:"unbonding_time"`
UnbondingTx string `bson:"unbonding_tx"`
CovenantUnbondingSignatures []CovenantSignature `bson:"covenant_unbonding_signatures"`
BTCDelegationCreatedBlock BTCDelegationCreatedBbnBlock `bson:"btc_delegation_created_bbn_block"`
}

func FromEventBTCDelegationCreated(
event *bbntypes.EventBTCDelegationCreated,
bbnBlockHeight,
bbnBlockTime int64,
) (*BTCDelegationDetails, *types.Error) {
stakingOutputIdx, err := strconv.ParseUint(event.StakingOutputIndex, 10, 32)
if err != nil {
Expand Down Expand Up @@ -98,6 +106,10 @@ func FromEventBTCDelegationCreated(
StartHeight: uint32(0), // it should be set when the inclusion proof is received
EndHeight: uint32(0), // it should be set when the inclusion proof is received
CovenantUnbondingSignatures: []CovenantSignature{},
BTCDelegationCreatedBlock: BTCDelegationCreatedBbnBlock{
Height: bbnBlockHeight,
Timestamp: bbnBlockTime,
},
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/services/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (s *Service) processBlocksSequentially(ctx context.Context) *types.Error {
}

for _, event := range events {
if err := s.processEvent(ctx, event); err != nil {
if err := s.processEvent(ctx, event, int64(i)); err != nil {
return err
}
}
Expand Down
54 changes: 49 additions & 5 deletions internal/services/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"strconv"

"github.com/babylonlabs-io/babylon-staking-indexer/internal/db"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/db/model"
Expand All @@ -24,7 +25,7 @@ const (
)

func (s *Service) processNewBTCDelegationEvent(
ctx context.Context, event abcitypes.Event,
ctx context.Context, event abcitypes.Event, bbnBlockHeight int64,
) *types.Error {
newDelegation, err := parseEvent[*bbntypes.EventBTCDelegationCreated](
EventBTCDelegationCreated, event,
Expand All @@ -37,7 +38,18 @@ func (s *Service) processNewBTCDelegationEvent(
return err
}

delegationDoc, err := model.FromEventBTCDelegationCreated(newDelegation)
// Get block info to get timestamp
bbnBlock, bbnErr := s.bbn.GetBlock(ctx, &bbnBlockHeight)
if bbnErr != nil {
return types.NewError(
http.StatusInternalServerError,
types.ClientRequestError,
fmt.Errorf("failed to get block: %w", bbnErr),
)
}
bbnBlockTime := bbnBlock.Block.Time.Unix()

delegationDoc, err := model.FromEventBTCDelegationCreated(newDelegation, bbnBlockHeight, bbnBlockTime)
if err != nil {
return err
}
Expand Down Expand Up @@ -239,9 +251,41 @@ func (s *Service) processBTCDelegationUnbondedEarlyEvent(
return err
}

// Handle unbonding process
if err := s.handleUnbondingProcess(ctx, unbondedEarlyEvent, delegation); err != nil {
return err
unbondingStartHeight, parseErr := strconv.ParseUint(unbondedEarlyEvent.StartHeight, 10, 32)
if parseErr != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to parse start height: %w", parseErr),
)
}

// Save timelock expire
unbondingExpireHeight := uint32(unbondingStartHeight) + delegation.UnbondingTime
if err := s.db.SaveNewTimeLockExpire(
ctx,
delegation.StakingTxHashHex,
unbondingExpireHeight,
types.EarlyUnbondingTxType.String(),
); err != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to save timelock expire: %w", err),
)
}

// Update delegation state
if err := s.db.UpdateBTCDelegationState(
ctx,
unbondedEarlyEvent.StakingTxHash,
types.StateUnbonding,
); err != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to update BTC delegation state: %w", err),
)
}

// Register unbonding spend notification
Expand Down
47 changes: 0 additions & 47 deletions internal/services/delegation_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,62 +5,15 @@ import (
"encoding/hex"
"fmt"
"net/http"
"strconv"

"github.com/babylonlabs-io/babylon-staking-indexer/internal/db/model"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/types"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/utils"
bbn "github.com/babylonlabs-io/babylon/types"
bbntypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
)

func (s *Service) handleUnbondingProcess(
ctx context.Context,
event *bbntypes.EventBTCDelgationUnbondedEarly,
delegation *model.BTCDelegationDetails,
) *types.Error {
unbondingStartHeight, parseErr := strconv.ParseUint(event.StartHeight, 10, 32)
if parseErr != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to parse start height: %w", parseErr),
)
}

// Save timelock expire
unbondingExpireHeight := uint32(unbondingStartHeight) + delegation.UnbondingTime
if err := s.db.SaveNewTimeLockExpire(
ctx,
delegation.StakingTxHashHex,
unbondingExpireHeight,
types.EarlyUnbondingTxType.String(),
); err != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to save timelock expire: %w", err),
)
}

// Update delegation state
if err := s.db.UpdateBTCDelegationState(
ctx,
event.StakingTxHash,
types.StateUnbonding,
); err != nil {
return types.NewError(
http.StatusInternalServerError,
types.InternalServiceError,
fmt.Errorf("failed to update BTC delegation state: %w", err),
)
}

return nil
}

func (s *Service) registerUnbondingSpendNotification(
ctx context.Context,
delegation *model.BTCDelegationDetails,
Expand Down
8 changes: 6 additions & 2 deletions internal/services/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ func NewBbnEvent(category EventCategory, event abcitypes.Event) BbnEvent {
}

// Entry point for processing events
func (s *Service) processEvent(ctx context.Context, event BbnEvent) *types.Error {
func (s *Service) processEvent(
ctx context.Context,
event BbnEvent,
blockHeight int64,
) *types.Error {
// Note: We no longer need to check for the event category here. We can directly
// process the event based on its type.
bbnEvent := event.Event
Expand All @@ -60,7 +64,7 @@ func (s *Service) processEvent(ctx context.Context, event BbnEvent) *types.Error
s.processFinalityProviderStateChangeEvent(ctx, bbnEvent)
case EventBTCDelegationCreated:
log.Debug().Msg("Processing new BTC delegation event")
err = s.processNewBTCDelegationEvent(ctx, bbnEvent)
err = s.processNewBTCDelegationEvent(ctx, bbnEvent, blockHeight)
case EventCovenantQuorumReached:
log.Debug().Msg("Processing covenant quorum reached event")
err = s.processCovenantQuorumReachedEvent(ctx, bbnEvent)
Expand Down
30 changes: 30 additions & 0 deletions tests/mocks/mock_bbn_client.go

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

18 changes: 18 additions & 0 deletions tests/mocks/mock_db_client.go

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

0 comments on commit 21a4158

Please sign in to comment.