Skip to content

Commit

Permalink
Feature: Support minimum-signed threshold (#80)
Browse files Browse the repository at this point in the history
* Support threshold, Check minimum signed

* Update threshold annotations
  • Loading branch information
BOSEES authored Apr 9, 2024
1 parent bc10d54 commit ec26068
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 75 deletions.
5 changes: 3 additions & 2 deletions td2/dashboard/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package dash
import (
"embed"
"encoding/json"
"github.com/gorilla/websocket"
"github.com/textileio/go-threads/broadcast"
"io/fs"
"log"
"net/http"
"regexp"
"sort"
"sync"
"time"

"github.com/gorilla/websocket"
"github.com/textileio/go-threads/broadcast"
)

var (
Expand Down
29 changes: 15 additions & 14 deletions td2/dashboard/types.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package dash

type ChainStatus struct {
MsgType string `json:"msgType"`
Name string `json:"name"`
ChainId string `json:"chain_id"`
Moniker string `json:"moniker"`
Bonded bool `json:"bonded"`
Jailed bool `json:"jailed"`
Tombstoned bool `json:"tombstoned"`
Missed int64 `json:"missed"`
Window int64 `json:"window"`
Nodes int `json:"nodes"`
HealthyNodes int `json:"healthy_nodes"`
ActiveAlerts int `json:"active_alerts"`
Height int64 `json:"height"`
LastError string `json:"last_error"`
MsgType string `json:"msgType"`
Name string `json:"name"`
ChainId string `json:"chain_id"`
Moniker string `json:"moniker"`
Bonded bool `json:"bonded"`
Jailed bool `json:"jailed"`
Tombstoned bool `json:"tombstoned"`
Missed int64 `json:"missed"`
Window int64 `json:"window"`
MinSignedPerWindow float64 `json:"min_signed_per_window"`
Nodes int `json:"nodes"`
HealthyNodes int `json:"healthy_nodes"`
ActiveAlerts int `json:"active_alerts"`
Height int64 `json:"height"`
LastError string `json:"last_error"`

Blocks []int `json:"blocks"`
}
Expand Down
32 changes: 17 additions & 15 deletions td2/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func (cc *ChainConfig) newRpc() error {
for _, endpoint := range cc.Nodes {
anyWorking = anyWorking || !endpoint.down
}

// grab the first working endpoint
tryUrl := func(u string) (msg string, down, syncing bool) {
_, err := url.Parse(u)
Expand Down Expand Up @@ -106,21 +107,22 @@ func (cc *ChainConfig) newRpc() error {
cc.lastError = "no usable RPC endpoints available for " + cc.ChainId
if td.EnableDash {
td.updateChan <- &dash.ChainStatus{
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
Nodes: len(cc.Nodes),
HealthyNodes: 0,
ActiveAlerts: 1,
Height: 0,
LastError: cc.lastError,
Blocks: cc.blocksResults,
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
MinSignedPerWindow: cc.minSignedPerWindow,
Nodes: len(cc.Nodes),
HealthyNodes: 0,
ActiveAlerts: 1,
Height: 0,
LastError: cc.lastError,
Blocks: cc.blocksResults,
}
}
return errors.New("no usable endpoints available for " + cc.ChainId)
Expand Down
6 changes: 6 additions & 0 deletions td2/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ func Run(configFile, stateFile, chainConfigDirectory string, password *string) e
time.Sleep(5 * time.Second)
continue
}

e = cc.GetMinSignedPerWindow()
if e != nil {
l("🛑", cc.ChainId, e)
}

e = cc.GetValInfo(true)
if e != nil {
l("🛑", cc.ChainId, e)
Expand Down
1 change: 1 addition & 0 deletions td2/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<th>Moniker</th>
<th style="text-align: center">Bonded</th>
<th class="uk-text-center">Uptime</th>
<th class="uk-text-center">Threshold</th>
<th class="uk-text-center">RPC Nodes</th>
</tr>
</thead>
Expand Down
6 changes: 5 additions & 1 deletion td2/static/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ function updateTable(status) {
window += `${(100 - (status.Status[i].missed / status.Status[i].window) * 100).toFixed(2)}%</div>`
}
window += `<div class="uk-width-1-2">${_.escape(status.Status[i].missed)} / ${_.escape(status.Status[i].window)}</div>`

let threshold = ""
threshold += `<span class="uk-width-1-2">${100 * status.Status[i].min_signed_per_window}%</span>`;

let nodes = `${_.escape(status.Status[i].healthy_nodes)} / ${_.escape(status.Status[i].nodes)}`
if (status.Status[i].healthy_nodes < status.Status[i].nodes) {
Expand All @@ -131,7 +134,8 @@ function updateTable(status) {
}
r.insertCell(4).innerHTML = `<div style="text-align: center">${bonded}</div>`
r.insertCell(5).innerHTML = `<div uk-grid>${window}</div>`
r.insertCell(6).innerHTML = `<div class="uk-text-center">${nodes}</div>`
r.insertCell(6).innerHTML = `<div class="uk-text-center">${threshold}</div>`
r.insertCell(7).innerHTML = `<div class="uk-text-center">${nodes}</div>`
}
}

Expand Down
52 changes: 27 additions & 25 deletions td2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,19 @@ type savedState struct {
// ChainConfig represents a validator to be monitored on a chain, it is somewhat of a misnomer since multiple
// validators can be monitored on a single chain.
type ChainConfig struct {
name string
wsclient *TmConn // custom websocket client to work around wss:// bugs in tendermint
client *rpchttp.HTTP // legit tendermint client
noNodes bool // tracks if all nodes are down
valInfo *ValInfo // recent validator state, only refreshed every few minutes
lastValInfo *ValInfo // use for detecting newly-jailed/tombstone
blocksResults []int
lastError string
lastBlockTime time.Time
lastBlockAlarm bool
lastBlockNum int64
activeAlerts int
name string
wsclient *TmConn // custom websocket client to work around wss:// bugs in tendermint
client *rpchttp.HTTP // legit tendermint client
noNodes bool // tracks if all nodes are down
valInfo *ValInfo // recent validator state, only refreshed every few minutes
lastValInfo *ValInfo // use for detecting newly-jailed/tombstone
minSignedPerWindow float64 // instantly see the validator risk level
blocksResults []int
lastError string
lastBlockTime time.Time
lastBlockAlarm bool
lastBlockNum int64
activeAlerts int

statTotalSigns float64
statTotalProps float64
Expand Down Expand Up @@ -326,19 +327,20 @@ func validateConfig(c *Config) (fatal bool, problems []string) {
}
if td.EnableDash {
td.updateChan <- &dash.ChainStatus{
MsgType: "status",
Name: v.name,
ChainId: v.ChainId,
Moniker: v.valInfo.Moniker,
Bonded: v.valInfo.Bonded,
Jailed: v.valInfo.Jailed,
Tombstoned: v.valInfo.Tombstoned,
Missed: v.valInfo.Missed,
Window: v.valInfo.Window,
Nodes: len(v.Nodes),
HealthyNodes: 0,
ActiveAlerts: 0,
Blocks: v.blocksResults,
MsgType: "status",
Name: v.name,
ChainId: v.ChainId,
Moniker: v.valInfo.Moniker,
Bonded: v.valInfo.Bonded,
Jailed: v.valInfo.Jailed,
Tombstoned: v.valInfo.Tombstoned,
Missed: v.valInfo.Missed,
MinSignedPerWindow: v.minSignedPerWindow,
Window: v.valInfo.Window,
Nodes: len(v.Nodes),
HealthyNodes: 0,
ActiveAlerts: 0,
Blocks: v.blocksResults,
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions td2/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,37 @@ type ValInfo struct {
Valcons string `json:"valcons"`
}

// GetMinSignedPerWindow The check the minimum signed threshold of the validator.
func (cc *ChainConfig) GetMinSignedPerWindow() (err error) {
if cc.client == nil {
return errors.New("nil rpc client")
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

qParams := &slashing.QueryParamsRequest{}
b, err := qParams.Marshal()
if err != nil {
return
}
resp, err := cc.client.ABCIQuery(ctx, "/cosmos.slashing.v1beta1.Query/Params", b)
if err != nil {
return
}
if resp.Response.Value == nil {
err = errors.New("🛑 could not query slashing params, got empty response")
return
}
params := &slashing.QueryParamsResponse{}
err = params.Unmarshal(resp.Response.Value)
if err != nil {
return
}

cc.minSignedPerWindow = params.Params.MinSignedPerWindow.MustFloat64()
return
}

// GetValInfo the first bool is used to determine if extra information about the validator should be printed.
func (cc *ChainConfig) GetValInfo(first bool) (err error) {
if cc.client == nil {
Expand Down
40 changes: 22 additions & 18 deletions td2/ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import (
"encoding/json"
"errors"
"fmt"
dash "github.com/blockpane/tenderduty/v2/td2/dashboard"
"github.com/gorilla/websocket"
pbtypes "github.com/tendermint/tendermint/proto/tendermint/types"
"log"
"net/url"
"strconv"
"strings"
"time"

dash "github.com/blockpane/tenderduty/v2/td2/dashboard"
"github.com/gorilla/websocket"
pbtypes "github.com/tendermint/tendermint/proto/tendermint/types"
)

const (
Expand Down Expand Up @@ -129,6 +130,7 @@ func (cc *ChainConfig) WsRun() {
cc.lastError = time.Now().UTC().String() + " " + info
l(warn)
}

switch signState {
case Statusmissed:
cc.statTotalMiss += 1
Expand Down Expand Up @@ -164,24 +166,26 @@ func (cc *ChainConfig) WsRun() {
case cc.valInfo.Jailed:
info += "- validator is jailed\n"
}

cc.activeAlerts = alarms.getCount(cc.name)
if td.EnableDash {
td.updateChan <- &dash.ChainStatus{
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
Nodes: len(cc.Nodes),
HealthyNodes: healthyNodes,
ActiveAlerts: cc.activeAlerts,
Height: update.Height,
LastError: info,
Blocks: cc.blocksResults,
MsgType: "status",
Name: cc.name,
ChainId: cc.ChainId,
Moniker: cc.valInfo.Moniker,
Bonded: cc.valInfo.Bonded,
Jailed: cc.valInfo.Jailed,
Tombstoned: cc.valInfo.Tombstoned,
Missed: cc.valInfo.Missed,
Window: cc.valInfo.Window,
MinSignedPerWindow: cc.minSignedPerWindow,
Nodes: len(cc.Nodes),
HealthyNodes: healthyNodes,
ActiveAlerts: cc.activeAlerts,
Height: update.Height,
LastError: info,
Blocks: cc.blocksResults,
}
}

Expand Down

0 comments on commit ec26068

Please sign in to comment.