forked from libp2p/go-libp2p-peerstore
-
Notifications
You must be signed in to change notification settings - Fork 0
/
keybook.go
134 lines (117 loc) · 3.64 KB
/
keybook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package pstoreds
import (
"context"
"errors"
base32 "github.com/whyrusleeping/base32"
ds "github.com/ipfs/go-datastore"
query "github.com/ipfs/go-datastore/query"
ic "github.com/libp2p/go-libp2p-crypto"
peer "github.com/libp2p/go-libp2p-peer"
pstore "github.com/libp2p/go-libp2p-peerstore"
)
// Public and private keys are stored under the following db key pattern:
// /peers/keys/<b32 peer id no padding>/{pub, priv}
var (
kbBase = ds.NewKey("/peers/keys")
pubSuffix = ds.NewKey("/pub")
privSuffix = ds.NewKey("/priv")
)
type dsKeyBook struct {
ds ds.TxnDatastore
}
var _ pstore.KeyBook = (*dsKeyBook)(nil)
func NewKeyBook(_ context.Context, store ds.TxnDatastore, _ Options) (pstore.KeyBook, error) {
return &dsKeyBook{store}, nil
}
func (kb *dsKeyBook) PubKey(p peer.ID) ic.PubKey {
key := kbBase.ChildString(base32.RawStdEncoding.EncodeToString([]byte(p))).Child(pubSuffix)
var pk ic.PubKey
if value, err := kb.ds.Get(key); err == nil {
pk, err = ic.UnmarshalPublicKey(value)
if err != nil {
log.Errorf("error when unmarshalling pubkey from datastore for peer %s: %s\n", p.Pretty(), err)
}
} else if err == ds.ErrNotFound {
pk, err = p.ExtractPublicKey()
switch err {
case nil:
case peer.ErrNoPublicKey:
return nil
default:
log.Errorf("error when extracting pubkey from peer ID for peer %s: %s\n", p.Pretty(), err)
return nil
}
pkb, err := pk.Bytes()
if err != nil {
log.Errorf("error when turning extracted pubkey into bytes for peer %s: %s\n", p.Pretty(), err)
return nil
}
err = kb.ds.Put(key, pkb)
if err != nil {
log.Errorf("error when adding extracted pubkey to peerstore for peer %s: %s\n", p.Pretty(), err)
return nil
}
} else {
log.Errorf("error when fetching pubkey from datastore for peer %s: %s\n", p.Pretty(), err)
}
return pk
}
func (kb *dsKeyBook) AddPubKey(p peer.ID, pk ic.PubKey) error {
// check it's correct.
if !p.MatchesPublicKey(pk) {
return errors.New("peer ID does not match public key")
}
key := kbBase.ChildString(base32.RawStdEncoding.EncodeToString([]byte(p))).Child(pubSuffix)
val, err := pk.Bytes()
if err != nil {
log.Errorf("error while converting pubkey byte string for peer %s: %s\n", p.Pretty(), err)
return err
}
err = kb.ds.Put(key, val)
if err != nil {
log.Errorf("error while updating pubkey in datastore for peer %s: %s\n", p.Pretty(), err)
}
return err
}
func (kb *dsKeyBook) PrivKey(p peer.ID) ic.PrivKey {
key := kbBase.ChildString(base32.RawStdEncoding.EncodeToString([]byte(p))).Child(privSuffix)
value, err := kb.ds.Get(key)
if err != nil {
log.Errorf("error while fetching privkey from datastore for peer %s: %s\n", p.Pretty(), err)
return nil
}
sk, err := ic.UnmarshalPrivateKey(value)
if err != nil {
return nil
}
return sk
}
func (kb *dsKeyBook) AddPrivKey(p peer.ID, sk ic.PrivKey) error {
if sk == nil {
return errors.New("private key is nil")
}
// check it's correct.
if !p.MatchesPrivateKey(sk) {
return errors.New("peer ID does not match private key")
}
key := kbBase.ChildString(base32.RawStdEncoding.EncodeToString([]byte(p))).Child(privSuffix)
val, err := sk.Bytes()
if err != nil {
log.Errorf("error while converting privkey byte string for peer %s: %s\n", p.Pretty(), err)
return err
}
err = kb.ds.Put(key, val)
if err != nil {
log.Errorf("error while updating privkey in datastore for peer %s: %s\n", p.Pretty(), err)
}
return err
}
func (kb *dsKeyBook) PeersWithKeys() peer.IDSlice {
ids, err := uniquePeerIds(kb.ds, kbBase, func(result query.Result) string {
return ds.RawKey(result.Key).Parent().Name()
})
if err != nil {
log.Errorf("error while retrieving peers with keys: %v", err)
}
return ids
}