implement namesys resolvers (thanks to bren2010 for dns and proquint)
Jeromy committed
Sep 10, 2014 at 16:55 UTC
235a7674929ec787c141abec96b11534023a159c
9 files changed
+257
-1
cmd/ipfs/pin.go
new
+44
@@ -0,0 +1,44 @@
1
+package main
2
+
3
+import (
4
+ "os"
5
+
6
+ "github.com/gonuts/flag"
7
+ "github.com/jbenet/commander"
8
+ "github.com/jbenet/go-ipfs/daemon"
9
+ u "github.com/jbenet/go-ipfs/util"
10
+)
11
+
12
+var cmdIpfsPin = &commander.Command{
13
+ UsageLine: "pin",
14
+ Short: "pin an ipfs object to local storage.",
15
+ Long: `ipfs pin <ipfs-path> - pin ipfs object to local storage.
16
+
17
+ Retrieves the object named by <ipfs-path> and stores it locally
18
+ on disk.
19
+`,
20
+ Run: pinCmd,
21
+ Flag: *flag.NewFlagSet("ipfs-pin", flag.ExitOnError),
22
+}
23
+
24
+func pinCmd(c *commander.Command, inp []string) error {
25
+ if len(inp) < 1 {
26
+ u.POut(c.Long)
27
+ return nil
28
+ }
29
+
30
+ com := daemon.NewCommand()
31
+ com.Command = "pin"
32
+ com.Args = inp
33
+
34
+ err := daemon.SendCommand(com, "localhost:12345")
35
+ if err != nil {
36
+ n, err := localNode(false)
37
+ if err != nil {
38
+ return err
39
+ }
40
+
41
+ daemon.ExecuteCommand(com, n, os.Stdout)
42
+ }
43
+ return nil
44
+}
core/core.go
+1
-1
@@ -60,7 +60,7 @@ type IpfsNode struct {
60
Resolver *path.Resolver
61
62
// the name system, resolves paths to hashes
63
- // Namesys *namesys.Namesys
63
+ Namesys namesys.NSResolver
64
}
65
66
// NewIpfsNode constructs a new IpfsNode based on the given config.
namesys/dns.go
new
+33
@@ -0,0 +1,33 @@
1
+package namesys
2
+
3
+import (
4
+ "net"
5
+ "strings"
6
+
7
+ u "github.com/jbenet/go-ipfs/util"
8
+)
9
+
10
+type DNSResolver struct {
11
+ // TODO: maybe some sort of caching?
12
+ // cache would need a timeout
13
+}
14
+
15
+func (r *DNSResolver) Resolve(name string) (string, error) {
16
+ txt, err := net.LookupTXT(name)
17
+ if err != nil {
18
+ return "", err
19
+ }
20
+
21
+ for _, t := range txt {
22
+ pair := strings.Split(t, "=")
23
+ if len(pair) < 2 {
24
+ // Log error?
25
+ u.DErr("Incorrectly formatted text record.")
26
+ continue
27
+ }
28
+ if pair[0] == name {
29
+ return pair[1], nil
30
+ }
31
+ }
32
+ return "", u.ErrNotFound
33
+}
namesys/entry.pb.go
new
+48
@@ -0,0 +1,48 @@
1
+// Code generated by protoc-gen-go.
2
+// source: entry.proto
3
+// DO NOT EDIT!
4
+
5
+/*
6
+Package namesys is a generated protocol buffer package.
7
+
8
+It is generated from these files:
9
+ entry.proto
10
+
11
+It has these top-level messages:
12
+ InpsEntry
13
+*/
14
+package namesys
15
+
16
+import proto "code.google.com/p/goprotobuf/proto"
17
+import math "math"
18
+
19
+// Reference imports to suppress errors if they are not otherwise used.
20
+var _ = proto.Marshal
21
+var _ = math.Inf
22
+
23
+type InpsEntry struct {
24
+ Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
25
+ Signature []byte `protobuf:"bytes,2,req,name=signature" json:"signature,omitempty"`
26
+ XXX_unrecognized []byte `json:"-"`
27
+}
28
+
29
+func (m *InpsEntry) Reset() { *m = InpsEntry{} }
30
+func (m *InpsEntry) String() string { return proto.CompactTextString(m) }
31
+func (*InpsEntry) ProtoMessage() {}
32
+
33
+func (m *InpsEntry) GetValue() []byte {
34
+ if m != nil {
35
+ return m.Value
36
+ }
37
+ return nil
38
+}
39
+
40
+func (m *InpsEntry) GetSignature() []byte {
41
+ if m != nil {
42
+ return m.Signature
43
+ }
44
+ return nil
45
+}
46
+
47
+func init() {
48
+}
namesys/entry.proto
new
+6
@@ -0,0 +1,6 @@
1
+package namesys;
2
+
3
+message InpsEntry {
4
+ required bytes value = 1;
5
+ required bytes signature = 2;
6
+}
namesys/nsresolver.go
new
+5
@@ -0,0 +1,5 @@
1
+package namesys
2
+
3
+type NSResolver interface {
4
+ Resolve(string) (string, error)
5
+}
namesys/proquint.go
new
+22
@@ -0,0 +1,22 @@
1
+package namesys
2
+
3
+import (
4
+ "errors"
5
+
6
+ proquint "github.com/bren2010/proquint"
7
+)
8
+
9
+var _ = proquint.Encode
10
+
11
+type ProquintResolver struct{}
12
+
13
+func (r *ProquintResolver) Resolve(name string) (string, error) {
14
+ ok, err := proquint.IsProquint(name)
15
+ if err != nil {
16
+ return "", err
17
+ }
18
+ if !ok {
19
+ return "", errors.New("not a valid proquint string")
20
+ }
21
+ return string(proquint.Decode(name)), nil
22
+}
namesys/resolver.go
new
+21
@@ -0,0 +1,21 @@
1
+package namesys
2
+
3
+import "strings"
4
+
5
+type MasterResolver struct {
6
+ dns *DNSResolver
7
+ routing *RoutingResolver
8
+ pro *ProquintResolver
9
+}
10
+
11
+func (mr *MasterResolver) Resolve(name string) (string, error) {
12
+ if strings.Contains(name, ".") {
13
+ return mr.dns.Resolve(name)
14
+ }
15
+
16
+ if strings.Contains(name, "-") {
17
+ return mr.pro.Resolve(name)
18
+ }
19
+
20
+ return mr.routing.Resolve(name)
21
+}
namesys/routing.go
new
+77
@@ -0,0 +1,77 @@
1
+package namesys
2
+
3
+import (
4
+ "fmt"
5
+ "time"
6
+
7
+ "code.google.com/p/goprotobuf/proto"
8
+
9
+ ci "github.com/jbenet/go-ipfs/crypto"
10
+ mdag "github.com/jbenet/go-ipfs/merkledag"
11
+ "github.com/jbenet/go-ipfs/routing"
12
+ u "github.com/jbenet/go-ipfs/util"
13
+ mh "github.com/jbenet/go-multihash"
14
+)
15
+
16
+// RoutingName is the de-serialized name structure that is stored (serialized)
17
+// in the routing system. Basically, a hash + a digital signature. (serialization can be
18
+// protobuf, or a simple binary format)
19
+type RoutingName struct {
20
+ Hash u.Key
21
+ Signature []byte
22
+}
23
+
24
+// RoutingResolver implements NSResolver for the main IPFS SFS-like naming
25
+type RoutingResolver struct {
26
+ routing routing.IpfsRouting
27
+ dag mdag.DAGService
28
+}
29
+
30
+func (r *RoutingResolver) Resolve(name string) (string, error) {
31
+ hash, err := mh.FromB58String(name)
32
+ if err != nil {
33
+ return "", err
34
+ }
35
+ // name should be a multihash. if it isn't, error out here.
36
+
37
+ // use the routing system to get the name.
38
+ // /ipns/<name>
39
+ h, err := u.Hash([]byte("ipns:" + name))
40
+ if err != nil {
41
+ return "", err
42
+ }
43
+
44
+ inpsKey := u.Key(h)
45
+ val, err := r.routing.GetValue(inpsKey, time.Second*10)
46
+ if err != nil {
47
+ return "", err
48
+ }
49
+
50
+ entry := new(InpsEntry)
51
+ err = proto.Unmarshal(val, entry)
52
+ if err != nil {
53
+ return "", err
54
+ }
55
+
56
+ // name should be a public key retrievable from ipfs
57
+ // /ipfs/<name>
58
+ key := u.Key(hash)
59
+ node, err := r.dag.Get(key)
60
+ if err != nil {
61
+ return "", err
62
+ }
63
+
64
+ // get PublicKey from node.Data
65
+ pk, err := ci.UnmarshalPublicKey(node.Data)
66
+ if err != nil {
67
+ return "", err
68
+ }
69
+
70
+ // check sig with pk
71
+ if ok, err := pk.Verify(entry.GetValue(), entry.GetSignature()); err != nil && ok {
72
+ return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pk)
73
+ }
74
+
75
+ // ok sig checks out. this is a valid name.
76
+ return string(entry.GetValue()), nil
77
+}