Revert block-broadcast fallback path

Removes the entire fallback submitter mechanism: ckpool patch 0004,
the blocksubmit package, the wiring in main.go, the config fields,
the aggregator's fallback counters and snapshot fields, the healthz
fallback fields, and the TS type fields plus the HealthBanners
fallback alert.

Reasoning: ckpool's primary bitcoind submission must remain the
single source of truth, and getting the parallel "race a fallback
during the submit" semantics right is more architectural complexity
than the marginal reliability gain justifies. The original upstream
behavior — submit to bitcoind, retry indefinitely if unavailable —
is what we want.

Kept intact:
  * Submit-attempt vs confirmed counters (block_submit_attempts /
    block_submits_confirmed). Useful on their own as a "did bitcoind
    confirm the submission?" signal.
  * HealthBanners shows submit_gap and zmq_stale only.
  * /healthz exposes submit_gap, zmq_stale, etc.
  * All P0 reliability work (tailer cursor, reconcile loop, reorg
    detection, multi-solve guard) and other P1 (RPC retry, WS
    back-pressure, ZMQ tracking, startup readiness gate).
This commit is contained in:
satoshi
2026-04-28 02:07:17 +03:00
parent 99302cf4af
commit 1dcf087842
9 changed files with 20 additions and 618 deletions
-63
View File
@@ -11,7 +11,6 @@ import (
"fmt"
"log/slog"
"net/http"
"net/url"
"os"
"os/signal"
"strconv"
@@ -20,7 +19,6 @@ import (
"time"
"github.com/kamadopool/kamado-api/internal/bitcoind"
"github.com/kamadopool/kamado-api/internal/blocksubmit"
"github.com/kamadopool/kamado-api/internal/ckpool"
"github.com/kamadopool/kamado-api/internal/config"
"github.com/kamadopool/kamado-api/internal/httpapi"
@@ -118,29 +116,6 @@ func main() {
go agg.IngestBlockEvents(ctx, tailer.Events)
go agg.IngestAttemptEvents(ctx, tailer.Attempts)
// Fallback block submitter: if ckpool's primary bitcoind doesn't
// accept a block, the patched local_block_submit leaves the raw
// hex sitting in PENDING_BLOCKS_DIR. This watcher re-broadcasts it
// via the operator-configured BACKUP_RPC_URLS list.
if cfg.PendingBlocksDir != "" {
fallbacks := parseBackupRPCs(cfg.BackupRPCURLs, log)
sub := &blocksubmit.Submitter{
Dir: cfg.PendingBlocksDir,
Grace: cfg.PendingBlocksGrace,
Primary: rpc,
Fallbacks: fallbacks,
Log: log,
OnSuccess: func(height int64, viaURL, viaLabel string) {
agg.RecordFallbackSubmit(height, viaLabel)
},
}
// Sweep every second so we react within ~grace+1s of a
// failed submit. Reading an empty directory is cheap.
go sub.Run(ctx, 1*time.Second)
} else {
log.Info("blocksubmit fallback disabled (PENDING_BLOCKS_DIR not set)")
}
// Wait briefly for the aggregator's first refresh to complete so
// the very first /api/snapshot or /api/health hit doesn't see an
// all-zeros snapshot and report bitcoin_ok=false during its own
@@ -177,41 +152,3 @@ func main() {
os.Exit(1)
}
}
// parseBackupRPCs splits BACKUP_RPC_URLS (newline- or comma-separated)
// into FallbackTargets. Credentials are accepted inline as
// https://user:pass@host:port/. Lines beginning with '#' are comments.
// Whitespace and empty lines are ignored.
func parseBackupRPCs(raw string, log *slog.Logger) []blocksubmit.FallbackTarget {
if raw == "" {
return nil
}
separated := strings.NewReplacer(",", "\n").Replace(raw)
var out []blocksubmit.FallbackTarget
for _, line := range strings.Split(separated, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
u, err := url.Parse(line)
if err != nil {
log.Warn("blocksubmit: invalid fallback URL, skipping", "raw", line, "err", err)
continue
}
var user, pass string
if u.User != nil {
user = u.User.Username()
pass, _ = u.User.Password()
u.User = nil
}
clean := u.String()
out = append(out, blocksubmit.FallbackTarget{
URL: clean,
User: user,
Password: pass,
Label: u.Host,
})
log.Info("blocksubmit fallback registered", "url", clean, "host", u.Host, "auth", user != "")
}
return out
}