diff --git a/db/errors.go b/db/errors.go new file mode 100644 index 0000000..4010d49 --- /dev/null +++ b/db/errors.go @@ -0,0 +1,5 @@ +package db + +import "errors" + +var ErrNotFound = errors.New("not found") diff --git a/monitor/contract_monitor.go b/monitor/contract_monitor.go index 392a3fe..da2c6ca 100644 --- a/monitor/contract_monitor.go +++ b/monitor/contract_monitor.go @@ -2,7 +2,6 @@ package monitor import ( "context" - "database/sql" "errors" "fmt" "math/big" @@ -11,6 +10,7 @@ import ( "time" "tokenbridge-monitor/config" "tokenbridge-monitor/contract" + "tokenbridge-monitor/db" "tokenbridge-monitor/entity" "tokenbridge-monitor/ethclient" "tokenbridge-monitor/logging" @@ -66,7 +66,7 @@ func NewContractMonitor(ctx context.Context, logger logging.Logger, repo *reposi } logsCursor, err := repo.LogsCursors.GetByChainIDAndAddress(ctx, cfg.Chain.ChainID, cfg.Address) if err != nil { - if errors.Is(err, sql.ErrNoRows) { + if errors.Is(err, db.ErrNotFound) { logger.WithFields(logrus.Fields{ "chain_id": cfg.Chain.ChainID, "address": cfg.Address, @@ -400,24 +400,24 @@ func (m *ContractMonitor) StartLogsProcessor(ctx context.Context) { } func (m *ContractMonitor) tryToGetBlockTimestamp(ctx context.Context, blockNumber uint) error { - ts, err := m.repo.BlockTimestamps.GetByBlockNumber(ctx, m.cfg.Chain.ChainID, blockNumber) + _, err := m.repo.BlockTimestamps.GetByBlockNumber(ctx, m.cfg.Chain.ChainID, blockNumber) if err != nil { + if errors.Is(err, db.ErrNotFound) { + m.logger.WithField("block_number", blockNumber).Debug("fetching block timestamp") + header, err := m.client.HeaderByNumber(ctx, blockNumber) + if err != nil { + return fmt.Errorf("can't request block header: %w", err) + } + return m.repo.BlockTimestamps.Ensure(ctx, &entity.BlockTimestamp{ + ChainID: m.cfg.Chain.ChainID, + BlockNumber: blockNumber, + Timestamp: time.Unix(int64(header.Time), 0), + }) + } return fmt.Errorf("can't get block timestamp from db: %w", err) } - if ts != nil { - m.logger.WithField("block_number", blockNumber).Debug("timestamp already exists, skipping") - return nil - } - m.logger.WithField("block_number", blockNumber).Debug("fetching block timestamp") - header, err := m.client.HeaderByNumber(ctx, blockNumber) - if err != nil { - return fmt.Errorf("can't request block header: %w", err) - } - return m.repo.BlockTimestamps.Ensure(ctx, &entity.BlockTimestamp{ - ChainID: m.cfg.Chain.ChainID, - BlockNumber: blockNumber, - Timestamp: time.Unix(int64(header.Time), 0), - }) + m.logger.WithField("block_number", blockNumber).Debug("timestamp already exists, skipping") + return nil } func (m *ContractMonitor) tryToProcessLogsBatch(ctx context.Context, batch *LogsBatch) error { diff --git a/monitor/handlers.go b/monitor/handlers.go index cdb178b..84f2c63 100644 --- a/monitor/handlers.go +++ b/monitor/handlers.go @@ -2,10 +2,12 @@ package monitor import ( "context" + "errors" "fmt" "math/big" "tokenbridge-monitor/config" "tokenbridge-monitor/contract/abi" + "tokenbridge-monitor/db" "tokenbridge-monitor/entity" "tokenbridge-monitor/ethclient" "tokenbridge-monitor/repository" @@ -413,11 +415,11 @@ func (p *BridgeEventHandler) HandleValidatorRemoved(ctx context.Context, log *en validator := data["validator"].(common.Address) val, err := p.repo.BridgeValidators.FindActiveValidator(ctx, p.bridgeID, log.ChainID, validator) if err != nil { + if errors.Is(err, db.ErrNotFound) { + return nil + } return err } - if val == nil { - return nil - } val.RemovedLogID = &log.ID return p.repo.BridgeValidators.Ensure(ctx, val) } diff --git a/presenter/presenter.go b/presenter/presenter.go index 6c3797e..801d22b 100644 --- a/presenter/presenter.go +++ b/presenter/presenter.go @@ -3,11 +3,13 @@ package presenter import ( "context" "encoding/json" + "errors" "fmt" "net/http" "regexp" "strconv" "tokenbridge-monitor/config" + "tokenbridge-monitor/db" "tokenbridge-monitor/entity" "tokenbridge-monitor/logging" "tokenbridge-monitor/repository" @@ -138,15 +140,16 @@ func (p *Presenter) SearchValidators(r *http.Request) (interface{}, error) { } seenValidators[val.Address] = true - confirmation, err := p.repo.SignedMessages.FindLatest(ctx, bridgeID, res.Home.ChainID, val.Address) - if err != nil { - p.logger.WithError(err).Error("failed to find latest validator confirmation") - return nil, err - } valInfo := &ValidatorInfo{ Signer: val.Address, } - if confirmation != nil { + confirmation, err := p.repo.SignedMessages.FindLatest(ctx, bridgeID, res.Home.ChainID, val.Address) + if err != nil { + if !errors.Is(err, db.ErrNotFound) { + p.logger.WithError(err).Error("failed to find latest validator confirmation") + return nil, err + } + } else { valInfo.LastConfirmation, err = p.getTxInfo(ctx, confirmation.LogID) if err != nil { p.logger.WithError(err).Error("failed to get tx info") @@ -253,7 +256,7 @@ func (p *Presenter) searchInLogs(ctx context.Context, logs []*entity.Log) []*Sea p.searchSignedInformationRequest, p.searchExecutedInformationRequest, } { - if res, err := task(ctx, log); err != nil { + if res, err := task(ctx, log); err != nil && !errors.Is(err, db.ErrNotFound) { p.logger.WithError(err).Error("failed to execute search task") } else if res != nil { for _, e := range res.RelatedEvents { @@ -278,33 +281,30 @@ func (p *Presenter) searchSentMessage(ctx context.Context, log *entity.Log) (*Se if err != nil { return nil, err } - if sent == nil { - return nil, nil - } var messageInfo interface{} var events []*EventInfo msg, err := p.repo.Messages.FindByMsgHash(ctx, sent.BridgeID, sent.MsgHash) - if err != nil { - return nil, err - } - if msg == nil { + if err != nil && errors.Is(err, db.ErrNotFound) { ercToNativeMsg, err2 := p.repo.ErcToNativeMessages.FindByMsgHash(ctx, sent.BridgeID, sent.MsgHash) if err2 != nil { return nil, err2 } - if ercToNativeMsg == nil { - return nil, nil - } messageInfo = ercToNativeMessageToInfo(ercToNativeMsg) events, err = p.buildMessageEvents(ctx, ercToNativeMsg.BridgeID, ercToNativeMsg.MsgHash, ercToNativeMsg.MsgHash) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, err } else { messageInfo = messageToInfo(msg) events, err = p.buildMessageEvents(ctx, msg.BridgeID, msg.MsgHash, msg.MessageID) + if err != nil { + return nil, err + } } - if err != nil { - return nil, err - } + return &SearchResult{ Message: messageInfo, RelatedEvents: events, @@ -316,32 +316,28 @@ func (p *Presenter) searchSignedMessage(ctx context.Context, log *entity.Log) (* if err != nil { return nil, err } - if sig == nil { - return nil, nil - } var messageInfo interface{} var events []*EventInfo msg, err := p.repo.Messages.FindByMsgHash(ctx, sig.BridgeID, sig.MsgHash) - if err != nil { - return nil, err - } - if msg == nil { + if err != nil && errors.Is(err, db.ErrNotFound) { ercToNativeMsg, err2 := p.repo.ErcToNativeMessages.FindByMsgHash(ctx, sig.BridgeID, sig.MsgHash) if err2 != nil { return nil, err2 } - if ercToNativeMsg == nil { - return nil, nil - } messageInfo = ercToNativeMessageToInfo(ercToNativeMsg) events, err = p.buildMessageEvents(ctx, ercToNativeMsg.BridgeID, ercToNativeMsg.MsgHash, ercToNativeMsg.MsgHash) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, err } else { messageInfo = messageToInfo(msg) events, err = p.buildMessageEvents(ctx, msg.BridgeID, msg.MsgHash, msg.MessageID) - } - if err != nil { - return nil, err + if err != nil { + return nil, err + } } return &SearchResult{ Message: messageInfo, @@ -354,32 +350,28 @@ func (p *Presenter) searchExecutedMessage(ctx context.Context, log *entity.Log) if err != nil { return nil, err } - if executed == nil { - return nil, nil - } var messageInfo interface{} var events []*EventInfo msg, err := p.repo.Messages.FindByMessageID(ctx, executed.BridgeID, executed.MessageID) - if err != nil { - return nil, err - } - if msg == nil { + if err != nil && errors.Is(err, db.ErrNotFound) { ercToNativeMsg, err2 := p.repo.ErcToNativeMessages.FindByMsgHash(ctx, executed.BridgeID, executed.MessageID) if err2 != nil { return nil, err2 } - if ercToNativeMsg == nil { - return nil, nil - } messageInfo = ercToNativeMessageToInfo(ercToNativeMsg) events, err = p.buildMessageEvents(ctx, ercToNativeMsg.BridgeID, ercToNativeMsg.MsgHash, ercToNativeMsg.MsgHash) + if err != nil { + return nil, err + } + } else if err != nil { + return nil, err } else { messageInfo = messageToInfo(msg) events, err = p.buildMessageEvents(ctx, msg.BridgeID, msg.MsgHash, msg.MessageID) - } - if err != nil { - return nil, err + if err != nil { + return nil, err + } } return &SearchResult{ Message: messageInfo, @@ -392,12 +384,9 @@ func (p *Presenter) searchSentInformationRequest(ctx context.Context, log *entit if err != nil { return nil, err } - if sent == nil { - return nil, nil - } req, err := p.repo.InformationRequests.FindByMessageID(ctx, sent.BridgeID, sent.MessageID) - if err != nil || req == nil { + if err != nil { return nil, err } events, err := p.buildInformationRequestEvents(ctx, req) @@ -415,12 +404,9 @@ func (p *Presenter) searchSignedInformationRequest(ctx context.Context, log *ent if err != nil { return nil, err } - if signed == nil { - return nil, nil - } req, err := p.repo.InformationRequests.FindByMessageID(ctx, signed.BridgeID, signed.MessageID) - if err != nil || req == nil { + if err != nil { return nil, err } events, err := p.buildInformationRequestEvents(ctx, req) @@ -438,12 +424,9 @@ func (p *Presenter) searchExecutedInformationRequest(ctx context.Context, log *e if err != nil { return nil, err } - if executed == nil { - return nil, nil - } req, err := p.repo.InformationRequests.FindByMessageID(ctx, executed.BridgeID, executed.MessageID) - if err != nil || req == nil { + if err != nil { return nil, err } events, err := p.buildInformationRequestEvents(ctx, req) @@ -458,7 +441,7 @@ func (p *Presenter) searchExecutedInformationRequest(ctx context.Context, log *e func (p *Presenter) buildMessageEvents(ctx context.Context, bridgeID string, msgHash, messageID common.Hash) ([]*EventInfo, error) { sent, err := p.repo.SentMessages.FindByMsgHash(ctx, bridgeID, msgHash) - if err != nil { + if err != nil && !errors.Is(err, db.ErrNotFound) { return nil, err } signed, err := p.repo.SignedMessages.FindByMsgHash(ctx, bridgeID, msgHash) @@ -466,11 +449,11 @@ func (p *Presenter) buildMessageEvents(ctx context.Context, bridgeID string, msg return nil, err } collected, err := p.repo.CollectedMessages.FindByMsgHash(ctx, bridgeID, msgHash) - if err != nil { + if err != nil && !errors.Is(err, db.ErrNotFound) { return nil, err } executed, err := p.repo.ExecutedMessages.FindByMessageID(ctx, bridgeID, messageID) - if err != nil { + if err != nil && !errors.Is(err, db.ErrNotFound) { return nil, err } @@ -507,7 +490,7 @@ func (p *Presenter) buildMessageEvents(ctx context.Context, bridgeID string, msg func (p *Presenter) buildInformationRequestEvents(ctx context.Context, req *entity.InformationRequest) ([]*EventInfo, error) { sent, err := p.repo.SentInformationRequests.FindByMessageID(ctx, req.BridgeID, req.MessageID) - if err != nil { + if err != nil && !errors.Is(err, db.ErrNotFound) { return nil, err } signed, err := p.repo.SignedInformationRequests.FindByMessageID(ctx, req.BridgeID, req.MessageID) @@ -515,7 +498,7 @@ func (p *Presenter) buildInformationRequestEvents(ctx context.Context, req *enti return nil, err } executed, err := p.repo.ExecutedInformationRequests.FindByMessageID(ctx, req.BridgeID, req.MessageID) - if err != nil { + if err != nil && !errors.Is(err, db.ErrNotFound) { return nil, err } diff --git a/repository/postgres/block_timestamps.go b/repository/postgres/block_timestamps.go index 5377c81..123b79f 100644 --- a/repository/postgres/block_timestamps.go +++ b/repository/postgres/block_timestamps.go @@ -50,7 +50,7 @@ func (r *blockTimestampsRepo) GetByBlockNumber(ctx context.Context, chainID stri err = r.db.GetContext(ctx, ts, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get block timestamp: %w", err) } diff --git a/repository/postgres/bridge_validators.go b/repository/postgres/bridge_validators.go index 3a057b0..4d78e70 100644 --- a/repository/postgres/bridge_validators.go +++ b/repository/postgres/bridge_validators.go @@ -53,7 +53,7 @@ func (r *bridgeValidatorsRepo) FindActiveValidator(ctx context.Context, bridgeID err = r.db.GetContext(ctx, val, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get bridge validator: %w", err) } diff --git a/repository/postgres/collected_messages.go b/repository/postgres/collected_messages.go index 700b775..da231e5 100644 --- a/repository/postgres/collected_messages.go +++ b/repository/postgres/collected_messages.go @@ -48,7 +48,7 @@ func (r *collectedMessagesRepo) FindByMsgHash(ctx context.Context, bridgeID stri err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get collected message: %w", err) } diff --git a/repository/postgres/erc_to_native_messages.go b/repository/postgres/erc_to_native_messages.go index 804a313..7ead178 100644 --- a/repository/postgres/erc_to_native_messages.go +++ b/repository/postgres/erc_to_native_messages.go @@ -48,7 +48,7 @@ func (r *ercToNativeMessagesRepo) FindByMsgHash(ctx context.Context, bridgeID st err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get message: %w", err) } diff --git a/repository/postgres/executed_information_requests.go b/repository/postgres/executed_information_requests.go index a7f4837..c700de9 100644 --- a/repository/postgres/executed_information_requests.go +++ b/repository/postgres/executed_information_requests.go @@ -48,7 +48,7 @@ func (r *executedInformationRequestsRepo) FindByLogID(ctx context.Context, logID err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get executed information requesst: %w", err) } @@ -68,7 +68,7 @@ func (r *executedInformationRequestsRepo) FindByMessageID(ctx context.Context, b err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get executed information request: %w", err) } diff --git a/repository/postgres/executed_messages.go b/repository/postgres/executed_messages.go index fd51311..19e91a4 100644 --- a/repository/postgres/executed_messages.go +++ b/repository/postgres/executed_messages.go @@ -48,7 +48,7 @@ func (r *executedMessagesRepo) FindByLogID(ctx context.Context, logID uint) (*en err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get executed message: %w", err) } @@ -68,7 +68,7 @@ func (r *executedMessagesRepo) FindByMessageID(ctx context.Context, bridgeID str err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get executed message: %w", err) } diff --git a/repository/postgres/information_requests.go b/repository/postgres/information_requests.go index a541817..277d417 100644 --- a/repository/postgres/information_requests.go +++ b/repository/postgres/information_requests.go @@ -48,7 +48,7 @@ func (r *informationRequestsRepo) FindByMessageID(ctx context.Context, bridgeID err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get information request: %w", err) } diff --git a/repository/postgres/logs_cursors.go b/repository/postgres/logs_cursors.go index 40c2171..67bdb3b 100644 --- a/repository/postgres/logs_cursors.go +++ b/repository/postgres/logs_cursors.go @@ -2,6 +2,8 @@ package postgres import ( "context" + "database/sql" + "errors" "fmt" "tokenbridge-monitor/db" "tokenbridge-monitor/entity" @@ -45,6 +47,9 @@ func (r *logsCursorsRepo) GetByChainIDAndAddress(ctx context.Context, chainID st log := new(entity.LogsCursor) err = r.db.GetContext(ctx, log, q, args...) if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, db.ErrNotFound + } return nil, fmt.Errorf("can't get logs cursor by chain_id and address: %w", err) } return log, nil diff --git a/repository/postgres/messages.go b/repository/postgres/messages.go index b4cc52a..fb582a2 100644 --- a/repository/postgres/messages.go +++ b/repository/postgres/messages.go @@ -48,7 +48,7 @@ func (r *messagesRepo) FindByMsgHash(ctx context.Context, bridgeID string, msgHa err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get message: %w", err) } @@ -68,7 +68,7 @@ func (r *messagesRepo) FindByMessageID(ctx context.Context, bridgeID string, mes err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get message: %w", err) } diff --git a/repository/postgres/sent_information_requests.go b/repository/postgres/sent_information_requests.go index e9076c5..e49372f 100644 --- a/repository/postgres/sent_information_requests.go +++ b/repository/postgres/sent_information_requests.go @@ -48,7 +48,7 @@ func (r *sentInformationRequestsRepo) FindByLogID(ctx context.Context, logID uin err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get sent information requesst: %w", err) } @@ -68,7 +68,7 @@ func (r *sentInformationRequestsRepo) FindByMessageID(ctx context.Context, bridg err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get sent information request: %w", err) } diff --git a/repository/postgres/sent_messages.go b/repository/postgres/sent_messages.go index 288cfd8..9254520 100644 --- a/repository/postgres/sent_messages.go +++ b/repository/postgres/sent_messages.go @@ -48,7 +48,7 @@ func (r *sentMessagesRepo) FindByLogID(ctx context.Context, logID uint) (*entity err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get sent message: %w", err) } @@ -68,7 +68,7 @@ func (r *sentMessagesRepo) FindByMsgHash(ctx context.Context, bridgeID string, m err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get sent message: %w", err) } diff --git a/repository/postgres/signed_information_requests.go b/repository/postgres/signed_information_requests.go index 6790856..7e05cec 100644 --- a/repository/postgres/signed_information_requests.go +++ b/repository/postgres/signed_information_requests.go @@ -51,7 +51,7 @@ func (r *signedInformationRequestsRepo) FindByLogID(ctx context.Context, logID u err = r.db.GetContext(ctx, req, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get signed information requesst: %w", err) } @@ -71,9 +71,6 @@ func (r *signedInformationRequestsRepo) FindByMessageID(ctx context.Context, bri reqs := make([]*entity.SignedInformationRequest, 0, 4) err = r.db.SelectContext(ctx, &reqs, q, args...) if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, nil - } return nil, fmt.Errorf("can't get signed information requests: %w", err) } return reqs, nil diff --git a/repository/postgres/signed_messages.go b/repository/postgres/signed_messages.go index 40dc2bc..373740c 100644 --- a/repository/postgres/signed_messages.go +++ b/repository/postgres/signed_messages.go @@ -48,7 +48,7 @@ func (r *signedMessagesRepo) FindByLogID(ctx context.Context, logID uint) (*enti err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get signed messages: %w", err) } @@ -68,9 +68,6 @@ func (r *signedMessagesRepo) FindByMsgHash(ctx context.Context, bridgeID string, msgs := make([]*entity.SignedMessage, 0, 4) err = r.db.SelectContext(ctx, &msgs, q, args...) if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, nil - } return nil, fmt.Errorf("can't get signed messages: %w", err) } return msgs, nil @@ -92,7 +89,7 @@ func (r *signedMessagesRepo) FindLatest(ctx context.Context, bridgeID, chainID s err = r.db.GetContext(ctx, msg, q, args...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, nil + return nil, db.ErrNotFound } return nil, fmt.Errorf("can't get latest signed message: %w", err) }