Add share cards
This commit is contained in:
51 files changed
+1193
-239
No files matched your search
@@ -37,7 +37,7 @@ type BestSharePow struct {
|
||||
|
||||
// StratumServer describes one entry in ckpool's serverurl[] array. ckpool
|
||||
// tags every client with the index of the bind it arrived on, but the index
|
||||
// alone doesn't say what that bind *is* — that depends on how the deployment
|
||||
// alone doesn't say what that bind *is*, that depends on how the deployment
|
||||
// rendered ckpool.conf. Declaring the array lets the dashboard report the
|
||||
// actual transport (plaintext, TLS with which certificate) instead of
|
||||
// hardcoding a bind order.
|
||||
@@ -77,7 +77,7 @@ type Snapshot struct {
|
||||
// Full PoW reproduction data (raw block header, coinbase, merkle
|
||||
// branches) for the best share seen since ckpool patch 0008 was
|
||||
// deployed. May describe a lower-diff share than BestDiff when the
|
||||
// all-time best predates the patch — the UI compares hashes and
|
||||
// all-time best predates the patch, the UI compares hashes and
|
||||
// shows a disclaimer in that case.
|
||||
BestSharePow *BestSharePow `json:"best_share_pow,omitempty"`
|
||||
// Last best-diff value acknowledged by the user via the UI.
|
||||
@@ -129,7 +129,7 @@ type Snapshot struct {
|
||||
// Counts of share-submit attempts ("Possible/Submitting block solve"
|
||||
// log lines) and confirmed solves ("Solved and confirmed block").
|
||||
// A growing gap means bitcoind is rejecting our submissions or
|
||||
// dropping the RPC — surface it in the UI as an alert.
|
||||
// dropping the RPC, surface it in the UI as an alert.
|
||||
BlockSubmitAttempts int64 `json:"block_submit_attempts"`
|
||||
BlockSubmitsConfirmed int64 `json:"block_submits_confirmed"`
|
||||
|
||||
@@ -186,7 +186,7 @@ const (
|
||||
|
||||
// kvCumulativeWork is versioned: "cumulative_shares" (v1) accidentally
|
||||
// summed pool.shares (raw per-share count), which is meaningless for
|
||||
// hashrate math. "cumulative_work" (v2) sums pool.accepted — the
|
||||
// hashrate math. "cumulative_work" (v2) sums pool.accepted, the
|
||||
// diff-1-normalized work, so cumulative_work * 2^32 is real hashes.
|
||||
// The old key is orphaned in the kv table on upgrade; harmless.
|
||||
kvCumulativeWork = "cumulative_work"
|
||||
@@ -264,14 +264,14 @@ type Aggregator struct {
|
||||
|
||||
// Cumulative pool work in diff-1-normalized shares, surviving
|
||||
// ckpool restarts. Maintained by re-reading pool.Shares each
|
||||
// refresh and integrating only the positive delta — a decrease
|
||||
// refresh and integrating only the positive delta, a decrease
|
||||
// means ckpool restarted and its counter reset to 0, so we reset
|
||||
// our delta baseline without losing the accumulated total.
|
||||
//
|
||||
// hasPoolSharesBaseline guards against double-counting on api
|
||||
// restart: cumulativeShares is loaded from disk, and the first
|
||||
// post-load observation of pool.Shares only establishes the
|
||||
// baseline — the current ckpool counter was already accounted for
|
||||
// baseline, the current ckpool counter was already accounted for
|
||||
// before we crashed.
|
||||
cumulativeShares float64
|
||||
lastPoolShares float64
|
||||
@@ -395,7 +395,7 @@ type Aggregator struct {
|
||||
loadOnce sync.Once
|
||||
// statsLoaded reports that the alltime share statistics have been
|
||||
// read back from the store. Persisting before that would write the
|
||||
// zero-valued in-memory counters over the accumulated history — the
|
||||
// zero-valued in-memory counters over the accumulated history, the
|
||||
// first share event triggers a save, so this is the difference
|
||||
// between a restart and permanent data loss.
|
||||
statsLoaded bool
|
||||
@@ -419,7 +419,7 @@ func New(ck *ckpool.Client, rpc *bitcoind.RPC, interval time.Duration, log *slog
|
||||
// Run calls it, but callers should invoke it directly before starting
|
||||
// any ingest goroutine: those goroutines mutate the same counters and
|
||||
// persist them on their first event, so a restore still in flight would
|
||||
// be overwritten by — and then read back as — near-empty state. Safe to
|
||||
// be overwritten by, and then read back as, near-empty state. Safe to
|
||||
// call repeatedly; only the first call does the work.
|
||||
func (a *Aggregator) LoadPersisted() {
|
||||
a.loadOnce.Do(func() {
|
||||
@@ -429,7 +429,7 @@ func (a *Aggregator) LoadPersisted() {
|
||||
}
|
||||
|
||||
// Ready returns a channel that's closed once the aggregator has
|
||||
// completed its first refresh — used by main to delay HTTP serving
|
||||
// completed its first refresh, used by main to delay HTTP serving
|
||||
// until /api/snapshot reflects real state instead of zeros.
|
||||
func (a *Aggregator) Ready() <-chan struct{} {
|
||||
return a.ready
|
||||
@@ -580,7 +580,7 @@ func (a *Aggregator) refresh(ctx context.Context) {
|
||||
// Measuring to wall-clock time instead adds the partial, in-progress
|
||||
// interval to the elapsed span without adding an interval to divide
|
||||
// it by. That skews the estimate toward "difficulty will fall" by
|
||||
// however long it has been since the last block — which averages a
|
||||
// however long it has been since the last block, which averages a
|
||||
// full 600s and, a handful of blocks into an epoch, is most of the
|
||||
// sample. It washes out only once enough blocks accumulate to dwarf
|
||||
// it, which is why the estimate used to settle down around mid-epoch.
|
||||
@@ -651,12 +651,12 @@ func (a *Aggregator) refresh(ctx context.Context) {
|
||||
|
||||
// --- cumulative work tracking ---
|
||||
// Integrate only positive deltas on pool.Accepted, which is ckpool's
|
||||
// accounted_diff_shares — the sum of each accepted share's
|
||||
// accounted_diff_shares, the sum of each accepted share's
|
||||
// difficulty, in diff-1-normalized units. pool.Shares is the raw
|
||||
// per-share count and is useless for hashrate math. A decrease
|
||||
// means ckpool restarted (or its state reset); we reset the
|
||||
// baseline without touching the accumulated total. The first
|
||||
// observation after load only establishes the baseline — the
|
||||
// observation after load only establishes the baseline, the
|
||||
// current counter was already integrated before we shut down.
|
||||
if next.Pool != nil {
|
||||
cur := float64(next.Pool.Accepted)
|
||||
@@ -687,7 +687,7 @@ func (a *Aggregator) refresh(ctx context.Context) {
|
||||
if curAcc >= a.lastPoolAcceptedRaw {
|
||||
a.allTimeAccepted += curAcc - a.lastPoolAcceptedRaw
|
||||
} else {
|
||||
// ckpool restarted — reset session share stats.
|
||||
// ckpool restarted, reset session share stats.
|
||||
a.resetSessionShareStats()
|
||||
}
|
||||
if curRej >= a.lastPoolRejectedRaw {
|
||||
@@ -866,8 +866,8 @@ func estimateRetargetPercent(inEpoch int64, elapsed float64) float64 {
|
||||
return 0
|
||||
}
|
||||
// Consensus budgets retargetInterval*600 seconds for an epoch but
|
||||
// spans them across retargetInterval-1 inter-block intervals — the
|
||||
// long-standing off-by-one — so on-target pace is fractionally above
|
||||
// spans them across retargetInterval-1 inter-block intervals, the
|
||||
// long-standing off-by-one, so on-target pace is fractionally above
|
||||
// 600s per block, and a perfectly on-time epoch retargets by ~0%
|
||||
// rather than a hair negative.
|
||||
targetPerInterval := float64(retargetInterval*targetBlockSeconds) / float64(retargetInterval-1)
|
||||
@@ -1000,7 +1000,7 @@ func (a *Aggregator) IngestShareEvents(ctx context.Context, events <-chan logmon
|
||||
// stats that were lost or truncated: the log is the only other record of
|
||||
// per-share difficulty, and ckpool keeps its full history there.
|
||||
//
|
||||
// Deliberately never automatic — the scan walks every line of a log that
|
||||
// Deliberately never automatic, the scan walks every line of a log that
|
||||
// can hold millions, and it was a long startup scan that made the race
|
||||
// this repairs so easy to hit in the first place.
|
||||
func (a *Aggregator) RebuildShareStatsFromLog() (adopted bool, scanned int64, err error) {
|
||||
@@ -1085,7 +1085,7 @@ func (a *Aggregator) persistShareStats() {
|
||||
|
||||
// loadPersistedState restores cumulative work and hashrate history from
|
||||
// the store so they survive process restarts. Safe to call with a nil
|
||||
// Store — becomes a no-op.
|
||||
// Store, becomes a no-op.
|
||||
func (a *Aggregator) loadPersistedState() {
|
||||
if a.Store == nil {
|
||||
return
|
||||
@@ -1173,7 +1173,7 @@ func (a *Aggregator) loadPersistedState() {
|
||||
if logDiff, h := logmon.FindBestShareHash(a.LogFilePath); h != "" {
|
||||
a.mu.Lock()
|
||||
a.bestShareHash = h
|
||||
// The log may contain the true best — adopt it if higher.
|
||||
// The log may contain the true best, adopt it if higher.
|
||||
if logDiff > a.bestDiff {
|
||||
a.bestDiff = logDiff
|
||||
if a.Store != nil {
|
||||
|
||||
Reference in new issue
Block a user