Include best block height in /vspinfo response (#254)

This commit is contained in:
Jamie Holdstock 2021-05-15 03:09:03 +01:00 committed by GitHub
parent 0936e090a9
commit ef472ffe5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 20 deletions

View File

@ -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)

View File

@ -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
}
```

View File

@ -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) {

View File

@ -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
@ -27,6 +32,7 @@ type vspStats struct {
VspClosed bool
Debug bool
Designation string
BlockHeight int64
}
var statsMtx sync.RWMutex
@ -39,28 +45,54 @@ func getVSPStats() *vspStats {
return stats
}
func updateVSPStats(db *database.VspDatabase, cfg Config) error {
// 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),
VSPFee: cfg.VSPFee,
Network: cfg.NetParams.Name,
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 = &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,
}
stats.UpdateTime = dateTime(time.Now().Unix())
stats.Voting = voting
stats.Voted = voted
stats.Revoked = revoked
stats.BlockHeight = blockHeight
return nil
}

View File

@ -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 {

View File

@ -25,5 +25,6 @@ func vspInfo(c *gin.Context) {
Voting: cachedStats.Voting,
Voted: cachedStats.Voted,
Revoked: cachedStats.Revoked,
BlockHeight: cachedStats.BlockHeight,
}, c)
}

View File

@ -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
@ -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
@ -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)
}