diff --git a/api/server.go b/api/server.go index d2a47042..699c5046 100644 --- a/api/server.go +++ b/api/server.go @@ -200,10 +200,15 @@ func (s *server) consensusTipHeightHandler(jc jape.Context) { if jc.DecodeParam("height", &height) != nil { return } + tip, err := s.e.BestTip(height) - if jc.Check("failed to get block", err) != nil { + if errors.Is(err, explorer.ErrNoTip) { + jc.Error(explorer.ErrNoTip, http.StatusNotFound) + return + } else if jc.Check("failed to get tip", err) != nil { return } + jc.Encode(tip) } diff --git a/explorer/explorer.go b/explorer/explorer.go index 292eaca5..52bc70ac 100644 --- a/explorer/explorer.go +++ b/explorer/explorer.go @@ -16,9 +16,8 @@ import ( ) var ( - // ErrNoTip is returned when Tip() is unable to find any blocks in the - // database and thus there is no tip. It does not mean there was an - // error in the underlying database. + // ErrNoTip is returned when we are unable to find the tip in the + // database or there is no tips at all. ErrNoTip = errors.New("no tip found") // ErrContractNotFound is returned when ContractRevisions is unable to find diff --git a/persist/sqlite/blocks.go b/persist/sqlite/blocks.go index 15ece33b..889a60e9 100644 --- a/persist/sqlite/blocks.go +++ b/persist/sqlite/blocks.go @@ -1,6 +1,8 @@ package sqlite import ( + "database/sql" + "errors" "fmt" "go.sia.tech/core/types" @@ -58,7 +60,9 @@ func (s *Store) Block(id types.BlockID) (result explorer.Block, err error) { func (s *Store) BestTip(height uint64) (result types.ChainIndex, err error) { err = s.transaction(func(tx *txn) error { err = tx.QueryRow(`SELECT id, height FROM blocks WHERE height=?`, height).Scan(decode(&result.ID), decode(&result.Height)) - if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return explorer.ErrNoTip + } else if err != nil { return err }