@cryptotaxi247 / kubo / commits / 8df2d1a92

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