-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validateconf.go
391 lines (375 loc) · 13.6 KB
/
validateconf.go
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
package cmd
import (
"errors"
"fmt"
"net"
"os"
"path/filepath"
"strings"
"time"
"git.parallelcoin.io/dev/9/cmd/node"
blockchain "git.parallelcoin.io/dev/9/pkg/chain"
"git.parallelcoin.io/dev/9/pkg/chain/fork"
"git.parallelcoin.io/dev/9/pkg/peer/connmgr"
"git.parallelcoin.io/dev/9/pkg/util"
"git.parallelcoin.io/dev/9/pkg/util/cl"
"github.com/btcsuite/go-socks/socks"
)
func setAppDataDir(app *App, name string) {
if app != nil {
if app.Config != nil {
if app.Config.AppDataDir == nil {
app.Config.AppDataDir = new(string)
// set AppDataDir for running as node
*app.Config.AppDataDir =
CleanAndExpandPath(
filepath.Join(*app.Config.DataDir, name),
*app.Config.DataDir)
}
if app.Config.LogDir == nil {
app.Config.LogDir = new(string)
*app.Config.LogDir = *app.Config.AppDataDir
}
}
}
}
func validateWhitelists(app *App) int {
// Validate any given whitelisted IP addresses and networks.
if app.Config.Whitelists != nil {
var ip net.IP
app.Config.State.ActiveWhitelists =
make([]*net.IPNet, 0, len(*app.Config.Whitelists))
for _, addr := range *app.Config.Whitelists {
_, ipnet, err := net.ParseCIDR(addr)
if err != nil {
err = fmt.Errorf("%s '%s'", cl.Ine(), err.Error())
ip = net.ParseIP(addr)
if ip == nil {
str := err.Error() + " %s: the whitelist value of '%s' is invalid"
err = fmt.Errorf(str, "runNode", addr)
return 1
}
var bits int
if ip.To4() == nil {
// IPv6
bits = 128
} else {
bits = 32
}
ipnet = &net.IPNet{
IP: ip,
Mask: net.CIDRMask(bits, bits),
}
}
app.Config.State.ActiveWhitelists =
append(app.Config.State.ActiveWhitelists, ipnet)
}
}
return 0
}
func validateProxyListeners(app *App) int {
// if proxy is not enabled, empty the proxy field as node sees presence as a
// on switch
if app.Config.Proxy != nil {
*app.Config.Proxy = ""
}
// if proxy is enabled or listeners list is empty, or connect peers are set,
// disable p2p listener
if app.Config.Proxy != nil ||
app.Config.ConnectPeers != nil ||
app.Config.Listeners == nil {
if app.Config.DisableListen == nil {
acd := true
app.Config.DisableListen = &acd
} else {
*app.Config.DisableListen = true
}
}
if !*app.Config.DisableListen && len(*app.Config.Listeners) < 1 {
*app.Config.Listeners = []string{
net.JoinHostPort("127.0.0.1", node.DefaultPort),
}
}
return 0
}
func validatePasswords(app *App) int {
// Check to make sure limited and admin users don't have the same username
if *app.Config.Username != "" && *app.Config.Username == *app.Config.LimitUser {
str := "%s: --username and --limituser must not specify the same username"
err := fmt.Errorf(str, "runNode")
fmt.Fprintln(os.Stderr, err)
return 1
}
// Check to make sure limited and admin users don't have the same password
if *app.Config.Password != "" &&
*app.Config.Password == *app.Config.LimitPass {
str := "%s: --password and --limitpass must not specify the same password"
err := fmt.Errorf(str, "runNode")
fmt.Fprintln(os.Stderr, err)
return 1
}
return 0
}
func validateRPCCredentials(app *App) int {
// The RPC server is disabled if no username or password is provided.
if (*app.Config.Username == "" || *app.Config.Password == "") &&
(*app.Config.LimitUser == "" || *app.Config.LimitPass == "") {
*app.Config.DisableRPC = true
}
if *app.Config.DisableRPC {
}
if !*app.Config.DisableRPC && len(*app.Config.RPCListeners) == 0 {
addrs, err := net.LookupHost(node.DefaultRPCListener)
if err != nil {
return 1
}
*app.Config.RPCListeners = make([]string, 0, len(addrs))
for _, addr := range addrs {
addr = net.JoinHostPort(addr, app.Config.ActiveNetParams.RPCPort)
*app.Config.RPCListeners = append(*app.Config.RPCListeners, addr)
}
}
return 0
}
func validateBlockLimits(app *App) int {
// Validate the the minrelaytxfee.
// log <- cl.Debug{"checking min relay tx fee"}
var err error
app.Config.State.ActiveMinRelayTxFee, err =
util.NewAmount(*app.Config.MinRelayTxFee)
if err != nil {
str := "%s: invalid minrelaytxfee: %v"
err := fmt.Errorf(str, "runNode", err)
fmt.Println(err)
return 1
}
// Limit the block priority and minimum block sizes to max block size.
*app.Config.BlockPrioritySize = int(MinUint32(
uint32(*app.Config.BlockPrioritySize),
uint32(*app.Config.BlockMaxSize)))
*app.Config.BlockMinSize = int(MinUint32(
uint32(*app.Config.BlockMinSize),
uint32(*app.Config.BlockMaxSize)))
*app.Config.BlockMinWeight = int(MinUint32(
uint32(*app.Config.BlockMinWeight),
uint32(*app.Config.BlockMaxWeight)))
switch {
// If the max block size isn't set, but the max weight is, then we'll set the limit for the max block size to a safe limit so weight takes precedence.
case *app.Config.BlockMaxSize == node.DefaultBlockMaxSize &&
*app.Config.BlockMaxWeight != node.DefaultBlockMaxWeight:
*app.Config.BlockMaxSize = blockchain.MaxBlockBaseSize - 1000
// If the max block weight isn't set, but the block size is, then we'll scale the set weight accordingly based on the max block size value.
case *app.Config.BlockMaxSize != node.DefaultBlockMaxSize &&
*app.Config.BlockMaxWeight == node.DefaultBlockMaxWeight:
*app.Config.BlockMaxWeight = *app.Config.BlockMaxSize * blockchain.WitnessScaleFactor
}
if *app.Config.RejectNonStd && *app.Config.RelayNonStd {
fmt.Println("cannot both relay and reject nonstandard transactions")
return 1
}
return 0
}
func validateUAComments(app *App) int {
// Look for illegal characters in the user agent comments.
// log <- cl.Debug{"checking user agent comments"}
if app.Config.UserAgentComments != nil {
for _, uaComment := range *app.Config.UserAgentComments {
if strings.ContainsAny(uaComment, "/:()") {
err := fmt.Errorf("%s: The following characters must not "+
"appear in user agent comments: '/', ':', '(', ')'",
"runNode")
fmt.Fprintln(os.Stderr, err)
return 1
}
}
}
return 0
}
func validateMiner(app *App) int {
// Check mining addresses are valid and saved parsed versions.
// log <- cl.Debug{"checking mining addresses"}
if app.Config.MiningAddrs != nil {
app.Config.State.ActiveMiningAddrs =
make([]util.Address, 0, len(*app.Config.MiningAddrs))
if len(*app.Config.MiningAddrs) > 0 {
for _, strAddr := range *app.Config.MiningAddrs {
if len(strAddr) > 1 {
addr, err := util.DecodeAddress(strAddr, app.Config.ActiveNetParams.Params)
if err != nil {
str := "%s: mining address '%s' failed to decode: %v"
err := fmt.Errorf(str, "runNode", strAddr, err)
fmt.Fprintln(os.Stderr, err)
return 1
}
if !addr.IsForNet(app.Config.ActiveNetParams.Params) {
str := "%s: mining address '%s' is on the wrong network"
err := fmt.Errorf(str, "runNode", strAddr)
fmt.Fprintln(os.Stderr, err)
return 1
}
app.Config.State.ActiveMiningAddrs =
append(app.Config.State.ActiveMiningAddrs, addr)
} else {
*app.Config.MiningAddrs = []string{}
}
}
}
}
// Ensure there is at least one mining address when the generate flag
// is set.
if (*app.Config.Generate ||
app.Config.MinerListener != nil) &&
app.Config.MiningAddrs != nil {
str := "%s: the generate flag is set, but there are no mining addresses specified "
err := fmt.Errorf(str, "runNode")
fmt.Fprintln(os.Stderr, err)
return 1
}
if *app.Config.MinerPass != "" {
app.Config.State.ActiveMinerKey = fork.Argon2i([]byte(*app.Config.MinerPass))
}
return 0
}
func validateCheckpoints(app *App) int {
var err error
// Check the checkpoints for syntax errors.
// log <- cl.Debug{"checking the checkpoints"}
if app.Config.AddCheckpoints != nil {
app.Config.State.AddedCheckpoints, err =
node.ParseCheckpoints(*app.Config.AddCheckpoints)
if err != nil {
str := "%s: Error parsing checkpoints: %v"
err := fmt.Errorf(str, "runNode", err)
fmt.Fprintln(os.Stderr, err)
return 1
}
}
return 0
}
func validateDialers(app *App) int {
// if !*app.Config.Onion && *app.Config.OnionProxy != "" {
// // log <- cl.Error{"cannot enable tor proxy without an address specified"}
// return 1
// }
// Tor stream isolation requires either proxy or onion proxy to be set.
if *app.Config.TorIsolation &&
app.Config.Proxy == nil {
str := "%s: Tor stream isolation requires either proxy or onionproxy to be set"
err := fmt.Errorf(str, "runNode")
fmt.Fprintln(os.Stderr, err)
return 1
}
// Setup dial and DNS resolution (lookup) functions depending on the specified options. The default is to use the standard net.DialTimeout function as well as the system DNS resolver. When a proxy is specified, the dial function is set to the proxy specific dial function and the lookup is set to use tor (unless --noonion is specified in which case the system DNS resolver is used).
// log <- cl.Debug{"setting network dialer and lookup"}
app.Config.State.Dial = net.DialTimeout
app.Config.State.Lookup = net.LookupIP
if app.Config.Proxy != nil {
fmt.Println("loading proxy")
// log <- cl.Debug{"we are loading a proxy!"}
_, _, err := net.SplitHostPort(*app.Config.Proxy)
if err != nil {
str := "%s: Proxy address '%s' is invalid: %v"
err := fmt.Errorf(str, "runNode", *app.Config.Proxy, err)
fmt.Fprintln(os.Stderr, err)
return 1
}
// Tor isolation flag means proxy credentials will be overridden unless
// there is also an onion proxy configured in which case that one will be overridden.
torIsolation := false
if *app.Config.TorIsolation &&
(app.Config.ProxyUser != nil ||
app.Config.ProxyPass != nil) {
torIsolation = true
// log <- cl.Warn{
// "Tor isolation set -- overriding specified proxy user credentials"}
}
proxy := &socks.Proxy{
Addr: *app.Config.Proxy,
Username: *app.Config.ProxyUser,
Password: *app.Config.ProxyPass,
TorIsolation: torIsolation,
}
app.Config.State.Dial = proxy.DialTimeout
// Treat the proxy as tor and perform DNS resolution through it unless the --noonion flag is set or there is an onion-specific proxy configured.
if *app.Config.Onion &&
*app.Config.OnionProxy != "" {
app.Config.State.Lookup = func(host string) ([]net.IP, error) {
return connmgr.TorLookupIP(host, *app.Config.Proxy)
}
}
}
// Setup onion address dial function depending on the specified options. The default is to use the same dial function selected above. However, when an onion-specific proxy is specified, the onion address dial function is set to use the onion-specific proxy while leaving the normal dial function as selected above. This allows .onion address traffic to be routed through a different proxy than normal traffic.
// log <- cl.Debug{"setting up tor proxy if enabled"}
if app.Config.OnionProxy != nil {
_, _, err := net.SplitHostPort(*app.Config.OnionProxy)
if err != nil {
str := "%s: Onion proxy address '%s' is invalid: %v"
err := fmt.Errorf(str, "runNode", *app.Config.OnionProxy, err)
fmt.Fprintln(os.Stderr, err)
return 1
}
// Tor isolation flag means onion proxy credentials will be overriddenode.
if *app.Config.TorIsolation &&
(*app.Config.OnionProxyUser != "" || *app.Config.OnionProxyPass != "") {
// log <- cl.Warn{
// "Tor isolation set - overriding specified onionproxy user credentials "}
}
app.Config.State.Oniondial =
func(network, addr string, timeout time.Duration) (net.Conn, error) {
proxy := &socks.Proxy{
Addr: *app.Config.OnionProxy,
Username: *app.Config.OnionProxyUser,
Password: *app.Config.OnionProxyPass,
TorIsolation: *app.Config.TorIsolation,
}
return proxy.DialTimeout(network, addr, timeout)
}
// When configured in bridge mode (both --onion and --proxy are configured), it means that the proxy configured by --proxy is not a tor proxy, so override the DNS resolution to use the onion-specific proxy.
if *app.Config.Proxy != "" {
app.Config.State.Lookup = func(host string) ([]net.IP, error) {
return connmgr.TorLookupIP(host, *app.Config.OnionProxy)
}
}
} else {
app.Config.State.Oniondial = app.Config.State.Dial
}
// Specifying --noonion means the onion address dial function results in an error.
if !*app.Config.Onion {
app.Config.State.Oniondial = func(a, b string, t time.Duration) (net.Conn, error) {
return nil, errors.New("tor has been disabled")
}
}
return 0
}
func validateAddresses(app *App) int {
// TODO: simplify this to a boolean and one slice for config fercryinoutloud
if app.Config.AddPeers != nil && app.Config.ConnectPeers != nil {
fmt.Println("ERROR:", cl.Ine(),
"cannot have addpeers at the same time as connectpeers")
return 1
}
// Add default port to all rpc listener addresses if needed and remove duplicate addresses.
// log <- cl.Debug{"checking rpc listener addresses"}
*app.Config.RPCListeners =
node.NormalizeAddresses(*app.Config.RPCListeners,
app.Config.ActiveNetParams.RPCPort)
// Add default port to all listener addresses if needed and remove duplicate addresses.
if app.Config.Listeners != nil {
*app.Config.Listeners =
node.NormalizeAddresses(*app.Config.Listeners,
app.Config.ActiveNetParams.DefaultPort)
}
// Add default port to all added peer addresses if needed and remove duplicate addresses.
if app.Config.AddPeers != nil {
*app.Config.AddPeers =
node.NormalizeAddresses(*app.Config.AddPeers,
app.Config.ActiveNetParams.DefaultPort)
}
if app.Config.ConnectPeers != nil {
*app.Config.ConnectPeers =
node.NormalizeAddresses(*app.Config.ConnectPeers,
app.Config.ActiveNetParams.DefaultPort)
}
// --onionproxy and not --onion are contradictory (TODO: this is kinda stupid hm? switch *and* toggle by presence of flag value, one should be enough)
return 0
}