Merge pull request #263 from filecoin-project/feat/libp2p-in-kstore
Store libp2p key in keystore
This commit is contained in:
commit
77835636b0
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.")
|
||||||
|
@ -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),
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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})
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user