Include best block height in /vspinfo response (#254)
This commit is contained in:
parent
0936e090a9
commit
ef472ffe5d
@ -243,7 +243,7 @@ func loadConfig() (*config, error) {
|
|||||||
flags.IniIncludeComments|flags.IniIncludeDefaults)
|
flags.IniIncludeComments|flags.IniIncludeDefaults)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating a default "+
|
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)
|
fmt.Printf("Config file with default values written to %s\n", defaultConfigFile)
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,8 @@ when a VSP is closed will result in an error.
|
|||||||
"vspdversion":"1.0.0-pre",
|
"vspdversion":"1.0.0-pre",
|
||||||
"voting":10,
|
"voting":10,
|
||||||
"voted":25,
|
"voted":25,
|
||||||
"revoked":3
|
"revoked":3,
|
||||||
|
"blockheight":623212
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
11
rpc/dcrd.go
11
rpc/dcrd.go
@ -224,6 +224,17 @@ func (c *DcrdRPC) CanTicketVote(rawTx *dcrdtypes.TxRawResult, ticketHash string,
|
|||||||
return live, nil
|
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
|
// ParseBlockConnectedNotification extracts the block header from a
|
||||||
// blockconnected JSON-RPC notification.
|
// blockconnected JSON-RPC notification.
|
||||||
func ParseBlockConnectedNotification(params json.RawMessage) (*wire.BlockHeader, error) {
|
func ParseBlockConnectedNotification(params json.RawMessage) (*wire.BlockHeader, error) {
|
||||||
|
|||||||
@ -5,16 +5,21 @@
|
|||||||
package webapi
|
package webapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/decred/dcrd/chaincfg/v3"
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/rpc"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"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 {
|
type vspStats struct {
|
||||||
PubKey string
|
PubKey string
|
||||||
Voting int64
|
Voting int64
|
||||||
@ -27,6 +32,7 @@ type vspStats struct {
|
|||||||
VspClosed bool
|
VspClosed bool
|
||||||
Debug bool
|
Debug bool
|
||||||
Designation string
|
Designation string
|
||||||
|
BlockHeight int64
|
||||||
}
|
}
|
||||||
|
|
||||||
var statsMtx sync.RWMutex
|
var statsMtx sync.RWMutex
|
||||||
@ -39,28 +45,54 @@ func getVSPStats() *vspStats {
|
|||||||
return stats
|
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()
|
voting, voted, revoked, err := db.CountTickets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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()
|
statsMtx.Lock()
|
||||||
defer statsMtx.Unlock()
|
defer statsMtx.Unlock()
|
||||||
|
|
||||||
stats = &vspStats{
|
stats.UpdateTime = dateTime(time.Now().Unix())
|
||||||
PubKey: base64.StdEncoding.EncodeToString(signPubKey),
|
stats.Voting = voting
|
||||||
Voting: voting,
|
stats.Voted = voted
|
||||||
Voted: voted,
|
stats.Revoked = revoked
|
||||||
Revoked: revoked,
|
stats.BlockHeight = blockHeight
|
||||||
VSPFee: cfg.VSPFee,
|
|
||||||
Network: cfg.NetParams.Name,
|
|
||||||
UpdateTime: dateTime(time.Now().Unix()),
|
|
||||||
SupportEmail: cfg.SupportEmail,
|
|
||||||
VspClosed: cfg.VspClosed,
|
|
||||||
Debug: cfg.Debug,
|
|
||||||
Designation: cfg.Designation,
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ type vspInfoResponse struct {
|
|||||||
Voting int64 `json:"voting"`
|
Voting int64 `json:"voting"`
|
||||||
Voted int64 `json:"voted"`
|
Voted int64 `json:"voted"`
|
||||||
Revoked int64 `json:"revoked"`
|
Revoked int64 `json:"revoked"`
|
||||||
|
BlockHeight int64 `json:"blockheight"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type feeAddressRequest struct {
|
type feeAddressRequest struct {
|
||||||
|
|||||||
@ -25,5 +25,6 @@ func vspInfo(c *gin.Context) {
|
|||||||
Voting: cachedStats.Voting,
|
Voting: cachedStats.Voting,
|
||||||
Voted: cachedStats.Voted,
|
Voted: cachedStats.Voted,
|
||||||
Revoked: cachedStats.Revoked,
|
Revoked: cachedStats.Revoked,
|
||||||
|
BlockHeight: cachedStats.BlockHeight,
|
||||||
}, c)
|
}, c)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,9 +69,10 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate cached VSP stats before starting webserver.
|
// Populate cached VSP stats before starting webserver.
|
||||||
err = updateVSPStats(vdb, config)
|
initVSPStats()
|
||||||
|
err = updateVSPStats(ctx, vdb, dcrd, config.NetParams)
|
||||||
if err != nil {
|
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
|
// 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
|
var refresh time.Duration
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
refresh = 1 * time.Second
|
refresh = 1 * time.Second
|
||||||
@ -156,7 +157,7 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
|
|||||||
shutdownWg.Done()
|
shutdownWg.Done()
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
err = updateVSPStats(db, cfg)
|
err = updateVSPStats(ctx, vdb, dcrd, config.NetParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to update cached VSP stats: %v", err)
|
log.Errorf("Failed to update cached VSP stats: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user