From f1267d0624fbb0493221ac33f4c0e43b64c58851 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Mon, 26 Jan 2015 20:13:11 +0000 Subject: [PATCH] change ipns resolve/publish to store raw keys, not b58 encoded --- core/commands/id.go | 22 ++++++++++++++++++++-- core/commands/publish.go | 17 ++++++++++++----- core/commands/resolve.go | 20 ++++++++++++-------- core/core.go | 3 +++ fuse/ipns/ipns_test.go | 5 +++-- fuse/ipns/ipns_unix.go | 16 ++++++++-------- namesys/dns.go | 7 +++++-- namesys/interface.go | 6 ++++-- namesys/namesys.go | 10 ++++++---- namesys/proquint.go | 6 ++++-- namesys/publisher.go | 11 +++++------ namesys/resolve_test.go | 9 +++++---- namesys/routing.go | 5 ++--- test/sharness/t0100-name.sh | 28 ++++++++++++++++++++++++++++ 14 files changed, 117 insertions(+), 48 deletions(-) create mode 100755 test/sharness/t0100-name.sh diff --git a/core/commands/id.go b/core/commands/id.go index 7d47465d9..590c0daff 100644 --- a/core/commands/id.go +++ b/core/commands/id.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "io" + "strings" "time" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" @@ -45,6 +46,9 @@ if no peer is specified, prints out local peers info. Arguments: []cmds.Argument{ cmds.StringArg("peerid", false, false, "peer.ID of node to look up").EnableStdin(), }, + Options: []cmds.Option{ + cmds.StringOption("f", "format", "optional output format"), + }, Run: func(req cmds.Request, res cmds.Response) { node, err := req.Context().GetNode() if err != nil { @@ -101,11 +105,25 @@ if no peer is specified, prints out local peers info. return nil, u.ErrCast() } - marshaled, err := json.MarshalIndent(val, "", "\t") + format, found, err := res.Request().Option("format").String() if err != nil { return nil, err } - return bytes.NewReader(marshaled), nil + if found { + output := format + output = strings.Replace(output, "", val.ID, -1) + output = strings.Replace(output, "", val.AgentVersion, -1) + output = strings.Replace(output, "", val.ProtocolVersion, -1) + output = strings.Replace(output, "", val.PublicKey, -1) + return strings.NewReader(output), nil + } else { + + marshaled, err := json.MarshalIndent(val, "", "\t") + if err != nil { + return nil, err + } + return bytes.NewReader(marshaled), nil + } }, }, Type: IdOutput{}, diff --git a/core/commands/publish.go b/core/commands/publish.go index 9b4d4014f..082be0778 100644 --- a/core/commands/publish.go +++ b/core/commands/publish.go @@ -6,6 +6,8 @@ import ( "io" "strings" + b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" + cmds "github.com/jbenet/go-ipfs/commands" core "github.com/jbenet/go-ipfs/core" nsys "github.com/jbenet/go-ipfs/namesys" @@ -54,12 +56,16 @@ Publish a to another public key: return } - args := req.Arguments() - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) + if !n.OnlineMode() { + err := n.SetupOfflineRouting() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } } + args := req.Arguments() + if n.Identity == "" { res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal) return @@ -98,7 +104,8 @@ Publish a to another public key: func publish(n *core.IpfsNode, k crypto.PrivKey, ref string) (*IpnsEntry, error) { pub := nsys.NewRoutingPublisher(n.Routing) - err := pub.Publish(k, ref) + val := b58.Decode(ref) + err := pub.Publish(n.Context(), k, u.Key(val)) if err != nil { return nil, err } diff --git a/core/commands/resolve.go b/core/commands/resolve.go index cb4703e11..9ad4bbbec 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -6,6 +6,7 @@ import ( "strings" cmds "github.com/jbenet/go-ipfs/commands" + u "github.com/jbenet/go-ipfs/util" ) var resolveCmd = &cmds.Command{ @@ -48,13 +49,16 @@ Resolve te value of another name: return } - var name string - - if n.PeerHost == nil { - res.SetError(errNotOnline, cmds.ErrClient) - return + if !n.OnlineMode() { + err := n.SetupOfflineRouting() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } } + var name string + if len(req.Arguments()) == 0 { if n.Identity == "" { res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal) @@ -66,7 +70,7 @@ Resolve te value of another name: name = req.Arguments()[0] } - output, err := n.Namesys.Resolve(name) + output, err := n.Namesys.Resolve(n.Context(), name) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -78,8 +82,8 @@ Resolve te value of another name: }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { - output := res.Output().(string) - return strings.NewReader(output), nil + output := res.Output().(u.Key) + return strings.NewReader(output.B58String()), nil }, }, } diff --git a/core/core.go b/core/core.go index a293f2199..30352bcab 100644 --- a/core/core.go +++ b/core/core.go @@ -367,6 +367,9 @@ func (n *IpfsNode) SetupOfflineRouting() error { } n.Routing = offroute.NewOfflineRouter(n.Repo.Datastore(), n.PrivateKey) + + n.Namesys = namesys.NewNameSystem(n.Routing) + return nil } diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index 6c54eda21..3b6118e5f 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -3,6 +3,7 @@ package ipns import ( "bytes" "crypto/rand" + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" "io/ioutil" "os" "testing" @@ -252,7 +253,7 @@ func TestFastRepublish(t *testing.T) { writeFileData(t, dataA, fname) // random <-time.After(shortRepublishTimeout * 2) log.Debug("resolving first hash") - resolvedHash, err := node.Namesys.Resolve(pubkeyHash) + resolvedHash, err := node.Namesys.Resolve(context.Background(), pubkeyHash) if err != nil { t.Fatal("resolve err:", pubkeyHash, err) } @@ -271,7 +272,7 @@ func TestFastRepublish(t *testing.T) { }(shortRepublishTimeout) hasPublished := func() bool { - res, err := node.Namesys.Resolve(pubkeyHash) + res, err := node.Namesys.Resolve(context.Background(), pubkeyHash) if err != nil { t.Fatalf("resolve err: %v", err) } diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index 341d355c7..15d848469 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -38,7 +38,7 @@ var ( // point to an empty directory. func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { emptyDir := &mdag.Node{Data: ft.FolderPBData()} - k, err := n.DAG.Add(emptyDir) + nodek, err := n.DAG.Add(emptyDir) if err != nil { return err } @@ -54,7 +54,7 @@ func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error { } pub := nsys.NewRoutingPublisher(n.Routing) - err = pub.Publish(key, k.B58String()) + err = pub.Publish(n.Context(), key, nodek) if err != nil { return err } @@ -116,7 +116,7 @@ func CreateRoot(n *core.IpfsNode, keys []ci.PrivKey, ipfsroot string) (*Root, er go nd.repub.Run() - pointsTo, err := n.Namesys.Resolve(name) + pointsTo, err := n.Namesys.Resolve(n.Context(), name) if err != nil { log.Warning("Could not resolve value for local ipns entry, providing empty dir") nd.Nd = &mdag.Node{Data: ft.FolderPBData()} @@ -124,12 +124,12 @@ func CreateRoot(n *core.IpfsNode, keys []ci.PrivKey, ipfsroot string) (*Root, er continue } - if !u.IsValidHash(pointsTo) { + if !u.IsValidHash(pointsTo.B58String()) { log.Criticalf("Got back bad data from namesys resolve! [%s]", pointsTo) return nil, nil } - node, err := n.Resolver.ResolvePath(pointsTo) + node, err := n.Resolver.ResolvePath(pointsTo.B58String()) if err != nil { log.Warning("Failed to resolve value from ipns entry in ipfs") continue @@ -186,13 +186,13 @@ func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) { } log.Debugf("ipns: Falling back to resolution for [%s].", name) - resolved, err := s.Ipfs.Namesys.Resolve(name) + resolved, err := s.Ipfs.Namesys.Resolve(s.Ipfs.Context(), name) if err != nil { log.Warningf("ipns: namesys resolve error: %s", err) return nil, fuse.ENOENT } - return &Link{s.IpfsRoot + "/" + resolved}, nil + return &Link{s.IpfsRoot + "/" + resolved.B58String()}, nil } // ReadDir reads a particular directory. Disallowed for root. @@ -461,7 +461,7 @@ func (n *Node) republishRoot() error { } log.Debug("Publishing changes!") - err = n.Ipfs.Namesys.Publish(root.key, ndkey.Pretty()) + err = n.Ipfs.Namesys.Publish(n.Ipfs.Context(), root.key, ndkey) if err != nil { log.Errorf("ipns: Publish Failed: %s", err) return err diff --git a/namesys/dns.go b/namesys/dns.go index 881979930..2fb477930 100644 --- a/namesys/dns.go +++ b/namesys/dns.go @@ -3,9 +3,12 @@ package namesys import ( "net" + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" isd "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-is-domain" mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" + + u "github.com/jbenet/go-ipfs/util" ) // DNSResolver implements a Resolver on DNS domains @@ -22,7 +25,7 @@ func (r *DNSResolver) CanResolve(name string) bool { // Resolve implements Resolver // TXT records for a given domain name should contain a b58 // encoded multihash. -func (r *DNSResolver) Resolve(name string) (string, error) { +func (r *DNSResolver) Resolve(ctx context.Context, name string) (u.Key, error) { log.Info("DNSResolver resolving %v", name) txt, err := net.LookupTXT(name) if err != nil { @@ -39,7 +42,7 @@ func (r *DNSResolver) Resolve(name string) (string, error) { if err != nil { continue } - return t, nil + return u.Key(chk), nil } return "", ErrResolveFailed diff --git a/namesys/interface.go b/namesys/interface.go index c2e39afec..f2e4f104d 100644 --- a/namesys/interface.go +++ b/namesys/interface.go @@ -3,7 +3,9 @@ package namesys import ( "errors" + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ci "github.com/jbenet/go-ipfs/p2p/crypto" + u "github.com/jbenet/go-ipfs/util" ) // ErrResolveFailed signals an error when attempting to resolve. @@ -28,7 +30,7 @@ type NameSystem interface { type Resolver interface { // Resolve looks up a name, and returns the value previously published. - Resolve(name string) (value string, err error) + Resolve(ctx context.Context, name string) (value u.Key, err error) // CanResolve checks whether this Resolver can resolve a name CanResolve(name string) bool @@ -39,5 +41,5 @@ type Publisher interface { // Publish establishes a name-value mapping. // TODO make this not PrivKey specific. - Publish(name ci.PrivKey, value string) error + Publish(ctx context.Context, name ci.PrivKey, value u.Key) error } diff --git a/namesys/namesys.go b/namesys/namesys.go index cc11d9ddc..eddae747d 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -1,8 +1,10 @@ package namesys import ( + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ci "github.com/jbenet/go-ipfs/p2p/crypto" routing "github.com/jbenet/go-ipfs/routing" + u "github.com/jbenet/go-ipfs/util" ) // ipnsNameSystem implements IPNS naming. @@ -32,10 +34,10 @@ func NewNameSystem(r routing.IpfsRouting) NameSystem { } // Resolve implements Resolver -func (ns *ipns) Resolve(name string) (string, error) { +func (ns *ipns) Resolve(ctx context.Context, name string) (u.Key, error) { for _, r := range ns.resolvers { if r.CanResolve(name) { - return r.Resolve(name) + return r.Resolve(ctx, name) } } return "", ErrResolveFailed @@ -52,6 +54,6 @@ func (ns *ipns) CanResolve(name string) bool { } // Publish implements Publisher -func (ns *ipns) Publish(name ci.PrivKey, value string) error { - return ns.publisher.Publish(name, value) +func (ns *ipns) Publish(ctx context.Context, name ci.PrivKey, value u.Key) error { + return ns.publisher.Publish(ctx, name, value) } diff --git a/namesys/proquint.go b/namesys/proquint.go index 89bbc4a44..24e97529d 100644 --- a/namesys/proquint.go +++ b/namesys/proquint.go @@ -3,7 +3,9 @@ package namesys import ( "errors" + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" proquint "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/bren2010/proquint" + u "github.com/jbenet/go-ipfs/util" ) type ProquintResolver struct{} @@ -15,10 +17,10 @@ func (r *ProquintResolver) CanResolve(name string) bool { } // Resolve implements Resolver. Decodes the proquint string. -func (r *ProquintResolver) Resolve(name string) (string, error) { +func (r *ProquintResolver) Resolve(ctx context.Context, name string) (u.Key, error) { ok := r.CanResolve(name) if !ok { return "", errors.New("not a valid proquint string") } - return string(proquint.Decode(name)), nil + return u.Key(proquint.Decode(name)), nil } diff --git a/namesys/publisher.go b/namesys/publisher.go index 75cccf9e4..8a82c7947 100644 --- a/namesys/publisher.go +++ b/namesys/publisher.go @@ -37,17 +37,16 @@ func NewRoutingPublisher(route routing.IpfsRouting) Publisher { // Publish implements Publisher. Accepts a keypair and a value, // and publishes it out to the routing system -func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error { +func (p *ipnsPublisher) Publish(ctx context.Context, k ci.PrivKey, value u.Key) error { log.Debugf("namesys: Publish %s", value) // validate `value` is a ref (multihash) - _, err := mh.FromB58String(value) + _, err := mh.FromB58String(value.Pretty()) if err != nil { log.Errorf("hash cast failed: %s", value) return fmt.Errorf("publish value must be str multihash. %v", err) } - ctx := context.TODO() data, err := createRoutingEntryData(k, value) if err != nil { log.Error("entry creation failed.") @@ -65,7 +64,7 @@ func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error { log.Debugf("Storing pubkey at: %s", namekey) // Store associated public key - timectx, _ := context.WithDeadline(ctx, time.Now().Add(time.Second*4)) + timectx, _ := context.WithDeadline(ctx, time.Now().Add(time.Second*10)) err = p.routing.PutValue(timectx, namekey, pkbytes) if err != nil { return err @@ -75,7 +74,7 @@ func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error { log.Debugf("Storing ipns entry at: %s", ipnskey) // Store ipns entry at "/ipns/"+b58(h(pubkey)) - timectx, _ = context.WithDeadline(ctx, time.Now().Add(time.Second*4)) + timectx, _ = context.WithDeadline(ctx, time.Now().Add(time.Second*10)) err = p.routing.PutValue(timectx, ipnskey, data) if err != nil { return err @@ -84,7 +83,7 @@ func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error { return nil } -func createRoutingEntryData(pk ci.PrivKey, val string) ([]byte, error) { +func createRoutingEntryData(pk ci.PrivKey, val u.Key) ([]byte, error) { entry := new(pb.IpnsEntry) entry.Value = []byte(val) diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go index 8e3214dfe..e349a0aa9 100644 --- a/namesys/resolve_test.go +++ b/namesys/resolve_test.go @@ -1,6 +1,7 @@ package namesys import ( + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" "testing" mockrouting "github.com/jbenet/go-ipfs/routing/mock" @@ -19,13 +20,13 @@ func TestRoutingResolve(t *testing.T) { t.Fatal(err) } - err = publisher.Publish(privk, "Hello") + err = publisher.Publish(context.Background(), privk, "Hello") if err == nil { t.Fatal("should have errored out when publishing a non-multihash val") } - h := u.Key(u.Hash([]byte("Hello"))).Pretty() - err = publisher.Publish(privk, h) + h := u.Key(u.Hash([]byte("Hello"))) + err = publisher.Publish(context.Background(), privk, h) if err != nil { t.Fatal(err) } @@ -36,7 +37,7 @@ func TestRoutingResolve(t *testing.T) { } pkhash := u.Hash(pubkb) - res, err := resolver.Resolve(u.Key(pkhash).Pretty()) + res, err := resolver.Resolve(context.Background(), u.Key(pkhash).Pretty()) if err != nil { t.Fatal(err) } diff --git a/namesys/routing.go b/namesys/routing.go index b57d2c601..a66565db6 100644 --- a/namesys/routing.go +++ b/namesys/routing.go @@ -38,9 +38,8 @@ func (r *routingResolver) CanResolve(name string) bool { // Resolve implements Resolver. Uses the IPFS routing system to resolve SFS-like // names. -func (r *routingResolver) Resolve(name string) (string, error) { +func (r *routingResolver) Resolve(ctx context.Context, name string) (u.Key, error) { log.Debugf("RoutingResolve: '%s'", name) - ctx := context.TODO() hash, err := mh.FromB58String(name) if err != nil { log.Warning("RoutingResolve: bad input hash: [%s]\n", name) @@ -88,5 +87,5 @@ func (r *routingResolver) Resolve(name string) (string, error) { } // ok sig checks out. this is a valid name. - return string(entry.GetValue()), nil + return u.Key(entry.GetValue()), nil } diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh new file mode 100755 index 000000000..195b61e4d --- /dev/null +++ b/test/sharness/t0100-name.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (c) 2014 Jeromy Johnson +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test ipfs repo operations" + +. lib/test-lib.sh + +test_init_ipfs + +test_expect_success "'ipfs name publish' succeeds" ' + PEERID=`ipfs id -format=""` && + HASH=QmYpv2VEsxzTTXRYX3PjDg961cnJE3kY1YDXLycHGQ3zZB && + ipfs name publish $HASH > publish_out && + echo Published name $PEERID to $HASH > expected1 && + test_cmp publish_out expected1 + +' + +test_expect_success "'ipfs name resolve' succeeds" ' + ipfs name resolve $PEERID > output && + printf "%s" $HASH > expected2 && + test_cmp output expected2 +' + +test_done