Merge pull request #263 from filecoin-project/feat/libp2p-in-kstore

Store libp2p key in keystore
This commit is contained in:
Łukasz Magiera 2019-10-03 02:18:11 +02:00 committed by GitHub
commit 77835636b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 100 deletions

View File

@ -27,7 +27,7 @@ type paramFile struct {
} }
func GetParams(storage bool) error { 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 return err
} }

View File

@ -2,6 +2,8 @@ package main
import ( import (
"context" "context"
"crypto/rand"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -101,7 +103,7 @@ var initCmd = &cli.Command{
log.Info("Initializing libp2p identity") log.Info("Initializing libp2p identity")
p2pSk, err := lr.Libp2pIdentity() p2pSk, err := makeHostKey(lr)
if err != nil { if err != nil {
return err 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 { func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID, genmine bool) error {
if genmine { if genmine {
log.Warn("Starting genesis mining. This shouldn't happen when connecting to the real network.") log.Warn("Starting genesis mining. This shouldn't happen when connecting to the real network.")

View File

@ -302,10 +302,6 @@ func Repo(r repo.Repo) Option {
if err != nil { if err != nil {
return Error(err) return Error(err)
} }
pk, err := lr.Libp2pIdentity()
if err != nil {
return Error(err)
}
return Options( return Options(
Config(cfg), Config(cfg),
@ -318,7 +314,7 @@ func Repo(r repo.Repo) Option {
Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore), Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore),
Override(new(dtypes.ClientDAG), modules.ClientDAG), 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(ci.PubKey), ci.PrivKey.GetPublic),
Override(new(peer.ID), peer.IDFromPublicKey), Override(new(peer.ID), peer.IDFromPublicKey),

View File

@ -1,6 +1,10 @@
package lp2p package lp2p
import ( import (
"crypto/rand"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/node/repo"
"golang.org/x/xerrors"
"time" "time"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
@ -14,12 +18,49 @@ import (
var log = logging.Logger("p2pnode") var log = logging.Logger("p2pnode")
const kstorePrivkey = "libp2p-host"
type Libp2pOpts struct { type Libp2pOpts struct {
fx.Out fx.Out
Opts []libp2p.Option `group:"libp2p"` 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 // Misc options
func ConnectionManager(low, high int, grace time.Duration) func() (opts Libp2pOpts, err error) { func ConnectionManager(low, high int, grace time.Duration) func() (opts Libp2pOpts, err error) {

View File

@ -3,6 +3,8 @@ package node_test
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/rand"
"github.com/libp2p/go-libp2p-core/crypto"
"io/ioutil" "io/ioutil"
"net/http/httptest" "net/http/httptest"
"os" "os"
@ -34,7 +36,19 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
lr, err := r.Lock() lr, err := r.Lock()
require.NoError(t, err) 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) require.NoError(t, err)
ds, err := lr.Datastore("/metadata") ds, err := lr.Datastore("/metadata")
@ -45,7 +59,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
err = lr.Close() err = lr.Close()
require.NoError(t, err) require.NoError(t, err)
peerid, err := peer.IDFromPrivateKey(p2pSk) peerid, err := peer.IDFromPrivateKey(pk)
require.NoError(t, err) require.NoError(t, err)
enc, err := actors.SerializeParams(&actors.UpdatePeerIDParams{PeerID: peerid}) enc, err := actors.SerializeParams(&actors.UpdatePeerIDParams{PeerID: peerid})

View File

@ -14,7 +14,6 @@ import (
badger "github.com/ipfs/go-ds-badger" badger "github.com/ipfs/go-ds-badger"
fslock "github.com/ipfs/go-fs-lock" fslock "github.com/ipfs/go-fs-lock"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/multiformats/go-base32" "github.com/multiformats/go-base32"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
@ -224,58 +223,6 @@ func (fsr *fsLockedRepo) Config() (*config.Root, error) {
return config.FromFile(fsr.join(fsConfig)) 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 { func (fsr *fsLockedRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {
if err := fsr.stillValid(); err != nil { if err := fsr.stillValid(); err != nil {
return err return err

View File

@ -4,7 +4,6 @@ import (
"errors" "errors"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
@ -42,9 +41,6 @@ type LockedRepo interface {
// Returns config in this repo // Returns config in this repo
Config() (*config.Root, error) Config() (*config.Root, error)
// Libp2pIdentity returns private key for libp2p indentity
Libp2pIdentity() (crypto.PrivKey, error)
// SetAPIEndpoint sets the endpoint of the current API // SetAPIEndpoint sets the endpoint of the current API
// so it can be read by API clients // so it can be read by API clients
SetAPIEndpoint(multiaddr.Multiaddr) error SetAPIEndpoint(multiaddr.Multiaddr) error

View File

@ -1,13 +1,11 @@
package repo package repo
import ( import (
"crypto/rand"
"sync" "sync"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/namespace"
dssync "github.com/ipfs/go-datastore/sync" dssync "github.com/ipfs/go-datastore/sync"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -27,7 +25,6 @@ type MemRepo struct {
datastore datastore.Datastore datastore datastore.Datastore
configF func() *config.Root configF func() *config.Root
libp2pKey crypto.PrivKey
keystore map[string]types.KeyInfo keystore map[string]types.KeyInfo
} }
@ -46,18 +43,9 @@ var _ Repo = &MemRepo{}
// MemRepoOptions contains options for memory repo // MemRepoOptions contains options for memory repo
type MemRepoOptions struct { type MemRepoOptions struct {
Ds datastore.Datastore Ds datastore.Datastore
ConfigF func() *config.Root ConfigF func() *config.Root
Libp2pKey crypto.PrivKey KeyStore map[string]types.KeyInfo
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
} }
// NewMemory creates new memory based repo with provided options. // NewMemory creates new memory based repo with provided options.
@ -73,13 +61,6 @@ func NewMemory(opts *MemRepoOptions) *MemRepo {
if opts.Ds == nil { if opts.Ds == nil {
opts.Ds = dssync.MutexWrap(datastore.NewMapDatastore()) 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 { if opts.KeyStore == nil {
opts.KeyStore = make(map[string]types.KeyInfo) opts.KeyStore = make(map[string]types.KeyInfo)
} }
@ -89,7 +70,6 @@ func NewMemory(opts *MemRepoOptions) *MemRepo {
datastore: opts.Ds, datastore: opts.Ds,
configF: opts.ConfigF, configF: opts.ConfigF,
libp2pKey: opts.Libp2pKey,
keystore: opts.KeyStore, keystore: opts.KeyStore,
} }
} }
@ -170,13 +150,6 @@ func (lmem *lockedMemRepo) Config() (*config.Root, error) {
return lmem.mem.configF(), nil 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 { func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {
if err := lmem.checkToken(); err != nil { if err := lmem.checkToken(); err != nil {
return err return err

View File

@ -47,10 +47,6 @@ func basicTest(t *testing.T, repo Repo) {
assert.NoError(t, err, "setting multiaddr shouldn't error") assert.NoError(t, err, "setting multiaddr shouldn't error")
assert.Equal(t, ma, apima, "returned API multiaddr should be the same") 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() cfg, err := lrepo.Config()
assert.Equal(t, config.Default(), cfg, "there should be a default config") assert.Equal(t, config.Default(), cfg, "there should be a default config")
assert.NoError(t, err, "config should not error") assert.NoError(t, err, "config should not error")