builder.go 3.15 KB
Newer Older
Łukasz Magiera's avatar
Łukasz Magiera committed
1 2 3
package node

import (
4
	"context"
5 6 7 8
	"crypto/rand"
	"encoding/base64"
	"errors"

9 10
	"go.uber.org/fx"

tavit ohanian's avatar
tavit ohanian committed
11 12 13 14 15 16 17 18 19
	"gitlab.dms3.io/dms3/go-dms3/core/node/dms3p2p"
	"gitlab.dms3.io/dms3/go-dms3/core/node/helpers"
	"gitlab.dms3.io/dms3/go-dms3/repo"

	ds "gitlab.dms3.io/dms3/go-datastore"
	dsync "gitlab.dms3.io/dms3/go-datastore/sync"
	cfg "gitlab.dms3.io/dms3/go-dms3-config"
	ci "gitlab.dms3.io/p2p/go-p2p-core/crypto"
	peer "gitlab.dms3.io/p2p/go-p2p-core/peer"
Łukasz Magiera's avatar
Łukasz Magiera committed
20 21 22 23 24 25
)

type BuildCfg struct {
	// If online is set, the node will have networking enabled
	Online bool

tavit ohanian's avatar
tavit ohanian committed
26
	// ExtraOpts is a map of extra options used to configure the dms3 nodes creation
Łukasz Magiera's avatar
Łukasz Magiera committed
27 28 29 30 31 32 33 34 35 36 37 38 39
	ExtraOpts map[string]bool

	// If permanent then node should run more expensive processes
	// that will improve performance in long run
	Permanent bool

	// DisableEncryptedConnections disables connection encryption *entirely*.
	// DO NOT SET THIS UNLESS YOU'RE TESTING.
	DisableEncryptedConnections bool

	// If NilRepo is set, a Repo backed by a nil datastore will be constructed
	NilRepo bool

tavit ohanian's avatar
tavit ohanian committed
40 41
	Routing dms3p2p.RoutingOption
	Host    dms3p2p.HostOption
Łukasz Magiera's avatar
Łukasz Magiera committed
42 43 44 45 46 47 48 49 50 51
	Repo    repo.Repo
}

func (cfg *BuildCfg) getOpt(key string) bool {
	if cfg.ExtraOpts == nil {
		return false
	}

	return cfg.ExtraOpts[key]
}
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

func (cfg *BuildCfg) fillDefaults() error {
	if cfg.Repo != nil && cfg.NilRepo {
		return errors.New("cannot set a Repo and specify nilrepo at the same time")
	}

	if cfg.Repo == nil {
		var d ds.Datastore
		if cfg.NilRepo {
			d = ds.NewNullDatastore()
		} else {
			d = ds.NewMapDatastore()
		}
		r, err := defaultRepo(dsync.MutexWrap(d))
		if err != nil {
			return err
		}
		cfg.Repo = r
	}

	if cfg.Routing == nil {
tavit ohanian's avatar
tavit ohanian committed
73
		cfg.Routing = dms3p2p.DHTOption
74 75 76
	}

	if cfg.Host == nil {
tavit ohanian's avatar
tavit ohanian committed
77
		cfg.Host = dms3p2p.DefaultHostOption
78 79 80 81 82
	}

	return nil
}

83
// options creates fx option group from this build config
84
func (cfg *BuildCfg) options(ctx context.Context) (fx.Option, *cfg.Config) {
85 86
	err := cfg.fillDefaults()
	if err != nil {
87
		return fx.Error(err), nil
88 89 90 91 92 93 94 95 96 97 98 99
	}

	repoOption := fx.Provide(func(lc fx.Lifecycle) repo.Repo {
		lc.Append(fx.Hook{
			OnStop: func(ctx context.Context) error {
				return cfg.Repo.Close()
			},
		})

		return cfg.Repo
	})

100 101
	metricsCtx := fx.Provide(func() helpers.MetricsCtx {
		return helpers.MetricsCtx(ctx)
102 103
	})

tavit ohanian's avatar
tavit ohanian committed
104
	hostOption := fx.Provide(func() dms3p2p.HostOption {
105 106 107
		return cfg.Host
	})

tavit ohanian's avatar
tavit ohanian committed
108
	routingOption := fx.Provide(func() dms3p2p.RoutingOption {
109 110 111
		return cfg.Routing
	})

112 113 114 115 116
	conf, err := cfg.Repo.Config()
	if err != nil {
		return fx.Error(err), nil
	}

117 118 119 120 121
	return fx.Options(
		repoOption,
		hostOption,
		routingOption,
		metricsCtx,
122
	), conf
123 124
}

125 126
func defaultRepo(dstore repo.Datastore) (repo.Repo, error) {
	c := cfg.Config{}
127
	priv, pub, err := ci.GenerateKeyPairWithReader(ci.RSA, 2048, rand.Reader)
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	if err != nil {
		return nil, err
	}

	pid, err := peer.IDFromPublicKey(pub)
	if err != nil {
		return nil, err
	}

	privkeyb, err := priv.Bytes()
	if err != nil {
		return nil, err
	}

	c.Bootstrap = cfg.DefaultBootstrapAddresses
143
	c.Addresses.Swarm = []string{"/ip4/0.0.0.0/tcp/4001", "/ip4/0.0.0.0/udp/4001/quic"}
144 145 146 147 148 149 150 151
	c.Identity.PeerID = pid.Pretty()
	c.Identity.PrivKey = base64.StdEncoding.EncodeToString(privkeyb)

	return &repo.Mock{
		D: dstore,
		C: c,
	}, nil
}