Add share cards

This commit is contained in:
satoshi committed 2026-09-04 00:54:26 +03:00
1 parent ec42ce9b54
commit 4669bf10c0
51 files changed
+1193 -239

No files matched your search

+18 -18
View File
@@ -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 {