From 09ce7363f7a914d1eb6b9db9a1be83b9f6caf076 Mon Sep 17 00:00:00 2001 From: rene <41963722+renaynay@users.noreply.github.com> Date: Mon, 29 May 2023 18:30:19 +0200 Subject: [PATCH 1/2] feat(libs/idstore): implement peer ID store Co-authored-by: derrandz --- libs/pidstore/pidstore.go | 67 ++++++++++++++++++++++++++++++++++ libs/pidstore/pidstore_test.go | 59 ++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 libs/pidstore/pidstore.go create mode 100644 libs/pidstore/pidstore_test.go diff --git a/libs/pidstore/pidstore.go b/libs/pidstore/pidstore.go new file mode 100644 index 0000000000..c5926827c5 --- /dev/null +++ b/libs/pidstore/pidstore.go @@ -0,0 +1,67 @@ +package pidstore + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/namespace" + logging "github.com/ipfs/go-log/v2" + "github.com/libp2p/go-libp2p/core/peer" +) + +var ( + storePrefix = datastore.NewKey("pidstore") + peersKey = datastore.NewKey("peers") + + log = logging.Logger("pidstore") +) + +// PeerIDStore is used to store/load peers to/from disk. +type PeerIDStore struct { + ds datastore.Datastore +} + +// NewPeerIDStore creates a new peer ID store backed by the given datastore. +func NewPeerIDStore(ds datastore.Datastore) *PeerIDStore { + return &PeerIDStore{ + ds: namespace.Wrap(ds, storePrefix), + } +} + +// Load loads the peers from datastore and returns them. +func (p *PeerIDStore) Load(ctx context.Context) ([]peer.ID, error) { + log.Debug("Loading peers") + + bin, err := p.ds.Get(ctx, peersKey) + if err != nil { + return nil, fmt.Errorf("pidstore: loading peers from datastore: %w", err) + } + + var peers []peer.ID + err = json.Unmarshal(bin, &peers) + if err != nil { + return nil, fmt.Errorf("pidstore: unmarshalling peer IDs: %w", err) + } + + log.Info("Loaded peers from disk", "amount", len(peers)) + return peers, nil +} + +// Put persists the given peer IDs to the datastore. +func (p *PeerIDStore) Put(ctx context.Context, peers []peer.ID) error { + log.Debug("Persisting peers to disk", "amount", len(peers)) + + bin, err := json.Marshal(peers) + if err != nil { + return fmt.Errorf("pidstore: marshal peerlist: %w", err) + } + + if err = p.ds.Put(ctx, peersKey, bin); err != nil { + return fmt.Errorf("pidstore:: error writing to datastore: %w", err) + } + + log.Info("Persisted peers successfully", "amount", len(peers)) + return nil +} diff --git a/libs/pidstore/pidstore_test.go b/libs/pidstore/pidstore_test.go new file mode 100644 index 0000000000..eafceff3fe --- /dev/null +++ b/libs/pidstore/pidstore_test.go @@ -0,0 +1,59 @@ +package pidstore + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "testing" + "time" + + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/sync" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPutLoad(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer t.Cleanup(cancel) + + peerstore := NewPeerIDStore(sync.MutexWrap(datastore.NewMapDatastore())) + + ids, err := generateRandomPeerList(10) + require.NoError(t, err) + + err = peerstore.Put(ctx, ids) + require.NoError(t, err) + + retrievedPeerlist, err := peerstore.Load(ctx) + require.NoError(t, err) + + assert.Equal(t, len(ids), len(retrievedPeerlist)) + assert.Equal(t, ids, retrievedPeerlist) +} + +func generateRandomPeerList(length int) ([]peer.ID, error) { + peerlist := make([]peer.ID, length) + for i := range peerlist { + key, err := rsa.GenerateKey(rand.Reader, 2096) + if err != nil { + return nil, err + } + + _, pubkey, err := crypto.KeyPairFromStdKey(key) + if err != nil { + return nil, err + } + + peerID, err := peer.IDFromPublicKey(pubkey) + if err != nil { + return nil, err + } + + peerlist[i] = peerID + } + + return peerlist, nil +} From 778958a4b50b6616a81de8930a84f4c0bc278e97 Mon Sep 17 00:00:00 2001 From: rene <41963722+renaynay@users.noreply.github.com> Date: Tue, 30 May 2023 11:54:26 +0200 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Hlib Kanunnikov --- libs/pidstore/pidstore.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/pidstore/pidstore.go b/libs/pidstore/pidstore.go index c5926827c5..2d4eb870a8 100644 --- a/libs/pidstore/pidstore.go +++ b/libs/pidstore/pidstore.go @@ -45,13 +45,13 @@ func (p *PeerIDStore) Load(ctx context.Context) ([]peer.ID, error) { return nil, fmt.Errorf("pidstore: unmarshalling peer IDs: %w", err) } - log.Info("Loaded peers from disk", "amount", len(peers)) + log.Infow("Loaded peers from disk", "amount", len(peers)) return peers, nil } // Put persists the given peer IDs to the datastore. func (p *PeerIDStore) Put(ctx context.Context, peers []peer.ID) error { - log.Debug("Persisting peers to disk", "amount", len(peers)) + log.Debugw("Persisting peers to disk", "amount", len(peers)) bin, err := json.Marshal(peers) if err != nil { @@ -59,9 +59,9 @@ func (p *PeerIDStore) Put(ctx context.Context, peers []peer.ID) error { } if err = p.ds.Put(ctx, peersKey, bin); err != nil { - return fmt.Errorf("pidstore:: error writing to datastore: %w", err) + return fmt.Errorf("pidstore: error writing to datastore: %w", err) } - log.Info("Persisted peers successfully", "amount", len(peers)) + log.Infow("Persisted peers successfully", "amount", len(peers)) return nil }