-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconfig.go
163 lines (134 loc) · 4.1 KB
/
config.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
package main
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/jessevdk/go-flags"
"github.com/rs/zerolog"
)
type config struct {
Listen string `long:"listen" description:"interface:port for server" default:"localhost:5080"`
JsonLog bool `long:"logging.json" description:"log to JSON format (default human readable)"`
LogLevel string `long:"logging.level" description:"log level" default:"debug"`
Bitcoind bitcoindConfig `group:"bitcoind" namespace:"bitcoind"`
}
type bitcoindConfig struct {
User string `long:"user"`
Pass string `long:"pass"`
PassFile string `long:"passfile" description:"if set, reads password from this file"`
Host string `long:"host" description:"host:port to connect to Bitcoin Core on. Inferred from network if not set."`
Cookie bool `long:"cookie" description:"Read cookie data from the data directory. Not compatible with user and pass options. "`
Network string `long:"network" default:"regtest" description:"Network Bitcoin Core is running on. Only used to infer other parameters if not set."`
Wallet string `long:"wallet" description:"equivalent to -rpcwallet in bitcoin-cli"`
}
func readConfig(ctx context.Context) (*config, error) {
var cfg config
if _, err := flags.Parse(&cfg); err != nil {
// help was requested, avoid print and non-zero exit code
if flagErr := new(flags.Error); errors.As(
err, &flagErr,
) && flagErr.Type == flags.ErrHelp {
os.Exit(0)
}
return nil, err
}
if err := configureLogging(&cfg); err != nil {
return nil, err
}
if cfg.Bitcoind.Pass != "" && cfg.Bitcoind.PassFile != "" {
return nil, errors.New("cannot set both pass and passfile")
}
if cfg.Bitcoind.PassFile != "" {
pass, err := os.ReadFile(cfg.Bitcoind.PassFile)
if err != nil {
return nil, fmt.Errorf("read passfile: %w", err)
}
cfg.Bitcoind.Pass = strings.TrimSpace(string(pass))
}
log := zerolog.Ctx(ctx)
if cfg.Bitcoind.Pass == "" && cfg.Bitcoind.User == "" {
log.Debug().
Msg("config: empty bitcoind.pass and bitcoind.user, defaulting to cookie")
cfg.Bitcoind.Cookie = true
}
net, ok := nets[cfg.Bitcoind.Network]
if !ok {
return nil, fmt.Errorf("unknown bitcoin network: %q", cfg.Bitcoind.Network)
}
if cfg.Bitcoind.Cookie {
log.Debug().
Str("network", cfg.Bitcoind.Network).
Msg("config: reading bitcoind cookie data")
if cfg.Bitcoind.Pass != "" ||
cfg.Bitcoind.User != "" {
return nil, fmt.Errorf("cannot set username or password when specifying bitcoind.cookie")
}
path, err := cookiePath(net)
if err != nil {
return nil, fmt.Errorf("could not find cookie path: %w", err)
}
log.Debug().Str("path", path).
Msg("config: found cookie path")
cookie, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("could not read cookie: %w", err)
}
user, pass, found := strings.Cut(string(cookie), ":")
if !found {
return nil, fmt.Errorf("could not parse cookie: %s", string(cookie))
}
cfg.Bitcoind.User = user
cfg.Bitcoind.Pass = pass
}
if cfg.Bitcoind.Host == "" {
log.Debug().Str("network", cfg.Bitcoind.Network).
Msg("config: empty bitcoind.host, inferring from network")
cfg.Bitcoind.Host = net.defaultRpcHost
}
if cfg.Bitcoind.Wallet != "" {
cfg.Bitcoind.Host = fmt.Sprintf(
"%s/wallet/%s",
cfg.Bitcoind.Host, cfg.Bitcoind.Wallet,
)
}
return &cfg, nil
}
func cookiePath(network bitcoinNet) (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".bitcoin", network.path, ".cookie"), nil
}
type bitcoinNet struct {
path string
defaultRpcHost string
}
var (
mainnet = bitcoinNet{
path: "",
defaultRpcHost: "localhost:8332",
}
testnet = bitcoinNet{
path: "testnet3",
defaultRpcHost: "localhost:18332",
}
regtest = bitcoinNet{
path: "regtest",
defaultRpcHost: "localhost:18443",
}
signet = bitcoinNet{
path: "signet",
defaultRpcHost: "localhost:38332",
}
)
var nets = map[string]bitcoinNet{
"mainnet": mainnet,
"testnet": testnet,
"testnet3": testnet,
"regtest": regtest,
"signet": signet,
}