2019-06-29 09:19:06 +00:00
|
|
|
package node
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-07-04 15:50:48 +00:00
|
|
|
"errors"
|
|
|
|
"github.com/filecoin-project/go-lotus/node/config"
|
|
|
|
"github.com/ipfs/go-datastore"
|
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peerstore"
|
|
|
|
"github.com/libp2p/go-libp2p-core/routing"
|
|
|
|
record "github.com/libp2p/go-libp2p-record"
|
2019-07-01 10:18:00 +00:00
|
|
|
"time"
|
2019-06-29 09:19:06 +00:00
|
|
|
|
2019-07-01 10:18:00 +00:00
|
|
|
ci "github.com/libp2p/go-libp2p-core/crypto"
|
2019-06-29 09:19:06 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2019-07-01 10:18:00 +00:00
|
|
|
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
|
2019-06-29 09:19:06 +00:00
|
|
|
"go.uber.org/fx"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-lotus/api"
|
|
|
|
"github.com/filecoin-project/go-lotus/build"
|
|
|
|
"github.com/filecoin-project/go-lotus/node/modules"
|
2019-07-01 10:18:00 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/node/modules/helpers"
|
2019-07-02 12:40:25 +00:00
|
|
|
"github.com/filecoin-project/go-lotus/node/modules/lp2p"
|
2019-06-29 09:19:06 +00:00
|
|
|
)
|
|
|
|
|
2019-07-04 15:50:48 +00:00
|
|
|
// special is a type used to give keys to modules which
|
|
|
|
// can't really be identified by the returned type
|
|
|
|
type special struct{ id int }
|
|
|
|
|
|
|
|
var (
|
|
|
|
DefaultTransportsKey = special{0} // Libp2p option
|
|
|
|
PNetKey = special{1} // Option + multiret
|
|
|
|
DiscoveryHandlerKey = special{2} // Private type
|
|
|
|
AddrsFactoryKey = special{3} // Libp2p option
|
|
|
|
SmuxTransportKey = special{4} // Libp2p option
|
|
|
|
RelayKey = special{5} // Libp2p option
|
|
|
|
SecurityKey = special{6} // Libp2p option
|
|
|
|
BaseRoutingKey = special{7} // fx groups + multiret
|
|
|
|
NatPortMapKey = special{8} // Libp2p option
|
|
|
|
ConnectionManagerKey = special{9} // Libp2p option
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
type invoke int
|
|
|
|
|
|
|
|
const (
|
|
|
|
PstoreAddSelfKeysKey = invoke(iota)
|
|
|
|
StartListeningKey
|
|
|
|
|
|
|
|
_nInvokes // keep this last
|
|
|
|
)
|
|
|
|
|
|
|
|
type settings struct {
|
|
|
|
modules map[interface{}]fx.Option
|
|
|
|
|
|
|
|
// invokes are separate from modules as they can't be referenced by return
|
|
|
|
// type, and must be applied in correct order
|
|
|
|
invokes []fx.Option
|
|
|
|
|
|
|
|
online bool // Online option applied
|
|
|
|
config bool // Config option applied
|
|
|
|
}
|
|
|
|
|
|
|
|
var defConf = config.Default()
|
|
|
|
|
|
|
|
var defaults = []Option{
|
|
|
|
Override(new(helpers.MetricsCtx), context.Background),
|
|
|
|
|
|
|
|
randomIdentity(),
|
|
|
|
|
|
|
|
Override(new(datastore.Batching), datastore.NewMapDatastore),
|
|
|
|
Override(new(record.Validator), modules.RecordValidator),
|
|
|
|
}
|
|
|
|
|
|
|
|
func Online() Option {
|
|
|
|
return Options(
|
|
|
|
func(s *settings) error { s.online = true; return nil },
|
|
|
|
applyIf(func(s *settings) bool { return s.config },
|
|
|
|
Error(errors.New("the Online option must be set before Config option")),
|
|
|
|
),
|
|
|
|
|
|
|
|
Override(new(peerstore.Peerstore), pstoremem.NewPeerstore),
|
|
|
|
|
|
|
|
Override(DefaultTransportsKey, lp2p.DefaultTransports),
|
|
|
|
Override(PNetKey, lp2p.PNet),
|
|
|
|
|
|
|
|
Override(new(lp2p.RawHost), lp2p.Host),
|
|
|
|
Override(new(host.Host), lp2p.RoutedHost),
|
|
|
|
Override(new(lp2p.BaseIpfsRouting), lp2p.DHTRouting(false)),
|
|
|
|
|
|
|
|
Override(DiscoveryHandlerKey, lp2p.DiscoveryHandler),
|
|
|
|
Override(AddrsFactoryKey, lp2p.AddrsFactory(nil, nil)),
|
|
|
|
Override(SmuxTransportKey, lp2p.SmuxTransport(true)),
|
|
|
|
Override(RelayKey, lp2p.Relay(true, false)),
|
|
|
|
Override(SecurityKey, lp2p.Security(true, false)),
|
|
|
|
|
|
|
|
Override(BaseRoutingKey, lp2p.BaseRouting),
|
|
|
|
Override(new(routing.Routing), lp2p.Routing),
|
|
|
|
|
|
|
|
Override(NatPortMapKey, lp2p.NatPortMap),
|
|
|
|
Override(ConnectionManagerKey, lp2p.ConnectionManager(50, 200, 20*time.Second)),
|
|
|
|
|
|
|
|
Override(PstoreAddSelfKeysKey, lp2p.PstoreAddSelfKeys),
|
|
|
|
Override(StartListeningKey, lp2p.StartListening(defConf.Libp2p.ListenAddresses)),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Config(cfg *config.Root) Option {
|
|
|
|
return Options(
|
|
|
|
func(s *settings) error { s.config = true; return nil },
|
|
|
|
|
|
|
|
applyIf(func(s *settings) bool { return s.online },
|
|
|
|
Override(StartListeningKey, lp2p.StartListening(cfg.Libp2p.ListenAddresses)),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
// New builds and starts new Filecoin node
|
2019-07-04 15:50:48 +00:00
|
|
|
func New(ctx context.Context, opts ...Option) (api.API, error) {
|
2019-07-02 13:05:43 +00:00
|
|
|
var resAPI api.Struct
|
2019-07-04 15:50:48 +00:00
|
|
|
settings := settings{
|
|
|
|
modules: map[interface{}]fx.Option{},
|
|
|
|
invokes: make([]fx.Option, _nInvokes),
|
|
|
|
}
|
2019-06-29 09:19:06 +00:00
|
|
|
|
2019-07-04 15:50:48 +00:00
|
|
|
if err := Options(Options(defaults...), Options(opts...))(&settings); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ctors := make([]fx.Option, 0, len(settings.modules))
|
|
|
|
for _, opt := range settings.modules {
|
|
|
|
ctors = append(ctors, opt)
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill holes in invokes
|
|
|
|
for i, opt := range settings.invokes {
|
|
|
|
if opt == nil {
|
|
|
|
settings.invokes[i] = fx.Options()
|
|
|
|
}
|
|
|
|
}
|
2019-07-01 10:18:00 +00:00
|
|
|
|
2019-06-29 09:19:06 +00:00
|
|
|
app := fx.New(
|
2019-07-04 15:50:48 +00:00
|
|
|
fx.Options(ctors...),
|
|
|
|
fx.Options(settings.invokes...),
|
2019-06-29 09:19:06 +00:00
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
fx.Invoke(versionAPI(&resAPI.Internal.Version)),
|
|
|
|
fx.Invoke(idAPI(&resAPI.Internal.ID)),
|
2019-06-29 09:19:06 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if err := app.Start(ctx); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
return &resAPI, nil
|
2019-06-29 09:19:06 +00:00
|
|
|
}
|
|
|
|
|
2019-07-01 10:18:00 +00:00
|
|
|
// In-memory / testing
|
|
|
|
|
2019-07-04 15:50:48 +00:00
|
|
|
func randomIdentity() Option {
|
2019-07-01 10:18:00 +00:00
|
|
|
sk, pk, err := ci.GenerateKeyPair(ci.RSA, 512)
|
|
|
|
if err != nil {
|
2019-07-04 15:50:48 +00:00
|
|
|
return Error(err)
|
2019-07-01 10:18:00 +00:00
|
|
|
}
|
|
|
|
|
2019-07-04 15:50:48 +00:00
|
|
|
return Options(
|
|
|
|
Override(new(ci.PrivKey), sk),
|
|
|
|
Override(new(ci.PubKey), pk),
|
|
|
|
Override(new(peer.ID), peer.IDFromPublicKey),
|
2019-07-01 10:18:00 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// API IMPL
|
|
|
|
|
2019-06-29 09:19:06 +00:00
|
|
|
// TODO: figure out a better way, this isn't usable in long term
|
2019-07-02 13:05:43 +00:00
|
|
|
func idAPI(set *func(ctx context.Context) (peer.ID, error)) func(id peer.ID) {
|
2019-06-29 09:19:06 +00:00
|
|
|
return func(id peer.ID) {
|
|
|
|
*set = func(ctx context.Context) (peer.ID, error) {
|
|
|
|
return id, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
func versionAPI(set *func(context.Context) (api.Version, error)) func() {
|
2019-06-29 09:19:06 +00:00
|
|
|
return func() {
|
|
|
|
*set = func(context.Context) (api.Version, error) {
|
|
|
|
return api.Version{
|
|
|
|
Version: build.Version,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|