From fd6bc01b87b77326eb6398ba0d8193c3f25c85cf Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 23:48:33 +0000 Subject: [PATCH] docs(proxy): align API comments with AX Co-Authored-By: Virgil --- api/router.go | 9 +++------ api_rows.go | 36 +++++++++--------------------------- config.go | 29 +++++++---------------------- pool/client.go | 12 +++++------- proxy.go | 40 +++++++++++++++++----------------------- stats.go | 17 ++++++----------- worker.go | 10 +++------- 7 files changed, 50 insertions(+), 103 deletions(-) diff --git a/api/router.go b/api/router.go index a9493de..8343fe6 100644 --- a/api/router.go +++ b/api/router.go @@ -16,16 +16,13 @@ import ( "dappco.re/go/proxy" ) -// Router matches the standard http.ServeMux registration shape. +// http.NewServeMux() type Router interface { HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) } -// RegisterRoutes wires the monitoring endpoints onto the supplied router. -// -// mux := http.NewServeMux() -// proxyapi.RegisterRoutes(mux, p) -// // GET /1/summary, /1/workers, and /1/miners are now live. +// mux := http.NewServeMux() +// RegisterRoutes(mux, p) func RegisterRoutes(router Router, p *proxy.Proxy) { if router == nil || p == nil { return diff --git a/api_rows.go b/api_rows.go index b256420..0d3bd6b 100644 --- a/api_rows.go +++ b/api_rows.go @@ -1,18 +1,12 @@ package proxy -// WorkerRow is one row in the /1/workers table. -// -// WorkerRow{"rig-alpha", "10.0.0.1", 1, 10, 0, 0, 100000, 1712232000, 1.0, 1.0, 1.0, 1.0, 1.0} +// WorkerRow{"rig-alpha", "10.0.0.1", 1, 10, 0, 0, 100000, 1712232000, 1.0, 1.0, 1.0, 1.0, 1.0} type WorkerRow [13]any -// MinerRow is one row in the /1/miners table. -// -// MinerRow{1, "10.0.0.1:49152", 4096, 512, 2, 100000, "WALLET", "********", "rig-alpha", "XMRig/6.21.0"} +// MinerRow{1, "10.0.0.1:49152", 4096, 512, 2, 100000, "WALLET", "********", "rig-alpha", "XMRig/6.21.0"} type MinerRow [10]any -// SummaryDocument is the RFC-shaped /1/summary response body. -// -// doc := p.SummaryDocument() +// p.SummaryDocument() type SummaryDocument struct { Version string `json:"version"` Mode string `json:"mode"` @@ -24,24 +18,18 @@ type SummaryDocument struct { CustomDiffStats map[uint64]CustomDiffBucketStats `json:"custom_diff_stats,omitempty"` } -// HashrateDocument carries the per-window hashrate array. -// -// HashrateDocument{Total: [6]float64{12345.67, 11900.00, 12100.00, 11800.00, 12000.00, 12200.00}} +// HashrateDocument{Total: [6]float64{12345.67, 11900.00, 12100.00, 11800.00, 12000.00, 12200.00}} type HashrateDocument struct { Total [6]float64 `json:"total"` } -// MinersCountDocument carries current and peak miner counts. -// -// MinersCountDocument{Now: 142, Max: 200} +// MinersCountDocument{Now: 142, Max: 200} type MinersCountDocument struct { Now uint64 `json:"now"` Max uint64 `json:"max"` } -// UpstreamDocument carries pool connection state counts. -// -// UpstreamDocument{Active: 1, Sleep: 0, Error: 0, Total: 1, Ratio: 142.0} +// UpstreamDocument{Active: 1, Sleep: 0, Error: 0, Total: 1, Ratio: 142.0} type UpstreamDocument struct { Active uint64 `json:"active"` Sleep uint64 `json:"sleep"` @@ -50,9 +38,7 @@ type UpstreamDocument struct { Ratio float64 `json:"ratio"` } -// ResultsDocument carries share acceptance statistics. -// -// ResultsDocument{Accepted: 4821, Rejected: 3, Invalid: 0, Expired: 12} +// ResultsDocument{Accepted: 4821, Rejected: 3, Invalid: 0, Expired: 12} type ResultsDocument struct { Accepted uint64 `json:"accepted"` Rejected uint64 `json:"rejected"` @@ -64,17 +50,13 @@ type ResultsDocument struct { Best [10]uint64 `json:"best"` } -// WorkersDocument is the RFC-shaped /1/workers response body. -// -// doc := p.WorkersDocument() +// p.WorkersDocument() type WorkersDocument struct { Mode string `json:"mode"` Workers []WorkerRow `json:"workers"` } -// MinersDocument is the RFC-shaped /1/miners response body. -// -// doc := p.MinersDocument() +// p.MinersDocument() type MinersDocument struct { Format []string `json:"format"` Miners []MinerRow `json:"miners"` diff --git a/config.go b/config.go index 63a9046..c7dd84e 100644 --- a/config.go +++ b/config.go @@ -1,11 +1,6 @@ package proxy -// Config is the top-level proxy configuration, loaded from JSON and hot-reloaded on change. -// -// cfg, result := proxy.LoadConfig("/etc/proxy.json") -// if !result.OK { -// return result.Error -// } +// LoadConfig("/etc/proxy.json") type Config struct { Mode string `json:"mode"` // "nicehash" or "simple" Bind []BindAddr `json:"bind"` // listen addresses @@ -27,18 +22,14 @@ type Config struct { configPath string } -// BindAddr is one TCP listen endpoint. -// -// proxy.BindAddr{Host: "0.0.0.0", Port: 3333, TLS: false} +// BindAddr{Host: "0.0.0.0", Port: 3333, TLS: false} type BindAddr struct { Host string `json:"host"` Port uint16 `json:"port"` TLS bool `json:"tls"` } -// PoolConfig is one upstream pool entry. -// -// proxy.PoolConfig{URL: "pool.lthn.io:3333", User: "WALLET", Pass: "x", Enabled: true} +// PoolConfig{URL: "pool.lthn.io:3333", User: "WALLET", Pass: "x", Enabled: true} type PoolConfig struct { URL string `json:"url"` User string `json:"user"` @@ -51,9 +42,7 @@ type PoolConfig struct { Enabled bool `json:"enabled"` } -// TLSConfig controls inbound TLS on bind addresses that have TLS: true. -// -// proxy.TLSConfig{Enabled: true, CertFile: "/etc/proxy/cert.pem", KeyFile: "/etc/proxy/key.pem"} +// TLSConfig{Enabled: true, CertFile: "/etc/proxy/cert.pem", KeyFile: "/etc/proxy/key.pem"} type TLSConfig struct { Enabled bool `json:"enabled"` CertFile string `json:"cert"` @@ -62,9 +51,7 @@ type TLSConfig struct { Protocols string `json:"protocols"` // TLS version string; "" = default } -// HTTPConfig controls the monitoring API server. -// -// proxy.HTTPConfig{Enabled: true, Host: "127.0.0.1", Port: 8080, Restricted: true} +// HTTPConfig{Enabled: true, Host: "127.0.0.1", Port: 8080, Restricted: true} type HTTPConfig struct { Enabled bool `json:"enabled"` Host string `json:"host"` @@ -73,15 +60,13 @@ type HTTPConfig struct { Restricted bool `json:"restricted"` // true = read-only GET only } -// RateLimit controls per-IP connection rate limiting using a token bucket. -// -// proxy.RateLimit{MaxConnectionsPerMinute: 30, BanDurationSeconds: 300} +// RateLimit{MaxConnectionsPerMinute: 30, BanDurationSeconds: 300} type RateLimit struct { MaxConnectionsPerMinute int `json:"max-connections-per-minute"` // 0 = disabled BanDurationSeconds int `json:"ban-duration"` // 0 = no ban } -// WorkersMode controls which login field becomes the worker name. +// WorkersByRigID type WorkersMode string const ( diff --git a/pool/client.go b/pool/client.go index 3b23e4c..568b89f 100644 --- a/pool/client.go +++ b/pool/client.go @@ -12,12 +12,8 @@ import ( "dappco.re/go/proxy" ) -// StratumClient is one outbound stratum TCP (optionally TLS) connection to a pool. -// The proxy presents itself to the pool as a standard stratum miner using the -// wallet address and password from PoolConfig. -// -// client := pool.NewStratumClient(poolCfg, listener) -// client.Connect() +// client := NewStratumClient(poolCfg, listener) +// client.Connect() type StratumClient struct { config proxy.PoolConfig listener StratumListener @@ -32,7 +28,9 @@ type StratumClient struct { sendMu sync.Mutex } -// StratumListener receives events from the pool connection. +// type listener struct{} +// +// func (listener) OnJob(job proxy.Job) {} type StratumListener interface { // OnJob is called when the pool pushes a new job notification or the login reply contains a job. OnJob(job proxy.Job) diff --git a/proxy.go b/proxy.go index dfee952..e399796 100644 --- a/proxy.go +++ b/proxy.go @@ -17,11 +17,11 @@ import ( "time" ) -// Proxy is the top-level orchestrator. It owns the server, splitter, stats, workers, -// event bus, tick goroutine, and optional HTTP API. +// p, result := proxy.New(cfg) // -// p, result := proxy.New(cfg) -// if result.OK { p.Start() } +// if result.OK { +// p.Start() +// } type Proxy struct { config *Config splitter Splitter @@ -44,7 +44,9 @@ type Proxy struct { submitCount atomic.Int64 } -// Splitter is the interface both NonceSplitter and SimpleSplitter satisfy. +// type stubSplitter struct{} +// +// func (stubSplitter) Connect() {} type Splitter interface { // Connect establishes the first pool upstream connection. Connect() @@ -62,7 +64,7 @@ type Splitter interface { Upstreams() UpstreamStats } -// UpstreamStats carries pool connection state counts for monitoring. +// UpstreamStats{Active: 1, Sleep: 0, Error: 0, Total: 1} type UpstreamStats struct { Active uint64 // connections currently receiving jobs Sleep uint64 // idle connections (simple mode reuse pool) @@ -70,12 +72,12 @@ type UpstreamStats struct { Total uint64 // Active + Sleep + Error } -// LoginEvent is dispatched when a miner completes the login handshake. +// LoginEvent{Miner: miner} type LoginEvent struct { Miner *Miner } -// SubmitEvent is dispatched when a miner submits a share. +// SubmitEvent{Miner: miner, JobID: "job-1", Nonce: "deadbeef", Result: "HASH", RequestID: 2} type SubmitEvent struct { Miner *Miner JobID string @@ -85,15 +87,12 @@ type SubmitEvent struct { RequestID int64 } -// CloseEvent is dispatched when a miner TCP connection closes. +// CloseEvent{Miner: miner} type CloseEvent struct { Miner *Miner } -// ConfigWatcher polls a config file for mtime changes and calls onChange on modification. -// -// w := proxy.NewConfigWatcher("config.json", func(cfg *proxy.Config) { p.Reload(cfg) }) -// w.Start() +// NewConfigWatcher("config.json", func(cfg *Config) { p.Reload(cfg) }) type ConfigWatcher struct { path string onChange func(*Config) @@ -101,10 +100,8 @@ type ConfigWatcher struct { done chan struct{} } -// RateLimiter implements per-IP token bucket connection rate limiting. -// -// rl := proxy.NewRateLimiter(proxy.RateLimit{MaxConnectionsPerMinute: 30, BanDurationSeconds: 300}) -// if rl.Allow("1.2.3.4:3333") { proceed() } +// limiter := NewRateLimiter(RateLimit{MaxConnectionsPerMinute: 30, BanDurationSeconds: 300}) +// limiter.Allow("1.2.3.4:3333") type RateLimiter struct { config RateLimit buckets map[string]*tokenBucket @@ -112,17 +109,14 @@ type RateLimiter struct { mu sync.Mutex } -// tokenBucket is a simple token bucket for one IP. +// tokenBucket{tokens: 30, lastRefill: time.Now()} type tokenBucket struct { tokens int lastRefill time.Time } -// CustomDiff resolves and applies per-miner difficulty overrides at login time. -// Resolution order: user-suffix (+N) > Config.CustomDiff > pool difficulty. -// -// cd := proxy.NewCustomDiff(cfg.CustomDiff) -// bus.Subscribe(proxy.EventLogin, cd.OnLogin) +// resolver := NewCustomDiff(50000) +// resolver.Apply(&Miner{user: "WALLET+75000"}) type CustomDiff struct { globalDiff uint64 } diff --git a/stats.go b/stats.go index ca03d7d..b19558f 100644 --- a/stats.go +++ b/stats.go @@ -6,12 +6,9 @@ import ( "time" ) -// Stats tracks global proxy metrics. Hot-path counters are atomic. Hashrate windows -// use a ring buffer per window size, advanced by Tick(). -// -// stats := proxy.NewStats() -// bus.Subscribe(proxy.EventAccept, stats.OnAccept) -// bus.Subscribe(proxy.EventReject, stats.OnReject) +// stats := NewStats() +// bus.Subscribe(EventAccept, stats.OnAccept) +// bus.Subscribe(EventReject, stats.OnReject) type Stats struct { accepted atomic.Uint64 rejected atomic.Uint64 @@ -28,7 +25,7 @@ type Stats struct { mu sync.Mutex } -// Hashrate window sizes in seconds. Index maps to Stats.windows and SummaryResponse.Hashrate. +// HashrateWindow60s const ( HashrateWindow60s = 0 // 1 minute HashrateWindow600s = 1 // 10 minutes @@ -38,16 +35,14 @@ const ( HashrateWindowAll = 5 // all-time (single accumulator, no window) ) -// tickWindow is a fixed-capacity ring buffer of per-second difficulty sums. +// newTickWindow(60) type tickWindow struct { buckets []uint64 pos int size int // window size in seconds = len(buckets) } -// StatsSummary is the serialisable snapshot returned by Summary(). -// -// summary := stats.Summary() +// NewStats().Summary() type StatsSummary struct { Accepted uint64 `json:"accepted"` Rejected uint64 `json:"rejected"` diff --git a/worker.go b/worker.go index 8bd1db3..7f04e26 100644 --- a/worker.go +++ b/worker.go @@ -5,10 +5,8 @@ import ( "time" ) -// Workers maintains per-worker aggregate stats. Workers are identified by name, -// derived from the miner's login fields per WorkersMode. -// -// workers := proxy.NewWorkers(proxy.WorkersByRigID, bus) +// workers := NewWorkers(WorkersByRigID, bus) +// records := workers.List() type Workers struct { mode WorkersMode entries []WorkerRecord // ordered by first-seen (stable) @@ -18,9 +16,7 @@ type Workers struct { mu sync.RWMutex } -// WorkerRecord is the per-identity aggregate. -// -// hr60 := record.Hashrate(60) +// record.Hashrate(60) type WorkerRecord struct { Name string LastIP string