coreapi: name/key review suggestions
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Dec 17, 2017 at 03:44 UTC
8df2d1a92eee8a1369e73aaa379c160d028bd3d4
5 files changed
+108
-69
core/coreapi/interface/interface.go
+26
-19
@@ -28,16 +28,21 @@ type Path interface {
28
type Node ipld.Node
29
type Link ipld.Link
30
31
-type IpnsEntry struct {
32
- Name string
33
- Value Path
34
-}
35
-
31
type Reader interface {
32
io.ReadSeeker
33
io.Closer
34
}
35
36
+type IpnsEntry interface {
37
+ Name() string
38
+ Value() Path
39
+}
40
+
41
+type Key interface {
42
+ Name() string
43
+ Path() Path
44
+}
45
+
46
// CoreAPI defines an unified interface to IPFS for Go programs.
47
type CoreAPI interface {
48
// Unixfs returns an implementation of Unixfs API
@@ -108,7 +113,7 @@ type DagAPI interface {
113
// You can use .Key API to list and generate more names and their respective keys.
114
type NameAPI interface {
115
// Publish announces new IPNS name
111
- Publish(ctx context.Context, path Path, opts ...options.NamePublishOption) (*IpnsEntry, error)
116
+ Publish(ctx context.Context, path Path, opts ...options.NamePublishOption) (IpnsEntry, error)
117
118
// WithValidTime is an option for Publish which specifies for how long the
119
// entry will remain valid. Default value is 24h
@@ -116,8 +121,9 @@ type NameAPI interface {
121
122
// WithKey is an option for Publish which specifies the key to use for
123
// publishing. Default value is "self" which is the node's own PeerID.
124
+ // The key parameter must be either PeerID or keystore key alias.
125
//
120
- // You can use .Key API to list and generate more names and their respective keys.
126
+ // You can use KeyAPI to list and generate more names and their respective keys.
127
WithKey(key string) options.NamePublishOption
128
129
// Resolve attempts to resolve the newest version of the specified name
@@ -131,41 +137,42 @@ type NameAPI interface {
137
// offline. Default value is false
138
WithLocal(local bool) options.NameResolveOption
139
134
- // WithNoCache is an option for Resolve which specifies when set to true
135
- // disables the use of local name cache. Default value is false
136
- WithNoCache(nocache bool) options.NameResolveOption
140
+ // WithCache is an option for Resolve which specifies if cache should be used.
141
+ // Default value is true
142
+ WithCache(cache bool) options.NameResolveOption
143
}
144
145
// KeyAPI specifies the interface to Keystore
146
type KeyAPI interface {
147
// Generate generates new key, stores it in the keystore under the specified
148
// name and returns a base58 encoded multihash of it's public key
143
- Generate(ctx context.Context, name string, opts ...options.KeyGenerateOption) (string, error)
149
+ Generate(ctx context.Context, name string, opts ...options.KeyGenerateOption) (Key, error)
150
151
// WithAlgorithm is an option for Generate which specifies which algorithm
146
- // should be used for the key. Default is "rsa"
152
+ // should be used for the key. Default is options.RSAKey
153
//
154
// Supported algorithms:
149
- // * rsa
150
- // * ed25519
155
+ // * options.RSAKey
156
+ // * options.Ed25519Key
157
WithAlgorithm(algorithm string) options.KeyGenerateOption
158
159
// WithSize is an option for Generate which specifies the size of the key to
160
// generated. Default is 0
161
WithSize(size int) options.KeyGenerateOption
162
157
- // Rename renames oldName key to newName.
158
- Rename(ctx context.Context, oldName string, newName string, opts ...options.KeyRenameOption) (string, bool, error)
163
+ // Rename renames oldName key to newName. Returns the key and whether another
164
+ // key was overwritten, or an error
165
+ Rename(ctx context.Context, oldName string, newName string, opts ...options.KeyRenameOption) (Key, bool, error)
166
167
// WithForce is an option for Rename which specifies whether to allow to
168
// replace existing keys.
169
WithForce(force bool) options.KeyRenameOption
170
171
// List lists keys stored in keystore
165
- List(ctx context.Context) (map[string]string, error) //TODO: better key type?
172
+ List(ctx context.Context) ([]Key, error)
173
167
- // Remove removes keys from keystore
168
- Remove(ctx context.Context, name string) (string, error)
174
+ // Remove removes keys from keystore. Returns ipns path of the removed key
175
+ Remove(ctx context.Context, name string) (Path, error)
176
}
177
178
// type ObjectAPI interface {
core/coreapi/interface/options/key.go
+6
-1
@@ -1,5 +1,10 @@
1
package options
2
3
+const (
4
+ RSAKey = "rsa"
5
+ Ed25519Key = "ed25519"
6
+)
7
+
8
type KeyGenerateSettings struct {
9
Algorithm string
10
Size int
@@ -14,7 +19,7 @@ type KeyRenameOption func(*KeyRenameSettings) error
19
20
func KeyGenerateOptions(opts ...KeyGenerateOption) (*KeyGenerateSettings, error) {
21
options := &KeyGenerateSettings{
17
- Algorithm: "rsa",
22
+ Algorithm: RSAKey,
23
Size: 0,
24
}
25
core/coreapi/interface/options/name.go
+9
-5
@@ -4,6 +4,10 @@ import (
4
"time"
5
)
6
7
+const (
8
+ DefaultNameValidTime = 24 * time.Hour
9
+)
10
+
11
type NamePublishSettings struct {
12
ValidTime time.Duration
13
Key string
@@ -12,7 +16,7 @@ type NamePublishSettings struct {
16
type NameResolveSettings struct {
17
Recursive bool
18
Local bool
15
- Nocache bool
19
+ Cache bool
20
}
21
22
type NamePublishOption func(*NamePublishSettings) error
@@ -20,7 +24,7 @@ type NameResolveOption func(*NameResolveSettings) error
24
25
func NamePublishOptions(opts ...NamePublishOption) (*NamePublishSettings, error) {
26
options := &NamePublishSettings{
23
- ValidTime: 24 * time.Hour,
27
+ ValidTime: DefaultNameValidTime,
28
Key: "self",
29
}
30
@@ -38,7 +42,7 @@ func NameResolveOptions(opts ...NameResolveOption) (*NameResolveSettings, error)
42
options := &NameResolveSettings{
43
Recursive: false,
44
Local: false,
41
- Nocache: false,
45
+ Cache: true,
46
}
47
48
for _, opt := range opts {
@@ -81,9 +85,9 @@ func (api *NameOptions) WithLocal(local bool) NameResolveOption {
85
}
86
}
87
84
-func (api *NameOptions) WithNoCache(nocache bool) NameResolveOption {
88
+func (api *NameOptions) WithCache(cache bool) NameResolveOption {
89
return func(settings *NameResolveSettings) error {
86
- settings.Nocache = nocache
90
+ settings.Cache = cache
91
return nil
92
}
93
}
core/coreapi/key.go
+47
-33
@@ -8,8 +8,9 @@ import (
8
9
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
10
caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11
+ ipfspath "github.com/ipfs/go-ipfs/path"
12
12
- peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
13
+ peer "gx/ipfs/QmWNY7dV54ZDYmTA1ykVdwNCqC11mpU4zSUp6XDpLTH9eG/go-libp2p-peer"
14
crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
15
)
16
@@ -18,10 +19,23 @@ type KeyAPI struct {
19
*caopts.KeyOptions
20
}
21
21
-func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (string, error) {
22
+type key struct {
23
+ name string
24
+ peerId string
25
+}
26
+
27
+func (k *key) Name() string {
28
+ return k.name
29
+}
30
+
31
+func (k *key) Path() coreiface.Path {
32
+ return &path{path: ipfspath.FromString(ipfspath.Join([]string{"/ipns/", k.peerId}))}
33
+}
34
+
35
+func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (coreiface.Key, error) {
36
options, err := caopts.KeyGenerateOptions(opts...)
37
if err != nil {
24
- return "", err
38
+ return nil, err
39
}
40
41
var sk crypto.PrivKey
@@ -30,12 +44,12 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key
44
switch options.Algorithm {
45
case "rsa":
46
if options.Size == 0 {
33
- return "", fmt.Errorf("please specify a key size with WithSize option")
47
+ return nil, fmt.Errorf("please specify a key size with WithSize option")
48
}
49
50
priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, options.Size, rand.Reader)
51
if err != nil {
38
- return "", err
52
+ return nil, err
53
}
54
55
sk = priv
@@ -43,29 +57,29 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key
57
case "ed25519":
58
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
59
if err != nil {
46
- return "", err
60
+ return nil, err
61
}
62
63
sk = priv
64
pk = pub
65
default:
52
- return "", fmt.Errorf("unrecognized key type: %s", options.Algorithm)
66
+ return nil, fmt.Errorf("unrecognized key type: %s", options.Algorithm)
67
}
68
69
err = api.node.Repo.Keystore().Put(name, sk)
70
if err != nil {
57
- return "", err
71
+ return nil, err
72
}
73
74
pid, err := peer.IDFromPublicKey(pk)
75
if err != nil {
62
- return "", err
76
+ return nil, err
77
}
78
65
- return pid.String(), nil
79
+ return &key{name, pid.String()}, nil
80
}
81
68
-func (api *KeyAPI) List(ctx context.Context) (map[string]string, error) {
82
+func (api *KeyAPI) List(ctx context.Context) ([]coreiface.Key, error) {
83
keys, err := api.node.Repo.Keystore().List()
84
if err != nil {
85
return nil, err
@@ -73,11 +87,11 @@ func (api *KeyAPI) List(ctx context.Context) (map[string]string, error) {
87
88
sort.Strings(keys)
89
76
- out := make(map[string]string, len(keys)+1)
77
- out["self"] = api.node.Identity.Pretty()
90
+ out := make([]coreiface.Key, len(keys)+1)
91
+ out[0] = &key{"self", api.node.Identity.Pretty()}
92
79
- for _, key := range keys {
80
- privKey, err := api.node.Repo.Keystore().Get(key)
93
+ for n, k := range keys {
94
+ privKey, err := api.node.Repo.Keystore().Get(k)
95
if err != nil {
96
return nil, err
97
}
@@ -89,88 +103,88 @@ func (api *KeyAPI) List(ctx context.Context) (map[string]string, error) {
103
return nil, err
104
}
105
92
- out[key] = pid.Pretty()
106
+ out[n+1] = &key{k, pid.Pretty()}
107
}
108
return out, nil
109
}
110
97
-func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, opts ...caopts.KeyRenameOption) (string, bool, error) {
111
+func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, opts ...caopts.KeyRenameOption) (coreiface.Key, bool, error) {
112
options, err := caopts.KeyRenameOptions(opts...)
99
- if newName == "self" {
100
- return "", false, err
113
+ if err != nil {
114
+ return nil, false, err
115
}
116
117
ks := api.node.Repo.Keystore()
118
119
if oldName == "self" {
106
- return "", false, fmt.Errorf("cannot rename key with name 'self'")
120
+ return nil, false, fmt.Errorf("cannot rename key with name 'self'")
121
}
122
123
if newName == "self" {
110
- return "", false, fmt.Errorf("cannot overwrite key with name 'self'")
124
+ return nil, false, fmt.Errorf("cannot overwrite key with name 'self'")
125
}
126
127
oldKey, err := ks.Get(oldName)
128
if err != nil {
115
- return "", false, fmt.Errorf("no key named %s was found", oldName)
129
+ return nil, false, fmt.Errorf("no key named %s was found", oldName)
130
}
131
132
pubKey := oldKey.GetPublic()
133
134
pid, err := peer.IDFromPublicKey(pubKey)
135
if err != nil {
122
- return "", false, err
136
+ return nil, false, err
137
}
138
139
overwrite := false
140
if options.Force {
141
exist, err := ks.Has(newName)
142
if err != nil {
129
- return "", false, err
143
+ return nil, false, err
144
}
145
146
if exist {
147
overwrite = true
148
err := ks.Delete(newName)
149
if err != nil {
136
- return "", false, err
150
+ return nil, false, err
151
}
152
}
153
}
154
155
err = ks.Put(newName, oldKey)
156
if err != nil {
143
- return "", false, err
157
+ return nil, false, err
158
}
159
146
- return pid.Pretty(), overwrite, ks.Delete(oldName)
160
+ return &key{newName, pid.Pretty()}, overwrite, ks.Delete(oldName)
161
}
162
149
-func (api *KeyAPI) Remove(ctx context.Context, name string) (string, error) {
163
+func (api *KeyAPI) Remove(ctx context.Context, name string) (coreiface.Path, error) {
164
ks := api.node.Repo.Keystore()
165
166
if name == "self" {
153
- return "", fmt.Errorf("cannot remove key with name 'self'")
167
+ return nil, fmt.Errorf("cannot remove key with name 'self'")
168
}
169
170
removed, err := ks.Get(name)
171
if err != nil {
158
- return "", fmt.Errorf("no key named %s was found", name)
172
+ return nil, fmt.Errorf("no key named %s was found", name)
173
}
174
175
pubKey := removed.GetPublic()
176
177
pid, err := peer.IDFromPublicKey(pubKey)
178
if err != nil {
165
- return "", err
179
+ return nil, err
180
}
181
182
err = ks.Delete(name)
183
if err != nil {
170
- return "", err
184
+ return nil, err
185
}
186
173
- return pid.Pretty(), nil
187
+ return (&key{"", pid.Pretty()}).Path(), nil
188
}
189
190
func (api *KeyAPI) core() coreiface.CoreAPI {
core/coreapi/name.go
+20
-11
@@ -15,7 +15,7 @@ import (
15
ipath "github.com/ipfs/go-ipfs/path"
16
offline "github.com/ipfs/go-ipfs/routing/offline"
17
18
- peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
18
+ peer "gx/ipfs/QmWNY7dV54ZDYmTA1ykVdwNCqC11mpU4zSUp6XDpLTH9eG/go-libp2p-peer"
19
crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
20
)
21
@@ -24,7 +24,20 @@ type NameAPI struct {
24
*caopts.NameOptions
25
}
26
27
-func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopts.NamePublishOption) (*coreiface.IpnsEntry, error) {
27
+type ipnsEntry struct {
28
+ name string
29
+ value coreiface.Path
30
+}
31
+
32
+func (e *ipnsEntry) Name() string {
33
+ return e.name
34
+}
35
+
36
+func (e *ipnsEntry) Value() coreiface.Path {
37
+ return e.value
38
+}
39
+
40
+func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopts.NamePublishOption) (coreiface.IpnsEntry, error) {
41
options, err := caopts.NamePublishOptions(opts...)
42
if err != nil {
43
return nil, err
@@ -42,10 +55,6 @@ func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopt
55
return nil, errors.New("cannot manually publish while IPNS is mounted")
56
}
57
45
- if n.Identity == "" {
46
- return nil, errors.New("identity not loaded")
47
- }
48
-
58
pth, err := ipath.ParsePath(p.String())
59
if err != nil {
60
return nil, err
@@ -67,9 +76,9 @@ func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopt
76
return nil, err
77
}
78
70
- return &coreiface.IpnsEntry{
71
- Name: pid.Pretty(),
72
- Value: p,
79
+ return &ipnsEntry{
80
+ name: pid.Pretty(),
81
+ value: p,
82
}, nil
83
}
84
@@ -90,7 +99,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam
99
100
var resolver namesys.Resolver = n.Namesys
101
93
- if options.Local && options.Nocache {
102
+ if options.Local && !options.Cache {
103
return nil, errors.New("cannot specify both local and nocache")
104
}
105
@@ -99,7 +108,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam
108
resolver = namesys.NewRoutingResolver(offroute, 0)
109
}
110
102
- if options.Nocache {
111
+ if !options.Cache {
112
resolver = namesys.NewNameSystem(n.Routing, n.Repo.Datastore(), 0)
113
}
114