1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-09-09 23:42:20 +08:00

New NameSystem interface

type NameSystem interface {
      Resolver
      Publisher
    }

should say it all.

cc @whyrusleeping
This commit is contained in:
Juan Batiz-Benet
2014-10-08 04:14:50 -07:00
parent cf6efc7a09
commit 2944360f5c
13 changed files with 139 additions and 113 deletions

View File

@ -19,7 +19,7 @@ func Publish(n *core.IpfsNode, args []string, opts map[string]interface{}, out i
k := n.Identity.PrivKey k := n.Identity.PrivKey
pub := nsys.NewPublisher(n.DAG, n.Routing) pub := nsys.NewRoutingPublisher(n.Routing)
err := pub.Publish(k, args[0]) err := pub.Publish(k, args[0])
if err != nil { if err != nil {
return err return err

View File

@ -63,10 +63,7 @@ type IpfsNode struct {
Resolver *path.Resolver Resolver *path.Resolver
// the name system, resolves paths to hashes // the name system, resolves paths to hashes
Namesys namesys.Resolver Namesys namesys.NameSystem
// the routing publisher
Publisher namesys.Publisher
} }
// NewIpfsNode constructs a new IpfsNode based on the given config. // NewIpfsNode constructs a new IpfsNode based on the given config.
@ -148,8 +145,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
} }
dag := &merkledag.DAGService{Blocks: bs} dag := &merkledag.DAGService{Blocks: bs}
resolve := namesys.NewMasterResolver(route, dag) ns := namesys.NewNameSystem(route)
publisher := namesys.NewPublisher(dag, route)
success = true success = true
return &IpfsNode{ return &IpfsNode{
@ -162,8 +158,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
Exchange: exchangeSession, Exchange: exchangeSession,
Identity: local, Identity: local,
Routing: route, Routing: route,
Namesys: resolve, Namesys: ns,
Publisher: publisher,
}, nil }, nil
} }

View File

