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