package lp2p import ( "crypto/rand" "time" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "golang.org/x/xerrors" logging "github.com/ipfs/go-log" "github.com/libp2p/go-libp2p" connmgr "github.com/libp2p/go-libp2p-connmgr" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" "go.uber.org/fx" ) var log = logging.Logger("p2pnode") const kstorePrivkey = "libp2p-host" type Libp2pOpts struct { fx.Out Opts []libp2p.Option `group:"libp2p"` } func PrivKey(ks types.KeyStore) (crypto.PrivKey, error) { k, err := ks.Get(kstorePrivkey) if err == nil { return crypto.UnmarshalPrivateKey(k.PrivateKey) } if !xerrors.Is(err, types.ErrKeyInfoNotFound) { return nil, err } pk, err := genLibp2pKey() if err != nil { return nil, err } kbytes, err := pk.Bytes() if err != nil { return nil, err } if err := ks.Put(kstorePrivkey, types.KeyInfo{ Type: kstorePrivkey, PrivateKey: kbytes, }); err != nil { return nil, err } return pk, nil } func genLibp2pKey() (crypto.PrivKey, error) { pk, _, err := crypto.GenerateEd25519Key(rand.Reader) if err != nil { return nil, err } return pk, nil } // Misc options func ConnectionManager(low, high uint, grace time.Duration, protected []string) func() (opts Libp2pOpts, err error) { return func() (Libp2pOpts, error) { cm := connmgr.NewConnManager(int(low), int(high), grace) for _, p := range protected { pid, err := peer.IDFromString(p) if err != nil { return Libp2pOpts{}, xerrors.Errorf("failed to parse peer ID in protected peers array: %w", err) } cm.Protect(pid, "config-prot") } infos, err := build.BuiltinBootstrap() if err != nil { return Libp2pOpts{}, xerrors.Errorf("failed to get bootstrap peers: %w", err) } for _, inf := range infos { cm.Protect(inf.ID, "bootstrap") } return Libp2pOpts{ Opts: []libp2p.Option{libp2p.ConnectionManager(cm)}, }, nil } } func PstoreAddSelfKeys(id peer.ID, sk crypto.PrivKey, ps peerstore.Peerstore) error { if err := ps.AddPubKey(id, sk.GetPublic()); err != nil { return err } return ps.AddPrivKey(id, sk) } func simpleOpt(opt libp2p.Option) func() (opts Libp2pOpts, err error) { return func() (opts Libp2pOpts, err error) { opts.Opts = append(opts.Opts, opt) return } }