@ -43,10 +43,7 @@ func NewMockNode() (*IpfsNode, error) {
nd.DAG = &mdag.DAGService{bserv} nd.DAG = &mdag.DAGService{bserv}
// Namespace resolver // Namespace resolver
nd.Namesys = nsys.NewMasterResolver(dht, nd.DAG) nd.Namesys = nsys.NewNameSystem(dht)
// Publisher
nd.Publisher = nsys.NewPublisher(nd.DAG, dht)
// Path resolver // Path resolver
nd.Resolver = &path.Resolver{nd.DAG} nd.Resolver = &path.Resolver{nd.DAG}

View File

@ -397,7 +397,7 @@ func (n *Node) republishRoot() error {
} }
log.Debug("Publishing changes!") log.Debug("Publishing changes!")
err = n.Ipfs.Publisher.Publish(root.key, ndkey.Pretty()) err = n.Ipfs.Namesys.Publish(root.key, ndkey.Pretty())
if err != nil { if err != nil {
log.Error("ipns: Publish Failed: %s", err) log.Error("ipns: Publish Failed: %s", err)
return err return err

View File

@ -4,9 +4,10 @@ import (
"net" "net"
b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
u "github.com/jbenet/go-ipfs/util"
isd "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-is-domain" 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 // DNSResolver implements a Resolver on DNS domains
@ -15,8 +16,8 @@ type DNSResolver struct {
// cache would need a timeout // cache would need a timeout
} }
// Matches implements Resolver // CanResolve implements Resolver
func (r *DNSResolver) Matches(name string) bool { func (r *DNSResolver) CanResolve(name string) bool {
return isd.IsDomain(name) return isd.IsDomain(name)
} }

43
namesys/interface.go Normal file
View File

@ -0,0 +1,43 @@
package namesys
import (
"errors"
ci "github.com/jbenet/go-ipfs/crypto"
)
// ErrResolveFailed signals an error when attempting to resolve.
var ErrResolveFailed = errors.New("could not resolve name.")
// ErrPublishFailed signals an error when attempting to publish.
var ErrPublishFailed = errors.New("could not publish name.")
// Namesys represents a cohesive name publishing and resolving system.
//
// Publishing a name is the process of establishing a mapping, a key-value
// pair, according to naming rules and databases.
//
// Resolving a name is the process of looking up the value associated with the
// key (name).
type NameSystem interface {
Resolver
Publisher
}
// Resolver is an object capable of resolving names.
type Resolver interface {
// Resolve looks up a name, and returns the value previously published.
Resolve(name string) (value string, err error)
// CanResolve checks whether this Resolver can resolve a name
CanResolve(name string) bool
}
// Publisher is an object capable of publishing particular names.
type Publisher interface {
// Publish establishes a name-value mapping.
// TODO make this not PrivKey specific.
Publish(name ci.PrivKey, value string) error
}

57
namesys/namesys.go Normal file
View File

@ -0,0 +1,57 @@
package namesys
import (
ci "github.com/jbenet/go-ipfs/crypto"
routing "github.com/jbenet/go-ipfs/routing"
)
// ipnsNameSystem implements IPNS naming.
//
// Uses three Resolvers:
// (a) ipfs routing naming: SFS-like PKI names.
// (b) dns domains: resolves using links in DNS TXT records
// (c) proquints: interprets string as the raw byte data.
//
// It can only publish to: (a) ipfs routing naming.
//
type ipns struct {
resolvers []Resolver
publisher Publisher
}
// NewNameSystem will construct the IPFS naming system based on Routing
func NewNameSystem(r routing.IpfsRouting) NameSystem {
return &ipns{
resolvers: []Resolver{
new(DNSResolver),
new(ProquintResolver),
NewRoutingResolver(r),
},
publisher: NewRoutingPublisher(r),
}
}
// Resolve implements Resolver
func (ns *ipns) Resolve(name string) (string, error) {
for _, r := range ns.resolvers {
if r.CanResolve(name) {
return r.Resolve(name)
}
}
return "", ErrResolveFailed
}
// CanResolve implements Resolver
func (ns *ipns) CanResolve(name string) bool {
for _, r := range ns.resolvers {
if r.CanResolve(name) {
return true
}
}
return false
}
// Publish implements Publisher
func (ns *ipns) Publish(name ci.PrivKey, value string) error {
return ns.publisher.Publish(name, value)
}

View File

@ -1,8 +0,0 @@
package namesys
type Resolver interface {
// Resolve returns a base58 encoded string
Resolve(string) (string, error)
Matches(string) bool
}

View File

@ -8,13 +8,15 @@ import (
type ProquintResolver struct{} type ProquintResolver struct{}
func (r *ProquintResolver) Matches(name string) bool { // CanResolve implements Resolver. Checks whether the name is a proquint string.
func (r *ProquintResolver) CanResolve(name string) bool {
ok, err := proquint.IsProquint(name) ok, err := proquint.IsProquint(name)
return err == nil && ok return err == nil && ok
} }
// Resolve implements Resolver. Decodes the proquint string.
func (r *ProquintResolver) Resolve(name string) (string, error) { func (r *ProquintResolver) Resolve(name string) (string, error) {
ok := r.Matches(name) ok := r.CanResolve(name)
if !ok { if !ok {
return "", errors.New("not a valid proquint string") return "", errors.New("not a valid proquint string")
} }

View File

@ -7,32 +7,26 @@ import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
ci "github.com/jbenet/go-ipfs/crypto" ci "github.com/jbenet/go-ipfs/crypto"
mdag "github.com/jbenet/go-ipfs/merkledag"
routing "github.com/jbenet/go-ipfs/routing" routing "github.com/jbenet/go-ipfs/routing"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
) )
// ipnsPublisher is capable of publishing and resolving names to the IPFS
// routing system.
type ipnsPublisher struct { type ipnsPublisher struct {
dag *mdag.DAGService
routing routing.IpfsRouting routing routing.IpfsRouting
} }
type Publisher interface { // NewRoutingPublisher constructs a publisher for the IPFS Routing name system.
Publish(ci.PrivKey, string) error func NewRoutingPublisher(route routing.IpfsRouting) Publisher {
return &ipnsPublisher{routing: route}
} }
func NewPublisher(dag *mdag.DAGService, route routing.IpfsRouting) Publisher { // Publish implements Publisher. Accepts a keypair and a value,
return &ipnsPublisher{
dag: dag,
routing: route,
}
}
// Publish accepts a keypair and a value,
func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error { func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error {
log.Debug("namesys: Publish %s", value) log.Debug("namesys: Publish %s", value)
ctx := context.TODO() ctx := context.TODO()
data, err := CreateEntryData(k, value) data, err := createRoutingEntryData(k, value)
if err != nil { if err != nil {
return err return err
} }
@ -63,7 +57,7 @@ func (p *ipnsPublisher) Publish(k ci.PrivKey, value string) error {
return nil return nil
} }
func CreateEntryData(pk ci.PrivKey, val string) ([]byte, error) { func createRoutingEntryData(pk ci.PrivKey, val string) ([]byte, error) {
entry := new(IpnsEntry) entry := new(IpnsEntry)
sig, err := pk.Sign([]byte(val)) sig, err := pk.Sign([]byte(val))
if err != nil { if err != nil {

View File

@ -4,9 +4,7 @@ import (
"testing" "testing"
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go" ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"
bs "github.com/jbenet/go-ipfs/blockservice"
ci "github.com/jbenet/go-ipfs/crypto" ci "github.com/jbenet/go-ipfs/crypto"
mdag "github.com/jbenet/go-ipfs/merkledag"
"github.com/jbenet/go-ipfs/peer" "github.com/jbenet/go-ipfs/peer"
mock "github.com/jbenet/go-ipfs/routing/mock" mock "github.com/jbenet/go-ipfs/routing/mock"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
@ -19,26 +17,15 @@ func TestRoutingResolve(t *testing.T) {
lds := ds.NewMapDatastore() lds := ds.NewMapDatastore()
d := mock.NewMockRouter(local, lds) d := mock.NewMockRouter(local, lds)
bserv, err := bs.NewBlockService(lds, nil) resolver := NewRoutingResolver(d)
if err != nil { publisher := NewRoutingPublisher(d)
t.Fatal(err)
}
dag := &mdag.DAGService{Blocks: bserv}
resolve := NewMasterResolver(d, dag)
pub := ipnsPublisher{
dag: dag,
routing: d,
}
privk, pubk, err := ci.GenerateKeyPair(ci.RSA, 512) privk, pubk, err := ci.GenerateKeyPair(ci.RSA, 512)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = pub.Publish(privk, "Hello") err = publisher.Publish(privk, "Hello")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -49,7 +36,7 @@ func TestRoutingResolve(t *testing.T) {
} }
pkhash := u.Hash(pubkb) pkhash := u.Hash(pubkb)
res, err := resolve.Resolve(u.Key(pkhash).Pretty()) res, err := resolver.Resolve(u.Key(pkhash).Pretty())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -1,42 +0,0 @@
package namesys
import (
"errors"
mdag "github.com/jbenet/go-ipfs/merkledag"
"github.com/jbenet/go-ipfs/routing"
)
var ErrCouldntResolve = errors.New("could not resolve name.")
type masterResolver struct {
res []Resolver
}
func NewMasterResolver(r routing.IpfsRouting, dag *mdag.DAGService) Resolver {
mr := new(masterResolver)
mr.res = []Resolver{
new(DNSResolver),
new(ProquintResolver),
NewRoutingResolver(r, dag),
}
return mr
}
func (mr *masterResolver) Resolve(name string) (string, error) {
for _, r := range mr.res {
if r.Matches(name) {
return r.Resolve(name)
}
}
return "", ErrCouldntResolve
}
func (mr *masterResolver) Matches(name string) bool {
for _, r := range mr.res {
if r.Matches(name) {
return true
}
}
return false
}

View File

@ -8,32 +8,32 @@ import (
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
ci "github.com/jbenet/go-ipfs/crypto" ci "github.com/jbenet/go-ipfs/crypto"
mdag "github.com/jbenet/go-ipfs/merkledag" routing "github.com/jbenet/go-ipfs/routing"
"github.com/jbenet/go-ipfs/routing"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
) )
var log = u.Logger("namesys") var log = u.Logger("namesys")
// RoutingResolver implements NSResolver for the main IPFS SFS-like naming // routingResolver implements NSResolver for the main IPFS SFS-like naming
type RoutingResolver struct { type routingResolver struct {
routing routing.IpfsRouting routing routing.IpfsRouting
dag *mdag.DAGService
} }
func NewRoutingResolver(route routing.IpfsRouting, dagservice *mdag.DAGService) *RoutingResolver { // NewRoutingResolver constructs a name resolver using the IPFS Routing system
return &RoutingResolver{ // to implement SFS-like naming on top.
routing: route, func NewRoutingResolver(route routing.IpfsRouting) Resolver {
dag: dagservice, return &routingResolver{routing: route}
}
} }
func (r *RoutingResolver) Matches(name string) bool { // CanResolve implements Resolver. Checks whether name is a b58 encoded string.
func (r *routingResolver) CanResolve(name string) bool {
_, err := mh.FromB58String(name) _, err := mh.FromB58String(name)
return err == nil return err == nil
} }
func (r *RoutingResolver) Resolve(name string) (string, error) { // Resolve implements Resolver. Uses the IPFS routing system to resolve SFS-like
// names.
func (r *routingResolver) Resolve(name string) (string, error) {
log.Debug("RoutingResolve: '%s'", name) log.Debug("RoutingResolve: '%s'", name)
ctx := context.TODO() ctx := context.TODO()
hash, err := mh.FromB58String(name) hash, err := mh.FromB58String(name)