master
go 145 lines 3.16 KB
Raw
1 package node
2
3 import (
4 "context"
5 "crypto/rand"
6 "encoding/base64"
7 "time"
8
9 "go.uber.org/fx"
10
11 "github.com/ipfs/boxo/autoconf"
12 "github.com/ipfs/kubo/core/node/helpers"
13 "github.com/ipfs/kubo/core/node/libp2p"
14 "github.com/ipfs/kubo/core/shutdown"
15 "github.com/ipfs/kubo/repo"
16
17 ds "github.com/ipfs/go-datastore"
18 dsync "github.com/ipfs/go-datastore/sync"
19 cfg "github.com/ipfs/kubo/config"
20 "github.com/libp2p/go-libp2p/core/crypto"
21 peer "github.com/libp2p/go-libp2p/core/peer"
22 )
23
24 type BuildCfg struct {
25 // If online is set, the node will have networking enabled
26 Online bool
27
28 // ExtraOpts is a map of extra options used to configure the ipfs nodes creation
29 ExtraOpts map[string]bool
30
31 // If permanent then node should run more expensive processes
32 // that will improve performance in long run
33 Permanent bool
34
35 // DisableEncryptedConnections disables connection encryption *entirely*.
36 // DO NOT SET THIS UNLESS YOU'RE TESTING.
37 DisableEncryptedConnections bool
38
39 Routing libp2p.RoutingOption
40 Host libp2p.HostOption
41 Repo repo.Repo
42
43 // ShutdownTimeout caps how long node.Close()'s call to app.Stop is
44 // allowed to take. Zero disables the cap (app.Stop runs with no
45 // deadline, matching the legacy "wait forever" behavior).
46 ShutdownTimeout time.Duration
47 }
48
49 func (cfg *BuildCfg) getOpt(key string) bool {
50 if cfg.ExtraOpts == nil {
51 return false
52 }
53
54 return cfg.ExtraOpts[key]
55 }
56
57 func (cfg *BuildCfg) fillDefaults() error {
58 if cfg.Repo == nil {
59 r, err := defaultRepo(dsync.MutexWrap(ds.NewMapDatastore()))
60 if err != nil {
61 return err
62 }
63 cfg.Repo = r
64 }
65
66 if cfg.Routing == nil {
67 cfg.Routing = libp2p.DHTOption
68 }
69
70 if cfg.Host == nil {
71 cfg.Host = libp2p.DefaultHostOption
72 }
73
74 return nil
75 }
76
77 // options creates fx option group from this build config
78 func (cfg *BuildCfg) options(ctx context.Context) (fx.Option, *cfg.Config) {
79 err := cfg.fillDefaults()
80 if err != nil {
81 return fx.Error(err), nil
82 }
83
84 repoOption := fx.Provide(func(lc fx.Lifecycle) repo.Repo {
85 lc.Append(fx.Hook{
86 OnStop: func(ctx context.Context) error {
87 return shutdown.CloseWithCtx(ctx, "repo", cfg.Repo.Close)
88 },
89 })
90
91 return cfg.Repo
92 })
93
94 metricsCtx := fx.Provide(func() helpers.MetricsCtx {
95 return helpers.MetricsCtx(ctx)
96 })
97
98 hostOption := fx.Provide(func() libp2p.HostOption {
99 return cfg.Host
100 })
101
102 routingOption := fx.Provide(func() libp2p.RoutingOption {
103 return cfg.Routing
104 })
105
106 conf, err := cfg.Repo.Config()
107 if err != nil {
108 return fx.Error(err), nil
109 }
110
111 return fx.Options(
112 repoOption,
113 hostOption,
114 routingOption,
115 metricsCtx,
116 ), conf
117 }
118
119 func defaultRepo(dstore repo.Datastore) (repo.Repo, error) {
120 c := cfg.Config{}
121 priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader)
122 if err != nil {
123 return nil, err
124 }
125
126 pid, err := peer.IDFromPublicKey(pub)
127 if err != nil {
128 return nil, err
129 }
130
131 privkeyb, err := crypto.MarshalPrivateKey(priv)
132 if err != nil {
133 return nil, err
134 }
135
136 c.Bootstrap = autoconf.FallbackBootstrapPeers
137 c.Addresses.Swarm = []string{"/ip4/0.0.0.0/tcp/4001", "/ip4/0.0.0.0/udp/4001/quic-v1"}
138 c.Identity.PeerID = pid.String()
139 c.Identity.PrivKey = base64.StdEncoding.EncodeToString(privkeyb)
140
141 return &repo.Mock{
142 D: dstore,
143 C: c,
144 }, nil
145 }