func NewChord(localNode *node.LocalNode) (*Chord, error) {
	ovl, err := overlay.NewOverlay(localNode)
	if err != nil {
		return nil, err
	}
	conf := localNode.Config
	nodeIDBits := conf.NodeIDBytes * 8
	next := NextID(localNode.Id, nodeIDBits)
	prev := PrevID(localNode.Id, nodeIDBits)
	successors, err := NewNeighborList(next, prev, nodeIDBits, conf.MinNumSuccessors, false)
	if err != nil {
		return nil, err
	}
	predecessors, err := NewNeighborList(prev, next, nodeIDBits, conf.MinNumSuccessors, true)
	if err != nil {
		return nil, err
	}
	fingerTable := make([]*NeighborList, nodeIDBits)
	for i := uint32(0); i < nodeIDBits; i++ {
		startID := PowerOffset(localNode.Id, i, nodeIDBits)
		endID := PrevID(PowerOffset(localNode.Id, i+1, nodeIDBits), nodeIDBits)
		fingerTable[i], err = NewNeighborList(startID, endID, nodeIDBits, conf.NumFingerSuccessors, false)
		if err != nil {
			return nil, err
		}
	}
	neighbors, err := NewNeighborList(next, prev, nodeIDBits, 0, false)
	if err != nil {
		return nil, err
	}
	middlewareStore := newMiddlewareStore()
	c := &Chord{
		Overlay:               ovl,
		nodeIDBits:            nodeIDBits,
		minNumSuccessors:      conf.MinNumSuccessors,
		numSuccessorsFactor:   conf.NumSuccessorsFactor,
		baseStabilizeInterval: conf.BaseStabilizeInterval,
		successors:            successors,
		predecessors:          predecessors,
		fingerTable:           fingerTable,
		neighbors:             neighbors,
		middlewareStore:       middlewareStore,
	}
	directRxMsgChan, err := localNode.GetRxMsgChan(protobuf.DIRECT)
	if err != nil {
		return nil, err
	}
	directRouting, err := routing.NewDirectRouting(ovl.LocalMsgChan, directRxMsgChan)
	if err != nil {
		return nil, err
	}
	err = ovl.AddRouter(protobuf.DIRECT, directRouting)
	if err != nil {
		return nil, err
	}
	relayRxMsgChan, err := localNode.GetRxMsgChan(protobuf.RELAY)
	if err != nil {
		return nil, err
	}
	relayRouting, err := NewRelayRouting(ovl.LocalMsgChan, relayRxMsgChan, c)
	if err != nil {
		return nil, err
	}
	err = ovl.AddRouter(protobuf.RELAY, relayRouting)
	if err != nil {
		return nil, err
	}
	broadcastRxMsgChan, err := localNode.GetRxMsgChan(protobuf.BROADCAST_PUSH)
	if err != nil {
		return nil, err
	}
	broadcastRouting, err := routing.NewBroadcastRouting(ovl.LocalMsgChan, broadcastRxMsgChan, localNode)
	if err != nil {
		return nil, err
	}
	err = ovl.AddRouter(protobuf.BROADCAST_PUSH, broadcastRouting)
	if err != nil {
		return nil, err
	}
	broadcastTreeRxMsgChan, err := localNode.GetRxMsgChan(protobuf.BROADCAST_TREE)
	if err != nil {
		return nil, err
	}
	broadcastTreeRouting, err := NewBroadcastTreeRouting(ovl.LocalMsgChan, broadcastTreeRxMsgChan, c)
	if err != nil {
		return nil, err
	}
	err = ovl.AddRouter(protobuf.BROADCAST_TREE, broadcastTreeRouting)
	if err != nil {
		return nil, err
	}
	err = localNode.ApplyMiddleware(node.RemoteNodeReady{
		Func: func(rn *node.RemoteNode) bool {
			c.addRemoteNode(rn)
			return true
		},
		Priority: 0,
	})
	if err != nil {
		return nil, err
	}
	err = localNode.ApplyMiddleware(node.RemoteNodeDisconnected{
		Func: func(rn *node.RemoteNode) bool {
			c.removeNeighbor(rn)
			return true
		},
		Priority: 0,
	})
	if err != nil {
		return nil, err
	}
	return c, nil
}
NewChord creates a Chord overlay network
package chord
import (
	"errors"
	"fmt"
	"sync"
	"time"
	"github.com/gogo/protobuf/proto"
	"github.com/nknorg/nnet/log"
	"github.com/nknorg/nnet/node"
	"github.com/nknorg/nnet/overlay"
	"github.com/nknorg/nnet/overlay/routing"
	"github.com/nknorg/nnet/protobuf"
	"github.com/nknorg/nnet/util"
)
const (
	numWorkers = 1
	joinRetries = 3
)
type Chord struct {
	*overlay.Overlay
	*middlewareStore
	nodeIDBits            uint32
	minNumSuccessors      uint32
	numSuccessorsFactor   uint32
	baseStabilizeInterval time.Duration
	successors            *NeighborList
	predecessors          *NeighborList
	fingerTable           []*NeighborList
	neighbors             *NeighborList
}