From 822566e82c91e75ccafed4a07618a8cddb995c31 Mon Sep 17 00:00:00 2001 From: Gurjot Date: Thu, 21 Nov 2024 14:46:08 +0530 Subject: [PATCH] add eoi time --- internal/clients/bbnclient/bbnclient.go | 16 +++++++ internal/clients/bbnclient/interface.go | 1 + internal/db/model/delegation.go | 62 ++++++++++++++----------- internal/services/bootstrap.go | 2 +- internal/services/delegation.go | 15 +++++- internal/services/events.go | 8 +++- tests/mocks/mock_bbn_client.go | 30 ++++++++++++ tests/mocks/mock_db_client.go | 18 +++++++ 8 files changed, 119 insertions(+), 33 deletions(-) diff --git a/internal/clients/bbnclient/bbnclient.go b/internal/clients/bbnclient/bbnclient.go index 4416cc6..d089485 100644 --- a/internal/clients/bbnclient/bbnclient.go +++ b/internal/clients/bbnclient/bbnclient.go @@ -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...) } diff --git a/internal/clients/bbnclient/interface.go b/internal/clients/bbnclient/interface.go index f189621..e660789 100644 --- a/internal/clients/bbnclient/interface.go +++ b/internal/clients/bbnclient/interface.go @@ -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 diff --git a/internal/db/model/delegation.go b/internal/db/model/delegation.go index 980dc03..fb12365 100644 --- a/internal/db/model/delegation.go +++ b/internal/db/model/delegation.go @@ -17,24 +17,28 @@ type CovenantSignature struct { } 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"` + BTCDelegationCreatedBbnHeight int64 `bson:"btc_delegation_created_bbn_height"` + BTCDelegationCreatedBbnTimestamp int64 `bson:"btc_delegation_created_bbn_timestamp"` // epoch time in seconds } func FromEventBTCDelegationCreated( event *bbntypes.EventBTCDelegationCreated, + bbnBlockHeight, + bbnBlockTime int64, ) (*BTCDelegationDetails, *types.Error) { stakingOutputIdx, err := strconv.ParseUint(event.StakingOutputIndex, 10, 32) if err != nil { @@ -84,20 +88,22 @@ func FromEventBTCDelegationCreated( stakingValue := btcutil.Amount(stakingTx.TxOut[stakingOutputIdx].Value) return &BTCDelegationDetails{ - StakingTxHashHex: stakingTx.TxHash().String(), - StakingTxHex: event.StakingTxHex, - StakingTime: uint32(stakingTime), - StakingAmount: uint64(stakingValue), - StakingOutputIdx: uint32(stakingOutputIdx), - StakerBtcPkHex: event.StakerBtcPkHex, - FinalityProviderBtcPksHex: event.FinalityProviderBtcPksHex, - ParamsVersion: uint32(paramsVersion), - UnbondingTime: uint32(unbondingTime), - UnbondingTx: event.UnbondingTx, - State: types.StatePending, // initial state will always be PENDING - 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{}, + StakingTxHashHex: stakingTx.TxHash().String(), + StakingTxHex: event.StakingTxHex, + StakingTime: uint32(stakingTime), + StakingAmount: uint64(stakingValue), + StakingOutputIdx: uint32(stakingOutputIdx), + StakerBtcPkHex: event.StakerBtcPkHex, + FinalityProviderBtcPksHex: event.FinalityProviderBtcPksHex, + ParamsVersion: uint32(paramsVersion), + UnbondingTime: uint32(unbondingTime), + UnbondingTx: event.UnbondingTx, + State: types.StatePending, // initial state will always be PENDING + 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{}, + BTCDelegationCreatedBbnHeight: bbnBlockHeight, + BTCDelegationCreatedBbnTimestamp: bbnBlockTime, }, nil } diff --git a/internal/services/bootstrap.go b/internal/services/bootstrap.go index 2d306ab..7cc235d 100644 --- a/internal/services/bootstrap.go +++ b/internal/services/bootstrap.go @@ -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 } } diff --git a/internal/services/delegation.go b/internal/services/delegation.go index 0a9b38a..136854d 100644 --- a/internal/services/delegation.go +++ b/internal/services/delegation.go @@ -25,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, @@ -38,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 } diff --git a/internal/services/events.go b/internal/services/events.go index 7ce3e1c..97240bf 100644 --- a/internal/services/events.go +++ b/internal/services/events.go @@ -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 @@ -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) diff --git a/tests/mocks/mock_bbn_client.go b/tests/mocks/mock_bbn_client.go index efbe075..1e50651 100644 --- a/tests/mocks/mock_bbn_client.go +++ b/tests/mocks/mock_bbn_client.go @@ -47,6 +47,36 @@ func (_m *BbnInterface) GetAllStakingParams(ctx context.Context) (map[uint32]*bb return r0, r1 } +// GetBlock provides a mock function with given fields: ctx, blockHeight +func (_m *BbnInterface) GetBlock(ctx context.Context, blockHeight *int64) (*coretypes.ResultBlock, error) { + ret := _m.Called(ctx, blockHeight) + + if len(ret) == 0 { + panic("no return value specified for GetBlock") + } + + var r0 *coretypes.ResultBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *int64) (*coretypes.ResultBlock, error)); ok { + return rf(ctx, blockHeight) + } + if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlock); ok { + r0 = rf(ctx, blockHeight) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.ResultBlock) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok { + r1 = rf(ctx, blockHeight) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetBlockResults provides a mock function with given fields: ctx, blockHeight func (_m *BbnInterface) GetBlockResults(ctx context.Context, blockHeight *int64) (*coretypes.ResultBlockResults, error) { ret := _m.Called(ctx, blockHeight) diff --git a/tests/mocks/mock_db_client.go b/tests/mocks/mock_db_client.go index 53a0d40..4c2ece4 100644 --- a/tests/mocks/mock_db_client.go +++ b/tests/mocks/mock_db_client.go @@ -233,6 +233,24 @@ func (_m *DbInterface) Ping(ctx context.Context) error { return r0 } +// SaveBTCDelegationUnbondingCovenantSignature provides a mock function with given fields: ctx, stakingTxHash, covenantBtcPkHex, signatureHex +func (_m *DbInterface) SaveBTCDelegationUnbondingCovenantSignature(ctx context.Context, stakingTxHash string, covenantBtcPkHex string, signatureHex string) error { + ret := _m.Called(ctx, stakingTxHash, covenantBtcPkHex, signatureHex) + + if len(ret) == 0 { + panic("no return value specified for SaveBTCDelegationUnbondingCovenantSignature") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok { + r0 = rf(ctx, stakingTxHash, covenantBtcPkHex, signatureHex) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SaveCheckpointParams provides a mock function with given fields: ctx, params func (_m *DbInterface) SaveCheckpointParams(ctx context.Context, params *bbnclient.CheckpointParams) error { ret := _m.Called(ctx, params)