Skip to content

Commit

Permalink
Include best block height in /vspinfo response
Browse files Browse the repository at this point in the history
  • Loading branch information
jholdstock committed May 14, 2021
1 parent 0936e09 commit 715a545
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 15 deletions.
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func loadConfig() (*config, error) {
flags.IniIncludeComments|flags.IniIncludeDefaults)
if err != nil {
return nil, fmt.Errorf("error creating a default "+
"config file: %v", err)
"config file: %w", err)
}
fmt.Printf("Config file with default values written to %s\n", defaultConfigFile)

Expand Down
3 changes: 2 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ when a VSP is closed will result in an error.
"vspdversion":"1.0.0-pre",
"voting":10,
"voted":25,
"revoked":3
"revoked":3,
"blockheight":623212
}
```

Expand Down
11 changes: 11 additions & 0 deletions rpc/dcrd.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ func (c *DcrdRPC) CanTicketVote(rawTx *dcrdtypes.TxRawResult, ticketHash string,
return live, nil
}

// GetBestBlockHeight uses getblockcount RPC to query the height of the best
// block known by the dcrd instance.
func (c *DcrdRPC) GetBestBlockHeight() (int64, error) {
var height int64
err := c.Call(c.ctx, "getblockcount", &height)
if err != nil {
return 0, err
}
return height, nil
}

// ParseBlockConnectedNotification extracts the block header from a
// blockconnected JSON-RPC notification.
func ParseBlockConnectedNotification(params json.RawMessage) (*wire.BlockHeader, error) {
Expand Down
50 changes: 41 additions & 9 deletions webapi/homepage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@
package webapi

import (
"context"
"encoding/base64"
"net/http"
"sync"
"time"

"github.com/decred/dcrd/chaincfg/v3"
"github.com/decred/vspd/database"
"github.com/decred/vspd/rpc"

"github.com/gin-gonic/gin"
)

// vspStats is used to cache values which are commonly used by the API, so
// repeated web requests don't repeatedly trigger DB or RPC calls.
type vspStats struct {
PubKey string
Voting int64
Expand All @@ -27,6 +32,7 @@ type vspStats struct {
VspClosed bool
Debug bool
Designation string
BlockHeight int64
}

var statsMtx sync.RWMutex
Expand All @@ -39,28 +45,54 @@ func getVSPStats() *vspStats {
return stats
}

func updateVSPStats(db *database.VspDatabase, cfg Config) error {
voting, voted, revoked, err := db.CountTickets()
if err != nil {
return err
}
// initVSPStats creates the struct which holds the cached VSP stats, and
// initializes it with static values.
func initVSPStats() {

statsMtx.Lock()
defer statsMtx.Unlock()

stats = &vspStats{
PubKey: base64.StdEncoding.EncodeToString(signPubKey),
Voting: voting,
Voted: voted,
Revoked: revoked,
VSPFee: cfg.VSPFee,
Network: cfg.NetParams.Name,
UpdateTime: dateTime(time.Now().Unix()),
SupportEmail: cfg.SupportEmail,
VspClosed: cfg.VspClosed,
Debug: cfg.Debug,
Designation: cfg.Designation,
}
}

// updateVSPStats updates the dynamic values in the cached VSP stats (ticket
// counts and best block height).
func updateVSPStats(ctx context.Context, db *database.VspDatabase,
dcrd rpc.DcrdConnect, netParams *chaincfg.Params) error {

// Update counts of voting, voted and revoked tickets.
voting, voted, revoked, err := db.CountTickets()
if err != nil {
return err
}

// Update best block height.
dcrdClient, err := dcrd.Client(ctx, netParams)
if err != nil {
return err
}

blockHeight, err := dcrdClient.GetBestBlockHeight()
if err != nil {
return err
}

statsMtx.Lock()
defer statsMtx.Unlock()

stats.UpdateTime = dateTime(time.Now().Unix())
stats.Voting = voting
stats.Voted = voted
stats.Revoked = revoked
stats.BlockHeight = blockHeight

return nil
}
Expand Down
1 change: 1 addition & 0 deletions webapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type vspInfoResponse struct {
Voting int64 `json:"voting"`
Voted int64 `json:"voted"`
Revoked int64 `json:"revoked"`
BlockHeight int64 `json:"blockheight"`
}

type feeAddressRequest struct {
Expand Down
1 change: 1 addition & 0 deletions webapi/vspinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ func vspInfo(c *gin.Context) {
Voting: cachedStats.Voting,
Voted: cachedStats.Voted,
Revoked: cachedStats.Revoked,
BlockHeight: cachedStats.BlockHeight,
}, c)
}
9 changes: 5 additions & 4 deletions webapi/webapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
}

// Populate cached VSP stats before starting webserver.
err = updateVSPStats(vdb, config)
initVSPStats()
err = updateVSPStats(ctx, vdb, dcrd, config.NetParams)
if err != nil {
return fmt.Errorf("could not initialize VSP stats cache: %w", err)
log.Errorf("Could not initialize VSP stats cache: %v", err)
}

// Get the last used address index and the feeXpub from the database, and
Expand Down Expand Up @@ -139,7 +140,7 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
}
}()

// Use a ticker to update template data.
// Use a ticker to update cached VSP stats.
var refresh time.Duration
if cfg.Debug {
refresh = 1 * time.Second
Expand All @@ -156,7 +157,7 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
shutdownWg.Done()
return
case <-ticker.C:
err = updateVSPStats(db, cfg)
err = updateVSPStats(ctx, vdb, dcrd, config.NetParams)
if err != nil {
log.Errorf("Failed to update cached VSP stats: %v", err)
}
Expand Down

0 comments on commit 715a545

Please sign in to comment.