func (t *Thread) updateLink(n *merkledag.Node, stamp time.Time) func(bool, *merkledag.Node) (bool, error) { return func(exist bool, prev *merkledag.Node) (bool, error) { if exist { return false, nil } pren, err := getLinkName(prev) if log.If(err) { return false, err } if pren != nil { log.Println(pren.stamp) pn := pren.string() raw, errr := prev.GetNodeLink(pn) if log.If(errr) { return false, errr } if errr := n.AddRawLink(pn, raw); log.If(errr) { return false, errr } if errr := prev.RemoveNodeLink(pn); log.If(errr) { return false, errr } } name := &linkName{stamp: stamp} log.Println(name.stamp) if err := prev.AddNodeLink(name.string(), n); log.If(err) { return false, err } log.If(err) return true, err } }
func doInit(out io.Writer, repoRoot string, force bool, empty bool, nBitsForKeypair int) error { log.Println("initializing ipfs node at ", repoRoot) if err := checkWriteable(repoRoot); err != nil { return err } if fsrepo.IsInitialized(repoRoot) && !force { log.Println("repo already exists") return nil } conf, err := config.Init(out, nBitsForKeypair) if err != nil { return err } if fsrepo.IsInitialized(repoRoot) { if err := fsrepo.Remove(repoRoot); err != nil { return err } } if err := fsrepo.Init(repoRoot, conf); err != nil { return err } if !empty { if err := addDefaultAssets(out, repoRoot); err != nil { return err } } return initializeIpnsKeyspace(repoRoot) }
//Slice returns sorted records slice. //if insufficient number it returns atmost records slice. func (t *Thread) Slice(from, to int, spam slice.Key) (record.Records, error) { sl := make(record.Records, 0, to-from) troot, err := t.self.GetDAGNode(t.root) log.Println(t.root) if log.If(err) { return nil, err } root, err := t.next(troot) if log.If(err) { return nil, err } for i := 0; root != nil && i < to; i++ { kkk, _ := root.Key() if spam != nil { if _, exist := spam[kkk]; exist { log.Println(kkk, "is regarded as spam") i-- continue } } if i >= from { r, errr := t.toRecord(root) if log.If(errr) { return nil, errr } sl = append(sl, r) } root, err = t.next(root) if log.If(err) { return nil, err } } return sl, nil }
//Add adds record r and return true is thread was changed. func (t *Thread) Add(r *record.Record) (bool, error) { if t.name != r.Thread { err := errors.New("thread name unmatch") log.Println(err) return false, err } rn, err := t.self.GetDAGNode(r.Key) if log.If(err) { return false, err } n := &merkledag.Node{} if err := n.AddNodeLink("contents", rn); log.If(err) { return false, err } nsign := &merkledag.Node{Data: r.Sign} if err := n.AddNodeLink("sign", nsign); log.If(err) { return false, err } troot, err := t.self.GetDAGNode(t.root) if log.If(err) { return false, err } troot, err = t.search(troot, r.Stamp, t.updateLink(n, r.Stamp)) if log.If(err) { return false, err } log.Println(t.root) if troot != nil { t.root, err = t.self.AddDAGNode(troot, false) } log.Println(t.root) log.If(err) return troot != nil, err }
//nameResolve resole name hash using IPNS. func (p *Peer) nameResolve() (key.Key, error) { log.Println("resolving", p.ID.Pretty()) pt, err := p.myself.ipfsNode.Namesys.Resolve(p.myself.ctx, "/ipns/"+p.ID.Pretty()) if log.If(err) { return "", err } log.Println("resolved", pt) seg := pt.Segments() return key.B58KeyDecode(seg[len(seg)-1]), nil }
//Merge merges all records in list which has key and returns true if updated . func (l *List) Merge(tkey key.Key) (bool, error) { if l.key == tkey { log.Println("same key,nothing to do") return false, nil } root, err := l.self.GetDAGNode(l.key) if log.If(err) { return false, err } troot, err := l.self.GetDAGNode(tkey) if log.If(err) { return false, err } var t *Thread updated := false for _, link := range troot.Links { var k key.Key if th, errr := l.self.GetLinkedNode(root, link.Name); errr == nil { k, err = th.Key() if log.If(err) { return false, err } } t, err = New(l.self, link.Name, k) if log.If(err) { return false, err } kk := key.Key(link.Hash) if k == kk { continue } log.Println("adding to " + link.Name) u, errr := t.Merge(kk) if log.If(errr) { return false, err } if !u { continue } tn, errr := t.self.GetDAGNode(t.Key()) if log.If(errr) { return false, errr } root, errr = root.UpdateNodeLink(link.Name, tn) if log.If(errr) { return false, errr } updated = true } if updated { l.key, err = l.self.AddDAGNode(root, false) log.If(err) } return updated, err }
//NewSelf make repo if needed ,starts daemon and returns Self obj. func NewSelf(cfg *config.Config, rootPath string) *Self { InitRepo(cfg.IpfsRepo) n := &merkledag.Node{} k, err := n.Key() log.IfFatal(err) //workaround "ERROR bitswap: failed to find any peer in table" i := 0 var node *core.IpfsNode var ctx context.Context var cancel context.CancelFunc for i = 0; i < 10; i++ { log.Println("setting up node...") r, err := fsrepo.Open(cfg.IpfsRepo) log.IfFatal(err) ctx, cancel = context.WithCancel(context.Background()) node, err = core.NewNode(ctx, &core.BuildCfg{ Repo: r, Online: true, }) log.IfFatal(err) if err := node.Routing.Provide(ctx, k); log.If(err) { cancel() log.If(node.Close()) log.Println("retrying...") continue } break } if i == 10 { log.Fatal("cannot provide a key to network") } self := &Self{ RootPath: rootPath, ipfsNode: node, ctx: ctx, cancel: cancel, cfg: cfg, } self.follow = FromStringSlice(cfg.FollowPeers, self) parent, err := self.ToPeer().GetDAGNode("") if log.If(err) { parent = &merkledag.Node{} } self.myIpns, err = parent.Key() log.IfFatal(err) if _, err = parent.GetNodeLink(rootPath); err != nil { log.Println("initializing DAGs for saving status") self.makeInitNodes(parent) } return self }
//StartListen starts listening and calls accept fucn if accepted. func (m *Self) StartListen(accept func(net.Stream) error) error { list, err := corenet.Listen(m.ipfsNode, "/app/"+m.RootPath) if log.If(err) { return err } log.Printf("starting to listen at peer: %s\n", m.ipfsNode.Identity.Pretty()) go func() { for { con, err := list.Accept() defer func() { log.If(con.Close()) }() if log.If(err) { continue } peer := con.Conn().RemotePeer() log.Printf("Connection from: %s\n", peer) p, err := FromBytes([]byte(peer), m) if log.If(err) { continue } if !p.IsAllowed() { log.Println(p, "denifed") continue } log.If(accept(con)) } }() return nil }
//LoadInitPeers loads init peers from the setting. func (m *Self) LoadInitPeers() Peers { peers := make(Peers) for _, p := range m.cfg.InitPeers.GetData() { pe, errr := New(p, m) log.Println("peer name", p) log.IfFatal(errr) peers.Add(pe) } log.Println("loaded init peers") if len(peers) == 0 { log.Println("Warning: no peers in init_peers.txt") } err := m.WritePeers(peers) log.IfFatal(err) return peers }
//New reeturns Manager obj. func New(cfg *config.Config, rootPath string) (*Manager, error) { self := peer.NewSelf(cfg, rootPath) m := &Manager{ self: self, } p := self.ToPeer() recent, err := p.ReadRecent() if log.If(err) { log.Println(err) } m.recent, err = thread.NewList(self, recent) m.peers, err = p.ReadPeers() log.If(err) if len(m.peers) == 0 { m.peers = self.LoadInitPeers() } m.tags, err = p.ReadTags() log.If(err) m.spams, err = p.ReadSpams() log.If(err) m.readThreads = self.ReadThreads() if err := self.StartListen(m.accept); log.If(err) { return nil, err } go func() { for { m.cron() time.Sleep(time.Hour) } }() return m, nil }
//WritePeersToDAG writes peer list and returns merkledag key. func (m *Self) WritePeersToDAG(peers Peers, kprev key.Key) (key.Key, error) { log.Println("writing peers prev:", kprev) var nodes NodesProto nodes.Id = make([][]byte, len(peers)) i := 0 for _, p := range peers { nodes.Id[i] = []byte(p.ID) i++ } dat, err := proto.Marshal(&nodes) if log.If(err) { return "", err } n := &merkledag.Node{Data: dat} if kprev != "" { prev, errr := m.GetDAGNode(kprev) if log.If(errr) { return "", errr } if err = n.AddNodeLink("prev", prev); log.If(err) { return "", err } } k, err := m.AddDAGNode(n, true) if log.If(err) { return "", err } return k, nil }
//GetDAGNode returns merkledag node. func (m *Self) GetDAGNode(k key.Key) (*merkledag.Node, error) { log.Println("get dag node key", k) n, err := m.ipfsNode.DAG.Get(m.ctx, k) if log.If(err) { return nil, err } return n, nil }
func (p *Peer) readDAG(pt string, obj proto.Message) error { log.Println("reading DAG from", pt) pa := p.myself.RootPath + "/" + pt n, err := p.GetDAGNode(pa) if log.If(err) { return err } return proto.Unmarshal(n.Data, obj) }
//check checks the record. i.e. check that it has valid Stamp, Thread, and valid pubKey if Signed. func (r *Record) check(mustSigned bool) error { if r.Stamp.UnixNano() <= 0 || r.Stamp.After(time.Now()) { err := errors.New("Stamp not found") log.Println(err) return err } if r.Thread == "" { err := errors.New("Thread not found") log.Println(err) return err } if mustSigned && r.Sign == nil { err := errors.New("not Signed") log.Println(err) return err } if r.Sign == nil { return nil } pubKey := r.Contents["pubkey"] if pubKey == nil { err := errors.New("no pubKey") log.Println(err) return err } pk, err := crypto.UnmarshalPublicKey(pubKey) if log.If(err) { return err } ok, err := pk.Verify([]byte(r.Key), r.Sign) if err == nil && !ok { err = errors.New("Sign unmatched") } if log.If(err) { return err } /* if !r.self.cfg.RegSpam.Check(r.Contents) { err := errors.New("regarded as spam") log.Println(err) return err } */ return nil }
func fromString(datastr string) (*linkName, error) { if !strings.HasPrefix(datastr, linkNamePrefix) { err := errors.New("don't have fixed prefix") log.Println(err) return nil, err } data := []byte(datastr[len(linkNamePrefix):]) if len(data) != lenName { err := errors.New("illegal length of data") log.Println(err) return nil, err } stamp := time.Unix(0, int64(binary.BigEndian.Uint64(data))) log.Println(stamp) l := &linkName{ stamp: stamp, } return l, nil }
//GetDAGNode gets dag node from path ph. func (p *Peer) GetDAGNode(ph string) (*merkledag.Node, error) { log.Println("getting dag from", ph) k, err := p.nameResolve() if log.If(err) { return nil, err } node, err := p.myself.GetPathNode(k, ph) log.If(err) return node, err }
func (m *Manager) broadcast(prev key.Key) error { log.Println("broadcasting...") m.mutex.RLock() defer m.mutex.RUnlock() const numcasts = 5 var err error num := 0 var peers peer.Peers for ; prev != ""; num++ { var p peer.Peers p, prev, err = m.self.ReadPeersFromDAG(prev) if log.If(err) { return err } peers.Extend(p) } var pf float32 = 1 for i := 0; i < num; i++ { pf *= 0.7 } pf = 0.8*pf + 0.2 rand.Seed(time.Now().UnixNano()) if pf < rand.Float32() { log.Println("Pf < rand") return nil } ps := m.peers.Excludes(peers, numcasts) pk, err := m.self.WritePeersToDAG(ps, prev) if log.If(err) { return err } for _, p := range ps { log.Println("broadcasting", p) go func(p *peer.Peer) { _, err = m.self.ExchangeRecent(p, m.recent.Key(), pk) log.If(err) }(p) } return nil }
//Equals returns true if r==r2 func (r *Record) Equals(r2 *Record) bool { if r.Thread != r2.Thread { log.Println("unmatched threadname") return false } if bytes.Compare(r.Sign, r2.Sign) != 0 { log.Println("unmatched sign") return false } if !r.Stamp.Equal(r2.Stamp) { log.Println("unmatched stamp") return false } if r.self != r2.self { log.Println("unmatched self") return false } if len(r.Contents) != len(r2.Contents) { log.Println("unmatched contents length") return false } for k, v := range r.Contents { v2, exist := r2.Contents[k] if !exist || bytes.Compare(v, v2) != 0 { log.Println("unmatched contents", k) return false } } return true }
//AddPeer adds one peer and writes keys of peers func (m *Manager) AddPeer(peer *peer.Peer) error { m.mutex.Lock() defer m.mutex.Unlock() if !peer.IsAllowed() { errr := errors.New("denied") log.Println(errr) return errr } if !peer.IsAllowed() || !m.peers.Add(peer) { return nil } return m.self.WritePeers(m.peers) }
//AddDAGNode adds dagNode and returns key func (m *Self) AddDAGNode(dagNode *merkledag.Node, pin bool) (key.Key, error) { if err := m.ipfsNode.DAG.AddRecursive(dagNode); log.If(err) { return "", err } k, err := dagNode.Key() if log.If(err) { return "", err } log.Println("added DAG", k.B58String()) if pin { err = m.ipfsNode.Pinning.Pin(m.ctx, dagNode, true) } log.If(err) return k, err }
func (t *Thread) next(root *merkledag.Node) (*merkledag.Node, error) { var err error link, err := getLinkName(root) if log.If(err) { return nil, err } if link == nil { return nil, nil } log.Println(link.stamp) root, err = t.self.GetLinkedNode(root, link.string()) if log.If(err) { return nil, err } return root, nil }
//Search serrches nearest and bigger than record r. func (t *Thread) Search(stamp time.Time) (*merkledag.Node, bool, error) { troot, err := t.self.GetDAGNode(t.root) if log.If(err) { return nil, false, err } var dag *merkledag.Node var found bool _, err = t.search(troot, stamp, func(exist bool, n *merkledag.Node) (bool, error) { log.Println("!!!") found = exist dag = n return false, nil }) log.If(err) return dag, found, err }
//AddPeers adds peers and writes keys of peers func (m *Manager) AddPeers(peers peer.Peers) error { m.mutex.Lock() defer m.mutex.Unlock() added := false for _, peer := range peers { if !peer.IsAllowed() { err := errors.New("denied") log.Println(err) continue } added = added || m.peers.Add(peer) } if !added { return nil } return m.self.WritePeers(m.peers) }
//New returns Thread obj. func New(self *peer.Self, name string, root key.Key) (*Thread, error) { if root == "" { var err error r := merkledag.Node{} root, err = r.Key() if log.If(err) { return nil, err } log.Println("root key", root) } t := &Thread{ self: self, name: name, root: root, } return t, nil }
//Merge adds records from merkledag key and returns true if thread was changed. func (t *Thread) Merge(key key.Key) (bool, error) { from, err := t.self.GetDAGNode(key) if log.If(err) { return false, err } root, err := t.next(from) if log.If(err) { return false, err } updated := false for root != nil { r, err := t.toRecord(root) if log.If(err) { return updated, err } n, found, err := t.Search(r.Stamp) if log.If(err) { return updated, err } nk, err := n.Key() if log.If(err) { return updated, err } rk, err := root.Key() if log.If(err) { return updated, err } if nk == rk { return updated, nil } if !found { u, errr := t.Add(r) if log.If(errr) { return updated, errr } log.Println("added") updated = updated || u } root, err = t.next(root) if log.If(err) { return updated, err } } return updated, nil }
//Load fills a struct cfg which usually embeds Config struct from the json file. func Load(appl, p string, cfg interface{}) { files := []string{p, "file", "/usr/local/etc/" + appl, "/etc/" + appl} usr, err := user.Current() if err == nil { files = append(files, path.Join(usr.HomeDir, "."+appl)) } for _, f := range files { if f == "" { continue } f = filepath.Join(f, appl+".json") dat, errr := ioutil.ReadFile(f) if errr != nil { continue } log.Println("loading config from", f) log.IfFatal(json.Unmarshal(dat, cfg)) } }
//ReadPeersFromDAG reads peer list from merkledag keyed k. func (m *Self) ReadPeersFromDAG(k key.Key) (Peers, key.Key, error) { log.Println("reading peer DAG", k) var ps NodesProto n, err := m.GetDAGNode(k) if log.If(err) { return nil, "", err } if err := proto.Unmarshal(n.Data, &ps); log.If(err) { return nil, "", err } p, err := fromProto(ps, m) if log.If(err) { return nil, "", err } var prevkey key.Key prev, err := n.GetNodeLink("prev") if err == nil { prevkey = key.Key(prev.Hash) } return p, prevkey, nil }
//GetPathNode searches merkledag from root key to path recursively. func (m *Self) GetPathNode(root key.Key, pt string) (*merkledag.Node, error) { var err error n, err := m.GetDAGNode(root) if log.If(err) { return nil, err } for _, s := range strings.Split(pt, "/") { if s == "" || s == "." { continue } n, err = n.GetLinkedNode(m.ctx, m.ipfsNode.DAG, s) if log.If(err) { return nil, err } if n == nil { err = errors.New("merkledag is nil") log.Println(err) return nil, err } } return n, nil }
//ReadRequest reads hash of recent ahd peers DAG from con. func ReadRequest(con net.Stream) (key.Key, key.Key, error) { rdat, err := ioutil.ReadAll(con) if log.If(err) { return "", "", err } var rmsg Msg if err := proto.Unmarshal(rdat, &rmsg); log.If(err) { return "", "", err } if *rmsg.Type != Type_Recent { err := errors.New("undefined type") log.Println(err) return "", "", err } var r, p key.Key if rmsg.Recent != nil { r = key.Key(rmsg.Recent) } if rmsg.Peers != nil { p = key.Key(rmsg.Peers) } return r, p, nil }
func initializeIpnsKeyspace(repoRoot string) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() r, err := fsrepo.Open(repoRoot) if log.If(err) { // NB: repo is owned by the node return err } nd, err := core.NewNode(ctx, &core.BuildCfg{Repo: r}) if log.If(err) { return err } defer func() { log.If(nd.Close()) }() if err := nd.SetupOfflineRouting(); err != nil { log.Println(err) return err } return namesys.InitializeKeyspace(ctx, nd.DAG, nd.Namesys, nd.Pinning, nd.PrivateKey) }