-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathconfig_validate.go
More file actions
143 lines (141 loc) · 5.58 KB
/
config_validate.go
File metadata and controls
143 lines (141 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"fmt"
"math/bits"
"net/url"
"strings"
)
func validateConfig(cfg Config) error {
if cfg.Extranonce2Size <= 0 {
return fmt.Errorf("extranonce2_size must be > 0, got %d", cfg.Extranonce2Size)
}
if cfg.TemplateExtraNonce2Size <= 0 {
cfg.TemplateExtraNonce2Size = cfg.Extranonce2Size
}
if cfg.TemplateExtraNonce2Size < cfg.Extranonce2Size {
cfg.TemplateExtraNonce2Size = cfg.Extranonce2Size
}
if !cfg.AllowPublicRPC && !cfg.rpcCookieWatch && (strings.TrimSpace(cfg.RPCUser) == "" || strings.TrimSpace(cfg.RPCPass) == "") {
return fmt.Errorf("rpc credentials are missing (set node.rpc_cookie_path, allow public RPC, or restart with -allow-rpc-credentials configured)")
}
if strings.TrimSpace(cfg.RPCURL) == "" {
return fmt.Errorf("rpc_url is required")
}
if parsedRPC, err := url.Parse(cfg.RPCURL); err != nil {
return fmt.Errorf("rpc_url parse error: %w", err)
} else if parsedRPC.Scheme != "http" && parsedRPC.Scheme != "https" {
if parsedRPC.Scheme == "" {
return fmt.Errorf("rpc_url %q missing protocol scheme (http/https)", cfg.RPCURL)
}
return fmt.Errorf("rpc_url %q must use http or https scheme", cfg.RPCURL)
}
if strings.TrimSpace(cfg.PayoutAddress) == "" {
return fmt.Errorf("payout_address is required for coinbase outputs")
}
if cfg.MaxConns < 0 {
return fmt.Errorf("max_conns cannot be negative")
}
if cfg.MaxAcceptsPerSecond < 0 {
return fmt.Errorf("max_accepts_per_second cannot be negative")
}
if cfg.MaxAcceptBurst < 0 {
return fmt.Errorf("max_accept_burst cannot be negative")
}
if cfg.DefaultDifficulty < 0 {
return fmt.Errorf("default_difficulty cannot be negative")
}
if cfg.MaxRecentJobs <= 0 {
return fmt.Errorf("max_recent_jobs must be > 0, got %d", cfg.MaxRecentJobs)
}
if cfg.JobEntropy < 0 {
return fmt.Errorf("job_entropy cannot be negative")
}
if cfg.JobEntropy > maxJobEntropy {
return fmt.Errorf("job_entropy cannot exceed %d", maxJobEntropy)
}
if cfg.PoolEntropy != "" {
if len(cfg.PoolEntropy) != poolTagLength {
return fmt.Errorf("pool_entropy must be %d characters", poolTagLength)
}
if normalizePoolTag(cfg.PoolEntropy) != cfg.PoolEntropy {
return fmt.Errorf("pool_entropy must only contain alphanumeric characters")
}
}
if cfg.CoinbaseScriptSigMaxBytes < 0 {
return fmt.Errorf("coinbase_scriptsig_max_bytes cannot be negative")
}
if cfg.ConnectionTimeout < 0 {
return fmt.Errorf("connection_timeout_seconds cannot be negative")
}
if cfg.ConnectionTimeout < minMinerTimeout {
return fmt.Errorf("connection_timeout_seconds must be >= %s, got %s", minMinerTimeout, cfg.ConnectionTimeout)
}
if cfg.MinVersionBits < 0 {
return fmt.Errorf("min_version_bits cannot be negative")
}
if cfg.VersionMask == 0 && cfg.MinVersionBits > 0 {
return fmt.Errorf("min_version_bits requires version_mask to be non-zero")
}
availableBits := bits.OnesCount32(cfg.VersionMask)
if cfg.MinVersionBits > availableBits {
return fmt.Errorf("min_version_bits=%d exceeds available bits in version_mask (%d)", cfg.MinVersionBits, availableBits)
}
if cfg.MaxDifficulty < 0 {
return fmt.Errorf("max_difficulty cannot be negative")
}
if cfg.MinDifficulty < 0 {
return fmt.Errorf("min_difficulty cannot be negative")
}
if cfg.TargetSharesPerMin <= 0 {
return fmt.Errorf("target_shares_per_min must be > 0, got %v", cfg.TargetSharesPerMin)
}
if cfg.DifficultyStepGranularity <= 0 {
return fmt.Errorf("difficulty_step_granularity must be > 0, got %d", cfg.DifficultyStepGranularity)
}
if cfg.PoolFeePercent < 0 || cfg.PoolFeePercent >= 100 {
return fmt.Errorf("pool_fee_percent must be >= 0 and < 100, got %v", cfg.PoolFeePercent)
}
if cfg.OperatorDonationPercent < 0 || cfg.OperatorDonationPercent > 100 {
return fmt.Errorf("operator_donation_percent must be >= 0 and <= 100, got %v", cfg.OperatorDonationPercent)
}
if cfg.OperatorDonationPercent > 0 && strings.TrimSpace(cfg.OperatorDonationAddress) == "" {
return fmt.Errorf("operator_donation_address is required when operator_donation_percent > 0")
}
if cfg.HashrateEMATauSeconds <= 0 {
return fmt.Errorf("hashrate_ema_tau_seconds must be > 0, got %v", cfg.HashrateEMATauSeconds)
}
if cfg.SavedWorkerHistoryFlushInterval < 0 {
return fmt.Errorf("saved_worker_history_flush_interval_seconds cannot be negative")
}
if cfg.StratumPasswordEnabled && strings.TrimSpace(cfg.StratumPassword) == "" {
return fmt.Errorf("stratum_password_enabled is true but stratum_password is empty")
}
if cfg.ShareNTimeMaxForwardSeconds <= 0 {
return fmt.Errorf("share_ntime_max_forward_seconds must be > 0, got %v", cfg.ShareNTimeMaxForwardSeconds)
}
if normalizeShareJobFreshnessMode(cfg.ShareJobFreshnessMode) < 0 {
return fmt.Errorf("share_job_freshness_mode must be one of %d, %d, or %d", shareJobFreshnessOff, shareJobFreshnessJobID, shareJobFreshnessJobIDPrev)
}
if cfg.BanInvalidSubmissionsAfter < 0 {
return fmt.Errorf("ban_invalid_submissions_after cannot be negative")
}
if cfg.BanInvalidSubmissionsWindow < 0 {
return fmt.Errorf("ban_invalid_submissions_window_seconds cannot be negative")
}
if cfg.BanInvalidSubmissionsDuration < 0 {
return fmt.Errorf("ban_invalid_submissions_duration_seconds cannot be negative")
}
if cfg.ReconnectBanThreshold < 0 {
return fmt.Errorf("reconnect_ban_threshold cannot be negative")
}
if cfg.ReconnectBanWindowSeconds < 0 {
return fmt.Errorf("reconnect_ban_window_seconds cannot be negative")
}
if cfg.ReconnectBanDurationSeconds < 0 {
return fmt.Errorf("reconnect_ban_duration_seconds cannot be negative")
}
if cfg.StratumMessagesPerMinute < 0 {
return fmt.Errorf("stratum_messages_per_minute cannot be negative")
}
return nil
}