From 153453659018126ccd2ff15a67c1e8178263f52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 3 Oct 2019 02:02:06 +0200 Subject: [PATCH] Store libp2p key in keystore --- build/paramfetch.go | 2 +- cmd/lotus-storage-miner/init.go | 30 ++++++++++++++++++- node/builder.go | 6 +--- node/modules/lp2p/libp2p.go | 41 +++++++++++++++++++++++++ node/node_test.go | 18 +++++++++-- node/repo/fsrepo.go | 53 --------------------------------- node/repo/interface.go | 4 --- node/repo/memrepo.go | 33 ++------------------ node/repo/repo_test.go | 4 --- 9 files changed, 91 insertions(+), 100 deletions(-) diff --git a/build/paramfetch.go b/build/paramfetch.go index 8e4b2079f..7816a2cca 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -27,7 +27,7 @@ type paramFile struct { } func GetParams(storage bool) error { - if err := os.Mkdir(paramdir, 0755); err != nil { + if err := os.Mkdir(paramdir, 0755); err != nil && !os.IsExist(err) { return err } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 7f7d1ce9b..03c61f9fe 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -2,6 +2,8 @@ package main import ( "context" + "crypto/rand" + "github.com/libp2p/go-libp2p-core/crypto" "github.com/ipfs/go-datastore" "github.com/libp2p/go-libp2p-core/peer" @@ -101,7 +103,7 @@ var initCmd = &cli.Command{ log.Info("Initializing libp2p identity") - p2pSk, err := lr.Libp2pIdentity() + p2pSk, err := makeHostKey(lr) if err != nil { return err } @@ -147,6 +149,32 @@ var initCmd = &cli.Command{ }, } +func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) { + pk, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, err + } + + ks, err := lr.KeyStore() + if err != nil { + return nil, err + } + + kbytes, err := pk.Bytes() + if err != nil { + return nil, err + } + + if err := ks.Put("libp2p-host", types.KeyInfo{ + Type: "libp2p-host", + PrivateKey: kbytes, + }); err != nil { + return nil, err + } + + return pk, nil +} + func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID, genmine bool) error { if genmine { log.Warn("Starting genesis mining. This shouldn't happen when connecting to the real network.") diff --git a/node/builder.go b/node/builder.go index db0ee64f0..39198a8ed 100644 --- a/node/builder.go +++ b/node/builder.go @@ -302,10 +302,6 @@ func Repo(r repo.Repo) Option { if err != nil { return Error(err) } - pk, err := lr.Libp2pIdentity() - if err != nil { - return Error(err) - } return Options( Config(cfg), @@ -318,7 +314,7 @@ func Repo(r repo.Repo) Option { Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore), Override(new(dtypes.ClientDAG), modules.ClientDAG), - Override(new(ci.PrivKey), pk), + Override(new(ci.PrivKey), lp2p.PrivKey), Override(new(ci.PubKey), ci.PrivKey.GetPublic), Override(new(peer.ID), peer.IDFromPublicKey), diff --git a/node/modules/lp2p/libp2p.go b/node/modules/lp2p/libp2p.go index eb6aee27f..c68796f57 100644 --- a/node/modules/lp2p/libp2p.go +++ b/node/modules/lp2p/libp2p.go @@ -1,6 +1,10 @@ package lp2p import ( + "crypto/rand" + "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/node/repo" + "golang.org/x/xerrors" "time" logging "github.com/ipfs/go-log" @@ -14,12 +18,49 @@ import ( 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, repo.ErrKeyNotFound) { + 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 int, grace time.Duration) func() (opts Libp2pOpts, err error) { diff --git a/node/node_test.go b/node/node_test.go index 57870052b..7466cfd02 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -3,6 +3,8 @@ package node_test import ( "bytes" "context" + "crypto/rand" + "github.com/libp2p/go-libp2p-core/crypto" "io/ioutil" "net/http/httptest" "os" @@ -34,7 +36,19 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a lr, err := r.Lock() require.NoError(t, err) - p2pSk, err := lr.Libp2pIdentity() + pk, _, err := crypto.GenerateEd25519Key(rand.Reader) + require.NoError(t, err) + + ks, err := lr.KeyStore() + require.NoError(t, err) + + kbytes, err := pk.Bytes() + require.NoError(t, err) + + err = ks.Put("libp2p-host", types.KeyInfo{ + Type: "libp2p-host", + PrivateKey: kbytes, + }) require.NoError(t, err) ds, err := lr.Datastore("/metadata") @@ -45,7 +59,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a err = lr.Close() require.NoError(t, err) - peerid, err := peer.IDFromPrivateKey(p2pSk) + peerid, err := peer.IDFromPrivateKey(pk) require.NoError(t, err) enc, err := actors.SerializeParams(&actors.UpdatePeerIDParams{PeerID: peerid}) diff --git a/node/repo/fsrepo.go b/node/repo/fsrepo.go index ad3a43388..611f57d7b 100644 --- a/node/repo/fsrepo.go +++ b/node/repo/fsrepo.go @@ -14,7 +14,6 @@ import ( badger "github.com/ipfs/go-ds-badger" fslock "github.com/ipfs/go-fs-lock" logging "github.com/ipfs/go-log" - "github.com/libp2p/go-libp2p-core/crypto" "github.com/mitchellh/go-homedir" "github.com/multiformats/go-base32" "github.com/multiformats/go-multiaddr" @@ -224,58 +223,6 @@ func (fsr *fsLockedRepo) Config() (*config.Root, error) { return config.FromFile(fsr.join(fsConfig)) } -func (fsr *fsLockedRepo) Libp2pIdentity() (crypto.PrivKey, error) { - if err := fsr.stillValid(); err != nil { - return nil, err - } - kpath := fsr.join(fsLibp2pKey) - stat, err := os.Stat(kpath) - - if os.IsNotExist(err) { - pk, err := genLibp2pKey() - if err != nil { - return nil, xerrors.Errorf("could not generate private key: %w", err) - } - pkb, err := pk.Bytes() - if err != nil { - return nil, xerrors.Errorf("could not serialize private key: %w", err) - } - err = ioutil.WriteFile(kpath, pkb, 0600) - if err != nil { - return nil, xerrors.Errorf("could not write private key: %w", err) - } - } else if err != nil { - return nil, err - } - - stat, err = os.Stat(kpath) - if err != nil { - return nil, err - } - - if stat.Mode()&0066 != 0 { - return nil, xerrors.New("libp2p identity has too wide access permissions, " + - fsLibp2pKey + " should have permission 0600") - } - - f, err := os.Open(kpath) - if err != nil { - return nil, xerrors.Errorf("could not open private key file: %w", err) - } - defer f.Close() //nolint: errcheck // read-only op - - pkbytes, err := ioutil.ReadAll(f) - if err != nil { - return nil, xerrors.Errorf("could not read private key file: %w", err) - } - - pk, err := crypto.UnmarshalPrivateKey(pkbytes) - if err != nil { - return nil, xerrors.Errorf("could not unmarshal private key: %w", err) - } - return pk, nil -} - func (fsr *fsLockedRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error { if err := fsr.stillValid(); err != nil { return err diff --git a/node/repo/interface.go b/node/repo/interface.go index bb1bb15ea..9ec3a263a 100644 --- a/node/repo/interface.go +++ b/node/repo/interface.go @@ -4,7 +4,6 @@ import ( "errors" "github.com/ipfs/go-datastore" - "github.com/libp2p/go-libp2p-core/crypto" "github.com/multiformats/go-multiaddr" "github.com/filecoin-project/go-lotus/chain/types" @@ -42,9 +41,6 @@ type LockedRepo interface { // Returns config in this repo Config() (*config.Root, error) - // Libp2pIdentity returns private key for libp2p indentity - Libp2pIdentity() (crypto.PrivKey, error) - // SetAPIEndpoint sets the endpoint of the current API // so it can be read by API clients SetAPIEndpoint(multiaddr.Multiaddr) error diff --git a/node/repo/memrepo.go b/node/repo/memrepo.go index 6ea85ca71..8441b9013 100644 --- a/node/repo/memrepo.go +++ b/node/repo/memrepo.go @@ -1,13 +1,11 @@ package repo import ( - "crypto/rand" "sync" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" dssync "github.com/ipfs/go-datastore/sync" - "github.com/libp2p/go-libp2p-core/crypto" "github.com/multiformats/go-multiaddr" "golang.org/x/xerrors" @@ -27,7 +25,6 @@ type MemRepo struct { datastore datastore.Datastore configF func() *config.Root - libp2pKey crypto.PrivKey keystore map[string]types.KeyInfo } @@ -46,18 +43,9 @@ var _ Repo = &MemRepo{} // MemRepoOptions contains options for memory repo type MemRepoOptions struct { - Ds datastore.Datastore - ConfigF func() *config.Root - Libp2pKey crypto.PrivKey - KeyStore map[string]types.KeyInfo -} - -func genLibp2pKey() (crypto.PrivKey, error) { - pk, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return nil, err - } - return pk, nil + Ds datastore.Datastore + ConfigF func() *config.Root + KeyStore map[string]types.KeyInfo } // NewMemory creates new memory based repo with provided options. @@ -73,13 +61,6 @@ func NewMemory(opts *MemRepoOptions) *MemRepo { if opts.Ds == nil { opts.Ds = dssync.MutexWrap(datastore.NewMapDatastore()) } - if opts.Libp2pKey == nil { - pk, err := genLibp2pKey() - if err != nil { - panic(err) - } - opts.Libp2pKey = pk - } if opts.KeyStore == nil { opts.KeyStore = make(map[string]types.KeyInfo) } @@ -89,7 +70,6 @@ func NewMemory(opts *MemRepoOptions) *MemRepo { datastore: opts.Ds, configF: opts.ConfigF, - libp2pKey: opts.Libp2pKey, keystore: opts.KeyStore, } } @@ -170,13 +150,6 @@ func (lmem *lockedMemRepo) Config() (*config.Root, error) { return lmem.mem.configF(), nil } -func (lmem *lockedMemRepo) Libp2pIdentity() (crypto.PrivKey, error) { - if err := lmem.checkToken(); err != nil { - return nil, err - } - return lmem.mem.libp2pKey, nil -} - func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error { if err := lmem.checkToken(); err != nil { return err diff --git a/node/repo/repo_test.go b/node/repo/repo_test.go index d12c5e953..a939ef462 100644 --- a/node/repo/repo_test.go +++ b/node/repo/repo_test.go @@ -47,10 +47,6 @@ func basicTest(t *testing.T, repo Repo) { assert.NoError(t, err, "setting multiaddr shouldn't error") assert.Equal(t, ma, apima, "returned API multiaddr should be the same") - iden, err := lrepo.Libp2pIdentity() - assert.NotNil(t, iden, "identity is not nil") - assert.NoError(t, err, "identity should not error") - cfg, err := lrepo.Config() assert.Equal(t, config.Default(), cfg, "there should be a default config") assert.NoError(t, err, "config should not error")