func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.Path, opts *publishOpts) (*IpnsEntry, error) { if opts.verifyExists { // verify the path exists _, err := core.Resolve(ctx, n, ref) if err != nil { return nil, err } } eol := time.Now().Add(opts.pubValidTime) err := n.Namesys.PublishWithEOL(ctx, k, ref, eol) if err != nil { return nil, err } hash, err := k.GetPublic().Hash() if err != nil { return nil, err } return &IpnsEntry{ Name: key.Key(hash).String(), Value: ref.String(), }, nil }
// newKeyRoot creates a new KeyRoot for the given key, and starts up a republisher routine // for it func (fs *Filesystem) newKeyRoot(parent context.Context, k ci.PrivKey) (*KeyRoot, error) { hash, err := k.GetPublic().Hash() if err != nil { return nil, err } name := "/ipns/" + key.Key(hash).String() root := new(KeyRoot) root.key = k root.fs = fs root.name = name ctx, cancel := context.WithCancel(parent) defer cancel() pointsTo, err := fs.nsys.Resolve(ctx, name) if err != nil { err = namesys.InitializeKeyspace(ctx, fs.dserv, fs.nsys, fs.pins, k) if err != nil { return nil, err } pointsTo, err = fs.nsys.Resolve(ctx, name) if err != nil { return nil, err } } mnode, err := fs.resolver.ResolvePath(ctx, pointsTo) if err != nil { log.Errorf("Failed to retrieve value '%s' for ipns entry: %s\n", pointsTo, err) return nil, err } root.node = mnode root.repub = NewRepublisher(root, time.Millisecond*300, time.Second*3) go root.repub.Run(parent) pbn, err := ft.FromBytes(mnode.Data) if err != nil { log.Error("IPNS pointer was not unixfs node") return nil, err } switch pbn.GetType() { case ft.TDirectory: root.val = NewDirectory(ctx, pointsTo.String(), mnode, root, fs) case ft.TFile, ft.TMetadata, ft.TRaw: fi, err := NewFile(pointsTo.String(), mnode, root, fs) if err != nil { return nil, err } root.val = fi default: panic("unrecognized! (NYI)") } return root, nil }
// newPeernet constructs a new peernet func newPeernet(ctx context.Context, m *mocknet, k ic.PrivKey, a ma.Multiaddr) (*peernet, error) { p, err := peer.IDFromPublicKey(k.GetPublic()) if err != nil { return nil, err } // create our own entirely, so that peers knowledge doesn't get shared ps := peer.NewPeerstore() ps.AddAddr(p, a, peer.PermanentAddrTTL) ps.AddPrivKey(p, k) ps.AddPubKey(p, k.GetPublic()) n := &peernet{ mocknet: m, peer: p, ps: ps, cg: ctxgroup.WithContext(ctx), connsByPeer: map[peer.ID]map[*conn]struct{}{}, connsByLink: map[*link]map[*conn]struct{}{}, notifs: make(map[inet.Notifiee]struct{}), } n.cg.SetTeardown(n.teardown) return n, nil }
func (mn *mocknet) AddPeer(k ic.PrivKey, a ma.Multiaddr) (host.Host, error) { p, err := peer.IDFromPublicKey(k.GetPublic()) if err != nil { return nil, err } ps := peer.NewPeerstore() ps.AddAddr(p, a, peer.PermanentAddrTTL) ps.AddPrivKey(p, k) ps.AddPubKey(p, k.GetPublic()) return mn.AddPeerWithPeerstore(p, ps) }
func createRoutingEntryData(pk ci.PrivKey, val path.Path) ([]byte, error) { entry := new(pb.IpnsEntry) entry.Value = []byte(val) typ := pb.IpnsEntry_EOL entry.ValidityType = &typ entry.Validity = []byte(u.FormatRFC3339(time.Now().Add(time.Hour * 24))) sig, err := pk.Sign(ipnsEntryDataForSig(entry)) if err != nil { return nil, err } entry.Signature = sig return proto.Marshal(entry) }
func CreateRoutingEntryData(pk ci.PrivKey, val path.Path, seq uint64, eol time.Time) (*pb.IpnsEntry, error) { entry := new(pb.IpnsEntry) entry.Value = []byte(val) typ := pb.IpnsEntry_EOL entry.ValidityType = &typ entry.Sequence = proto.Uint64(seq) entry.Validity = []byte(u.FormatRFC3339(eol)) sig, err := pk.Sign(ipnsEntryDataForSig(entry)) if err != nil { return nil, err } entry.Signature = sig return entry, nil }
func PutRecordToRouting(ctx context.Context, k ci.PrivKey, value path.Path, seqnum uint64, eol time.Time, r routing.IpfsRouting, id peer.ID) error { namekey, ipnskey := IpnsKeysForID(id) entry, err := CreateRoutingEntryData(k, value, seqnum, eol) if err != nil { return err } err = PublishEntry(ctx, r, ipnskey, entry) if err != nil { return err } err = PublishPublicKey(ctx, r, namekey, k.GetPublic()) if err != nil { return err } return nil }
func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.Path) (*IpnsEntry, error) { // First, verify the path exists _, err := core.Resolve(ctx, n, ref) if err != nil { return nil, err } err = n.Namesys.Publish(ctx, k, ref) if err != nil { return nil, err } hash, err := k.GetPublic().Hash() if err != nil { return nil, err } return &IpnsEntry{ Name: key.Key(hash).String(), Value: ref.String(), }, nil }
// Publish implements Publisher. Accepts a keypair and a value, // and publishes it out to the routing system func (p *ipnsPublisher) Publish(ctx context.Context, k ci.PrivKey, value path.Path) error { log.Debugf("Publish %s", value) data, err := createRoutingEntryData(k, value) if err != nil { return err } pubkey := k.GetPublic() pkbytes, err := pubkey.Bytes() if err != nil { return err } nameb := u.Hash(pkbytes) namekey := key.Key("/pk/" + string(nameb)) log.Debugf("Storing pubkey at: %s", namekey) // Store associated public key timectx, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second*10)) defer cancel() err = p.routing.PutValue(timectx, namekey, pkbytes) if err != nil { return err } ipnskey := key.Key("/ipns/" + string(nameb)) log.Debugf("Storing ipns entry at: %s", ipnskey) // Store ipns entry at "/ipns/"+b58(h(pubkey)) timectx, cancel = context.WithDeadline(ctx, time.Now().Add(time.Second*10)) defer cancel() if err := p.routing.PutValue(timectx, ipnskey, data); err != nil { return err } return nil }
func PutRecordToRouting(ctx context.Context, k ci.PrivKey, value path.Path, seqnum uint64, eol time.Time, r routing.IpfsRouting, id peer.ID) error { namekey, ipnskey := IpnsKeysForID(id) entry, err := CreateRoutingEntryData(k, value, seqnum, eol) if err != nil { return err } ttl, ok := checkCtxTTL(ctx) if ok { entry.Ttl = proto.Uint64(uint64(ttl.Nanoseconds())) } err = PublishEntry(ctx, r, ipnskey, entry) if err != nil { return err } err = PublishPublicKey(ctx, r, namekey, k.GetPublic()) if err != nil { return err } return nil }
// MakePutRecord creates and signs a dht record for the given key/value pair func MakePutRecord(sk ci.PrivKey, key key.Key, value []byte, sign bool) (*pb.Record, error) { record := new(pb.Record) record.Key = proto.String(string(key)) record.Value = value pkh, err := sk.GetPublic().Hash() if err != nil { return nil, err } record.Author = proto.String(string(pkh)) if sign { blob := RecordBlobForSig(record) sig, err := sk.Sign(blob) if err != nil { return nil, err } record.Signature = sig } return record, nil }
// MatchesPrivateKey tests whether this ID was derived from sk func (id ID) MatchesPrivateKey(sk ic.PrivKey) bool { return id.MatchesPublicKey(sk.GetPublic()) }
// IDFromPrivateKey returns the Peer ID corresponding to sk func IDFromPrivateKey(sk ic.PrivKey) (ID, error) { return IDFromPublicKey(sk.GetPublic()) }