master
go 289 lines 6.76 KB
Raw
1 package config
2
3 import (
4 "crypto/rand"
5 "encoding/base64"
6 "fmt"
7 "io"
8 "time"
9
10 "github.com/cockroachdb/pebble/v2"
11 "github.com/ipfs/kubo/core/coreiface/options"
12 "github.com/libp2p/go-libp2p/core/crypto"
13 "github.com/libp2p/go-libp2p/core/peer"
14 )
15
16 func Init(out io.Writer, nBitsForKeypair int) (*Config, error) {
17 identity, err := CreateIdentity(out, []options.KeyGenerateOption{options.Key.Size(nBitsForKeypair)})
18 if err != nil {
19 return nil, err
20 }
21
22 return InitWithIdentity(identity)
23 }
24
25 func InitWithIdentity(identity Identity) (*Config, error) {
26 datastore := DefaultDatastoreConfig()
27
28 conf := &Config{
29 API: API{
30 HTTPHeaders: map[string][]string{},
31 },
32
33 // setup the node's default addresses.
34 // NOTE: two swarm listen addrs, one tcp, one utp.
35 Addresses: addressesConfig(),
36
37 Datastore: datastore,
38 Bootstrap: []string{AutoPlaceholder},
39 Identity: identity,
40 Discovery: Discovery{
41 MDNS: MDNS{
42 Enabled: true,
43 },
44 },
45
46 // setup the node mount points.
47 Mounts: Mounts{
48 IPFS: "/ipfs",
49 IPNS: "/ipns",
50 MFS: "/mfs",
51 },
52
53 Ipns: Ipns{
54 ResolveCacheSize: 128,
55 DelegatedPublishers: []string{AutoPlaceholder},
56 },
57
58 Gateway: Gateway{
59 RootRedirect: "",
60 NoFetch: false,
61 HTTPHeaders: map[string][]string{},
62 },
63 Pinning: Pinning{
64 RemoteServices: map[string]RemotePinningService{},
65 },
66 DNS: DNS{
67 Resolvers: map[string]string{
68 ".": AutoPlaceholder,
69 },
70 },
71 Routing: Routing{
72 DelegatedRouters: []string{AutoPlaceholder},
73 },
74 }
75
76 return conf, nil
77 }
78
79 // DefaultConnMgrHighWater is the default value for the connection managers
80 // 'high water' mark.
81 const DefaultConnMgrHighWater = 96
82
83 // DefaultConnMgrLowWater is the default value for the connection managers 'low
84 // water' mark.
85 const DefaultConnMgrLowWater = 32
86
87 // DefaultConnMgrGracePeriod is the default value for the connection managers
88 // grace period.
89 const DefaultConnMgrGracePeriod = time.Second * 20
90
91 // DefaultConnMgrSilencePeriod controls how often the connection manager enforces the limits.
92 const DefaultConnMgrSilencePeriod = time.Second * 10
93
94 // DefaultConnMgrType is the default value for the connection managers
95 // type.
96 const DefaultConnMgrType = "basic"
97
98 // DefaultResourceMgrMinInboundConns is a MAGIC number that probably a good
99 // enough number of inbound conns to be a good network citizen.
100 const DefaultResourceMgrMinInboundConns = 800
101
102 func addressesConfig() Addresses {
103 return Addresses{
104 Swarm: []string{
105 "/ip4/0.0.0.0/tcp/4001",
106 "/ip6/::/tcp/4001",
107 "/ip4/0.0.0.0/udp/4001/webrtc-direct",
108 "/ip4/0.0.0.0/udp/4001/quic-v1",
109 "/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
110 "/ip6/::/udp/4001/webrtc-direct",
111 "/ip6/::/udp/4001/quic-v1",
112 "/ip6/::/udp/4001/quic-v1/webtransport",
113 },
114 Announce: []string{},
115 AppendAnnounce: []string{},
116 NoAnnounce: []string{},
117 API: Strings{"/ip4/127.0.0.1/tcp/5001"},
118 Gateway: Strings{"/ip4/127.0.0.1/tcp/8080"},
119 }
120 }
121
122 // DefaultDatastoreConfig is an internal function exported to aid in testing.
123 func DefaultDatastoreConfig() Datastore {
124 return Datastore{
125 StorageMax: "10GB",
126 StorageGCWatermark: 90, // 90%
127 GCPeriod: "1h",
128 BloomFilterSize: 0,
129 Spec: flatfsSpec(),
130 }
131 }
132
133 func pebbleSpec() map[string]any {
134 return map[string]any{
135 "type": "pebbleds",
136 "prefix": "pebble.datastore",
137 "path": "pebbleds",
138 "formatMajorVersion": int(pebble.FormatNewest),
139 }
140 }
141
142 func pebbleSpecMeasure() map[string]any {
143 return map[string]any{
144 "type": "measure",
145 "prefix": "pebble.datastore",
146 "child": map[string]any{
147 "formatMajorVersion": int(pebble.FormatNewest),
148 "type": "pebbleds",
149 "path": "pebbleds",
150 },
151 }
152 }
153
154 func badgerSpec() map[string]any {
155 return map[string]any{
156 "type": "badgerds",
157 "prefix": "badger.datastore",
158 "path": "badgerds",
159 "syncWrites": false,
160 "truncate": true,
161 }
162 }
163
164 func badgerSpecMeasure() map[string]any {
165 return map[string]any{
166 "type": "measure",
167 "prefix": "badger.datastore",
168 "child": map[string]any{
169 "type": "badgerds",
170 "path": "badgerds",
171 "syncWrites": false,
172 "truncate": true,
173 },
174 }
175 }
176
177 func flatfsSpec() map[string]any {
178 return map[string]any{
179 "type": "mount",
180 "mounts": []any{
181 map[string]any{
182 "mountpoint": "/blocks",
183 "type": "flatfs",
184 "prefix": "flatfs.datastore",
185 "path": "blocks",
186 "sync": false,
187 "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
188 },
189 map[string]any{
190 "mountpoint": "/",
191 "type": "levelds",
192 "prefix": "leveldb.datastore",
193 "path": "datastore",
194 "compression": "none",
195 },
196 },
197 }
198 }
199
200 func flatfsSpecMeasure() map[string]any {
201 return map[string]any{
202 "type": "mount",
203 "mounts": []any{
204 map[string]any{
205 "mountpoint": "/blocks",
206 "type": "measure",
207 "prefix": "flatfs.datastore",
208 "child": map[string]any{
209 "type": "flatfs",
210 "path": "blocks",
211 "sync": false,
212 "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
213 },
214 },
215 map[string]any{
216 "mountpoint": "/",
217 "type": "measure",
218 "prefix": "leveldb.datastore",
219 "child": map[string]any{
220 "type": "levelds",
221 "path": "datastore",
222 "compression": "none",
223 },
224 },
225 },
226 }
227 }
228
229 // CreateIdentity initializes a new identity.
230 func CreateIdentity(out io.Writer, opts []options.KeyGenerateOption) (Identity, error) {
231 // TODO guard higher up
232 ident := Identity{}
233
234 settings, err := options.KeyGenerateOptions(opts...)
235 if err != nil {
236 return ident, err
237 }
238
239 var sk crypto.PrivKey
240 var pk crypto.PubKey
241
242 switch settings.Algorithm {
243 case "rsa":
244 if settings.Size == -1 {
245 settings.Size = options.DefaultRSALen
246 }
247
248 fmt.Fprintf(out, "generating %d-bit RSA keypair...", settings.Size)
249
250 priv, pub, err := crypto.GenerateKeyPair(crypto.RSA, settings.Size)
251 if err != nil {
252 return ident, err
253 }
254
255 sk = priv
256 pk = pub
257 case "ed25519":
258 if settings.Size != -1 {
259 return ident, fmt.Errorf("number of key bits does not apply when using ed25519 keys")
260 }
261 fmt.Fprintf(out, "generating ED25519 keypair...")
262 priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
263 if err != nil {
264 return ident, err
265 }
266
267 sk = priv
268 pk = pub
269 default:
270 return ident, fmt.Errorf("unrecognized key type: %s", settings.Algorithm)
271 }
272 fmt.Fprintf(out, "done\n")
273
274 // currently storing key unencrypted. in the future we need to encrypt it.
275 // TODO(security)
276 skbytes, err := crypto.MarshalPrivateKey(sk)
277 if err != nil {
278 return ident, err
279 }
280 ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
281
282 id, err := peer.IDFromPublicKey(pk)
283 if err != nil {
284 return ident, err
285 }
286 ident.PeerID = id.String()
287 fmt.Fprintf(out, "peer identity: %s\n", ident.PeerID)
288 return ident, nil
289 }