github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/node.go (about)

     1  // Copyright (C) 2013-2017, The MetaCurrency Project (Eric Harris-Braun, Arthur Brock, et. al.)
     2  // Use of this source code is governed by GPLv3 found in the LICENSE file
     3  //----------------------------------------------------------------------------------------
     4  
     5  // node implements ipfs network transport for communicating between holochain nodes
     6  
     7  package holochain
     8  
     9  import (
    10  	"context"
    11  	//	host "github.com/libp2p/go-libp2p-host"
    12  	"encoding/gob"
    13  	"errors"
    14  	"fmt"
    15  
    16  	. "github.com/holochain/holochain-proto/hash"
    17  	goprocess "github.com/jbenet/goprocess"
    18  	goprocessctx "github.com/jbenet/goprocess/context"
    19  	ic "github.com/libp2p/go-libp2p-crypto"
    20  	nat "github.com/libp2p/go-libp2p-nat"
    21  	net "github.com/libp2p/go-libp2p-net"
    22  	peer "github.com/libp2p/go-libp2p-peer"
    23  	pstore "github.com/libp2p/go-libp2p-peerstore"
    24  	protocol "github.com/libp2p/go-libp2p-protocol"
    25  	swarm "github.com/libp2p/go-libp2p-swarm"
    26  	discovery "github.com/libp2p/go-libp2p/p2p/discovery"
    27  	bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
    28  	rhost "github.com/libp2p/go-libp2p/p2p/host/routed"
    29  	ma "github.com/multiformats/go-multiaddr"
    30  	mh "github.com/multiformats/go-multihash"
    31  	"gopkg.in/mgo.v2/bson"
    32  	"io"
    33  	"math/big"
    34  	"math/rand"
    35  	go_net "net"
    36  	"strconv"
    37  	"strings"
    38  	"sync"
    39  	"time"
    40  )
    41  
    42  type ReceiverFn func(h *Holochain, m *Message) (response interface{}, err error)
    43  
    44  type MsgType int8
    45  
    46  // @TODO don't have order dependant constants
    47  // https://github.com/holochain/holochain-proto/issues/713
    48  const (
    49  	// common messages
    50  
    51  	ERROR_RESPONSE MsgType = iota
    52  	OK_RESPONSE
    53  
    54  	// DHT messages
    55  
    56  	PUT_REQUEST
    57  	DEL_REQUEST
    58  	MOD_REQUEST
    59  	GET_REQUEST
    60  	LINK_REQUEST
    61  	GETLINK_REQUEST
    62  	DELETELINK_REQUEST
    63  
    64  	// Gossip messages
    65  
    66  	GOSSIP_REQUEST
    67  
    68  	// Validate Messages
    69  
    70  	VALIDATE_PUT_REQUEST
    71  	VALIDATE_LINK_REQUEST
    72  	VALIDATE_DEL_REQUEST
    73  	VALIDATE_MOD_REQUEST
    74  
    75  	// Application Messages
    76  
    77  	APP_MESSAGE
    78  
    79  	// Peer messages
    80  
    81  	LISTADD_REQUEST
    82  
    83  	// Kademlia messages
    84  
    85  	FIND_NODE_REQUEST
    86  )
    87  
    88  func (msgType MsgType) String() string {
    89  	return []string{"ERROR_RESPONSE",
    90  		"OK_RESPONSE",
    91  		"PUT_REQUEST",
    92  		"DEL_REQUEST",
    93  		"MOD_REQUEST",
    94  		"GET_REQUEST",
    95  		"LINK_REQUEST",
    96  		"GETLINK_REQUEST",
    97  		"DELETELINK_REQUEST",
    98  		"GOSSIP_REQUEST",
    99  		"VALIDATE_PUT_REQUEST",
   100  		"VALIDATE_LINK_REQUEST",
   101  		"VALIDATE_DEL_REQUEST",
   102  		"VALIDATE_MOD_REQUEST",
   103  		"APP_MESSAGE",
   104  		"LISTADD_REQUEST",
   105  		"FIND_NODE_REQUEST"}[msgType]
   106  }
   107  
   108  var ErrBlockedListed = errors.New("node blockedlisted")
   109  
   110  // Message represents data that can be sent to node in the network
   111  type Message struct {
   112  	Type MsgType
   113  	Time time.Time
   114  	From peer.ID
   115  	Body interface{}
   116  }
   117  
   118  type BytesSent struct {
   119  	Bytes   int64
   120  	MsgType MsgType
   121  }
   122  
   123  var BytesSentChan chan BytesSent
   124  
   125  const (
   126  	RetryingStopper = iota
   127  	GossipingStopper
   128  	BootstrappingStopper
   129  	RefreshingStopper
   130  	HoldingStopper
   131  	_StopperCount
   132  )
   133  
   134  // Node represents a node in the network
   135  type Node struct {
   136  	HashAddr     peer.ID
   137  	NetAddr      ma.Multiaddr
   138  	host         *rhost.RoutedHost
   139  	mdnsSvc      discovery.Service
   140  	blockedlist  map[peer.ID]bool
   141  	protocols    [_protocolCount]*Protocol
   142  	peerstore    pstore.Peerstore
   143  	routingTable *RoutingTable
   144  	nat          *nat.NAT
   145  	log          *Logger
   146  
   147  	// ticker task stoppers
   148  	stoppers []chan bool
   149  
   150  	// items for the kademlia implementation
   151  	plk   sync.Mutex
   152  	peers map[peer.ID]*peerTracker
   153  	ctx   context.Context
   154  	proc  goprocess.Process
   155  }
   156  
   157  // Protocol encapsulates data for our different protocols
   158  type Protocol struct {
   159  	ID       protocol.ID
   160  	Receiver ReceiverFn
   161  }
   162  
   163  const (
   164  	ActionProtocol = iota
   165  	ValidateProtocol
   166  	GossipProtocol
   167  	KademliaProtocol
   168  	_protocolCount
   169  )
   170  
   171  const (
   172  	PeerTTL                       = time.Minute * 10
   173  	DefaultRoutingRefreshInterval = time.Minute
   174  	DefaultGossipInterval         = time.Second * 2
   175  	DefaultHoldingCheckInterval   = time.Second * 30
   176  )
   177  
   178  // implement peer found function for mdns discovery
   179  func (h *Holochain) HandlePeerFound(pi pstore.PeerInfo) {
   180  	if h.dht != nil {
   181  		h.dht.dlog.Logf("discovered peer via mdns: %v", pi)
   182  		err := h.AddPeer(pi)
   183  		if err != nil {
   184  			h.dht.dlog.Logf("error when adding peer: %v, %v", pi, err)
   185  		}
   186  	}
   187  }
   188  
   189  func (h *Holochain) getNodePubKey(ID peer.ID) (pubKey ic.PubKey, err error) {
   190  	req := GetReq{H: HashFromPeerID(ID), GetMask: GetMaskEntry}
   191  	var rsp interface{}
   192  	rsp, err = callGet(h, req, &GetOptions{GetMask: req.GetMask})
   193  	if err != nil {
   194  		return
   195  	}
   196  	e := rsp.(GetResp).Entry
   197  	pubKey, err = DecodePubKey(e.Content().(string))
   198  	if err != nil {
   199  		return
   200  	}
   201  	var pkID peer.ID
   202  	pkID, err = peer.IDFromPublicKey(pubKey)
   203  	if err != nil {
   204  		return
   205  	}
   206  	if pkID != ID {
   207  		err = errors.New("Public Key doesn't match Node ID!")
   208  		return
   209  	}
   210  	return
   211  }
   212  
   213  func (h *Holochain) addPeer(pi pstore.PeerInfo, confirm bool) (err error) {
   214  	// add the peer into the peerstore
   215  	h.node.peerstore.AddAddrs(pi.ID, pi.Addrs, PeerTTL)
   216  
   217  	// attempt a connection to see if this is actually valid
   218  	if confirm {
   219  		err = h.node.host.Connect(h.node.ctx, pi)
   220  	}
   221  	if err != nil {
   222  		h.dht.dlog.Logf("Clearing peer %v, connection failed (%v)\n", pi.ID, err)
   223  		h.node.peerstore.ClearAddrs(pi.ID)
   224  		err = nil
   225  	} else {
   226  		bootstrap := h.node.routingTable.IsEmpty()
   227  		h.dht.dlog.Logf("Adding Peer: %v\n", pi.ID)
   228  		h.node.routingTable.Update(pi.ID)
   229  		err = h.dht.AddGossiper(pi.ID)
   230  		if err != nil {
   231  			return
   232  		}
   233  		if bootstrap {
   234  			RoutingRefreshTask(h)
   235  		}
   236  
   237  		var pubKey ic.PubKey
   238  		if confirm {
   239  			pubKey, err = h.getNodePubKey(pi.ID)
   240  			if err != nil {
   241  				return
   242  			}
   243  		}
   244  		if h.Config.EnableWorldModel {
   245  			h.world.AddNode(pi, pubKey)
   246  		}
   247  	}
   248  
   249  	return
   250  }
   251  
   252  // RoutingRefreshTask fills the routing table by searching for a random node
   253  func RoutingRefreshTask(h *Holochain) {
   254  	s := fmt.Sprintf("%d", rand.Intn(1000000))
   255  	var hash Hash
   256  	hash, err := Sum(h.hashSpec, []byte(s))
   257  	if err == nil {
   258  		h.node.FindPeer(h.node.ctx, PeerIDFromHash(hash))
   259  	}
   260  }
   261  
   262  func (node *Node) isPeerActive(id peer.ID) bool {
   263  	// inactive currently defined by seeing if there are any addrs in the
   264  	// peerstore
   265  	// TODO: should be something different
   266  	addrs := node.peerstore.Addrs(id)
   267  	return len(addrs) > 0
   268  }
   269  
   270  // filterInactviePeers removes peers from a list who are currently inactive
   271  // if max >  0 returns only max number of peers
   272  func (node *Node) filterInactviePeers(peersIn []peer.ID, max int) (peersOut []peer.ID) {
   273  	if max <= 0 {
   274  		max = len(peersIn)
   275  	}
   276  	var i int
   277  	for _, p := range peersIn {
   278  		if node.isPeerActive(p) {
   279  			peersOut = append(peersOut, p)
   280  			i += 1
   281  			if i == max {
   282  				return
   283  			}
   284  		}
   285  	}
   286  	return
   287  }
   288  
   289  // AddPeer adds a peer to the peerstore if it passes various checks
   290  func (h *Holochain) AddPeer(pi pstore.PeerInfo) (err error) {
   291  	// to protect against crashes from background routines after close
   292  	if h.node == nil || h.dht == nil {
   293  		return
   294  	}
   295  	h.dht.dlog.Logf("Adding Peer Req: %v my node %v\n", pi.ID, h.node.HashAddr)
   296  	if pi.ID == h.node.HashAddr {
   297  		return
   298  	}
   299  	if h.node.IsBlocked(pi.ID) {
   300  		err = ErrBlockedListed
   301  	} else {
   302  		err = h.addPeer(pi, true)
   303  	}
   304  	return
   305  }
   306  
   307  func (n *Node) EnableMDNSDiscovery(h *Holochain, interval time.Duration) (err error) {
   308  	ctx := context.Background()
   309  	tag := h.dnaHash.String() + "._udp"
   310  	n.mdnsSvc, err = discovery.NewMdnsService(ctx, n.host, interval, tag)
   311  	if err != nil {
   312  		return
   313  	}
   314  	n.mdnsSvc.RegisterNotifee(h)
   315  	return
   316  }
   317  
   318  func (n *Node) ExternalAddr() ma.Multiaddr {
   319  	if n.nat == nil {
   320  		return n.NetAddr
   321  	} else {
   322  		mappings := n.nat.Mappings()
   323  		for i := 0; i < len(mappings); i++ {
   324  			external_addr, err := mappings[i].ExternalAddr()
   325  			if err == nil {
   326  				return external_addr
   327  			}
   328  		}
   329  		return n.NetAddr
   330  	}
   331  }
   332  
   333  func (node *Node) discoverAndHandleNat(listenPort int) {
   334  	node.log.Logf("Looking for a NAT...")
   335  	node.nat = nat.DiscoverNAT()
   336  	if node.nat == nil {
   337  		node.log.Logf("No NAT found.")
   338  	} else {
   339  		node.log.Logf("Discovered NAT! Trying to aquire public port mapping via UPnP...")
   340  		ifaces, _ := go_net.Interfaces()
   341  		// handle err
   342  		for _, i := range ifaces {
   343  			addrs, _ := i.Addrs()
   344  			// handle err
   345  			for _, addr := range addrs {
   346  				var ip go_net.IP
   347  				switch v := addr.(type) {
   348  				case *go_net.IPNet:
   349  					ip = v.IP
   350  				case *go_net.IPAddr:
   351  					ip = v.IP
   352  				}
   353  				if ip.Equal(go_net.IPv4(127, 0, 0, 1)) {
   354  					continue
   355  				}
   356  				addr_string := fmt.Sprintf("/ip4/%s/tcp/%d", ip, listenPort)
   357  				localaddr, err := ma.NewMultiaddr(addr_string)
   358  				if err == nil {
   359  					node.log.Logf("NAT: trying to establish NAT mapping for %s...", addr_string)
   360  					node.nat.NewMapping(localaddr)
   361  				}
   362  			}
   363  		}
   364  
   365  		external_addr := node.ExternalAddr()
   366  
   367  		if external_addr != node.NetAddr {
   368  			node.log.Logf("NAT: successfully created port mapping! External address is: %s", external_addr.String())
   369  		} else {
   370  			node.log.Logf("NAT: could not create port mappping. Keep trying...")
   371  			Infof("NAT:-------------------------------------------------------")
   372  			Infof("NAT:---------------------Warning---------------------------")
   373  			Infof("NAT:-------------------------------------------------------")
   374  			Infof("NAT: You seem to be behind a NAT that does not speak UPnP.")
   375  			Infof("NAT: You will have to setup a port forwarding manually.")
   376  			Infof("NAT: This instance is configured to listen on port: %d", listenPort)
   377  			Infof("NAT:-------------------------------------------------------")
   378  		}
   379  
   380  	}
   381  }
   382  
   383  // NewNode creates a new node with given multiAddress listener string and identity
   384  func NewNode(listenAddr string, protoMux string, agent *LibP2PAgent, enableNATUPnP bool, log *Logger) (node *Node, err error) {
   385  	var n Node
   386  	n.log = log
   387  	n.log.Logf("Creating new node with protoMux: %s\n", protoMux)
   388  	nodeID, _, err := agent.NodeID()
   389  	if err != nil {
   390  		return
   391  	}
   392  	n.log.Logf("NodeID is: %v\n", nodeID)
   393  
   394  	listenPort, err := strconv.Atoi(strings.Split(listenAddr, "/")[4])
   395  	if err != nil {
   396  		Infof("Can't parse port from Multiaddress string: %s", listenAddr)
   397  		return
   398  	}
   399  
   400  	n.NetAddr, err = ma.NewMultiaddr(listenAddr)
   401  	if err != nil {
   402  		return
   403  	}
   404  
   405  	if enableNATUPnP {
   406  		n.discoverAndHandleNat(listenPort)
   407  	}
   408  
   409  	ps := pstore.NewPeerstore()
   410  	n.peerstore = ps
   411  	ps.AddAddrs(nodeID, []ma.Multiaddr{n.NetAddr}, pstore.PermanentAddrTTL)
   412  
   413  	n.HashAddr = nodeID
   414  	priv := agent.PrivKey()
   415  	ps.AddPrivKey(nodeID, priv)
   416  	ps.AddPubKey(nodeID, priv.GetPublic())
   417  
   418  	validateProtocolString := "/hc-validate-" + protoMux + "/0.0.0"
   419  	gossipProtocolString := "/hc-gossip-" + protoMux + "/0.0.0"
   420  	actionProtocolString := "/hc-action-" + protoMux + "/0.0.0"
   421  	kademliaProtocolString := "/hc-kademlia-" + protoMux + "/0.0.0"
   422  
   423  	n.log.Logf("Validate protocol identifier: " + validateProtocolString)
   424  	n.log.Logf("Gossip protocol identifier: " + gossipProtocolString)
   425  	n.log.Logf("Action protocol identifier: " + actionProtocolString)
   426  	n.log.Logf("Kademlia protocol identifier: " + kademliaProtocolString)
   427  
   428  	n.protocols[ValidateProtocol] = &Protocol{protocol.ID(validateProtocolString), ValidateReceiver}
   429  	n.protocols[GossipProtocol] = &Protocol{protocol.ID(gossipProtocolString), GossipReceiver}
   430  	n.protocols[ActionProtocol] = &Protocol{protocol.ID(actionProtocolString), ActionReceiver}
   431  	n.protocols[KademliaProtocol] = &Protocol{protocol.ID(kademliaProtocolString), KademliaReceiver}
   432  
   433  	n.stoppers = make([]chan bool, _StopperCount)
   434  
   435  	ctx := context.Background()
   436  	n.ctx = ctx
   437  
   438  	// create a new swarm to be used by the service host
   439  	netw, err := swarm.NewNetwork(ctx, []ma.Multiaddr{n.NetAddr}, nodeID, ps, nil)
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	var bh *bhost.BasicHost
   445  	bh, err = bhost.New(netw), nil
   446  	if err != nil {
   447  		return
   448  	}
   449  
   450  	n.host = rhost.Wrap(bh, &n)
   451  
   452  	m := pstore.NewMetrics()
   453  	n.routingTable = NewRoutingTable(KValue, nodeID, time.Minute, m)
   454  	n.peers = make(map[peer.ID]*peerTracker)
   455  
   456  	node = &n
   457  
   458  	n.host.Network().Notify((*netNotifiee)(node))
   459  
   460  	n.proc = goprocessctx.WithContextAndTeardown(ctx, func() error {
   461  		// remove ourselves from network notifs.
   462  		n.host.Network().StopNotify((*netNotifiee)(node))
   463  		return n.host.Close()
   464  	})
   465  
   466  	return
   467  }
   468  
   469  // Encode codes a message to gob format
   470  // @TODO generalize for other message encoding formats
   471  func (m *Message) Encode() (data []byte, err error) {
   472  	data, err = ByteEncoder(m)
   473  	if err != nil {
   474  		return
   475  	}
   476  	return
   477  }
   478  
   479  // Decode converts a message from gob format
   480  // @TODO generalize for other message encoding formats
   481  func (m *Message) Decode(r io.Reader) (err error) {
   482  	dec := gob.NewDecoder(r)
   483  	err = dec.Decode(m)
   484  	return
   485  }
   486  
   487  // Fingerprint creates a hash of a message
   488  func (m *Message) Fingerprint() (f Hash, err error) {
   489  	var data []byte
   490  	if m != nil {
   491  		data, err = bson.Marshal(m)
   492  
   493  		if err != nil {
   494  			return
   495  		}
   496  		// TODO should just use hash.Sum Code and length not available?
   497  		var multiH mh.Multihash
   498  		multiH, err = mh.Sum(data, mh.SHA2_256, -1)
   499  		f = Hash(multiH)
   500  	} else {
   501  		f = NullHash()
   502  	}
   503  
   504  	return
   505  }
   506  
   507  // String converts a message to a nice string
   508  func (m Message) String() string {
   509  	return fmt.Sprintf("%v @ %v From:%v Body:%v", m.Type, m.Time, m.From, m.Body)
   510  }
   511  
   512  // respondWith writes a message either error or otherwise, to the stream
   513  func (node *Node) respondWith(s net.Stream, err error, body interface{}) {
   514  	var m *Message
   515  	if err != nil {
   516  		errResp := NewErrorResponse(err)
   517  		errResp.Payload = body
   518  		m = node.NewMessage(ERROR_RESPONSE, errResp)
   519  	} else {
   520  		m = node.NewMessage(OK_RESPONSE, body)
   521  	}
   522  
   523  	data, err := m.Encode()
   524  	if err != nil {
   525  		Infof("Response failed: unable to encode message: %v", m)
   526  	}
   527  	var n int
   528  	n, err = s.Write(data)
   529  	if err != nil {
   530  		Infof("Response failed: write returned error: %v", err)
   531  	}
   532  	if BytesSentChan != nil {
   533  		b := BytesSent{Bytes: int64(n), MsgType: m.Type}
   534  		BytesSentChan <- b
   535  	}
   536  }
   537  
   538  // StartProtocol initiates listening for a protocol on the node
   539  func (node *Node) StartProtocol(h *Holochain, proto int) (err error) {
   540  	node.host.SetStreamHandler(node.protocols[proto].ID, func(s net.Stream) {
   541  		var m Message
   542  		err := m.Decode(s)
   543  		var response interface{}
   544  		if m.From == "" {
   545  			// @todo other sanity checks on From?
   546  			err = errors.New("message must have a source")
   547  		} else {
   548  			if node.IsBlocked(s.Conn().RemotePeer()) {
   549  				err = ErrBlockedListed
   550  			}
   551  
   552  			if err == nil {
   553  				response, err = node.protocols[proto].Receiver(h, &m)
   554  			}
   555  		}
   556  		node.respondWith(s, err, response)
   557  	})
   558  	return
   559  }
   560  
   561  // Close shuts down the node
   562  func (node *Node) Close() error {
   563  	for i, stopper := range node.stoppers {
   564  		if stopper != nil {
   565  			stop := node.stoppers[i]
   566  			node.stoppers[i] = nil
   567  			stop <- true
   568  		}
   569  	}
   570  	return node.proc.Close()
   571  }
   572  
   573  // Send delivers a message to a node via the given protocol
   574  func (node *Node) Send(ctx context.Context, proto int, addr peer.ID, m *Message) (response Message, err error) {
   575  
   576  	if node.IsBlocked(addr) {
   577  		err = ErrBlockedListed
   578  		return
   579  	}
   580  
   581  	s, err := node.host.NewStream(ctx, addr, node.protocols[proto].ID)
   582  	if err != nil {
   583  		return
   584  	}
   585  	defer s.Close()
   586  
   587  	// encode the message and send it
   588  	data, err := m.Encode()
   589  	if err != nil {
   590  		return
   591  	}
   592  
   593  	n, err := s.Write(data)
   594  	if err != nil {
   595  		return
   596  	}
   597  	if n != len(data) {
   598  		err = errors.New("unable to send all data")
   599  	}
   600  	if BytesSentChan != nil {
   601  		b := BytesSent{Bytes: int64(n), MsgType: m.Type}
   602  		BytesSentChan <- b
   603  	}
   604  
   605  	// decode the response
   606  	err = response.Decode(s)
   607  	if err != nil {
   608  		node.log.Logf("failed to decode with err:%v ", err)
   609  		return
   610  	}
   611  	return
   612  }
   613  
   614  // NewMessage creates a message from the node with a new current timestamp
   615  func (node *Node) NewMessage(t MsgType, body interface{}) (msg *Message) {
   616  	m := Message{Type: t, Time: time.Now().Round(0), Body: body, From: node.HashAddr}
   617  	msg = &m
   618  	return
   619  }
   620  
   621  // IsBlockedListed checks to see if a node is on the blockedlist
   622  func (node *Node) IsBlocked(addr peer.ID) (ok bool) {
   623  	ok = node.blockedlist[addr]
   624  	return
   625  }
   626  
   627  // InitBlockedList sets up the blockedlist from a PeerList
   628  func (node *Node) InitBlockedList(list PeerList) {
   629  	node.blockedlist = make(map[peer.ID]bool)
   630  	for _, r := range list.Records {
   631  		node.Block(r.ID)
   632  	}
   633  }
   634  
   635  // Block adds a peer to the blocklist
   636  func (node *Node) Block(addr peer.ID) {
   637  	if node.blockedlist == nil {
   638  		node.blockedlist = make(map[peer.ID]bool)
   639  	}
   640  	node.blockedlist[addr] = true
   641  }
   642  
   643  // Unblock removes a peer from the blocklist
   644  func (node *Node) Unblock(addr peer.ID) {
   645  	if node.blockedlist != nil {
   646  		delete(node.blockedlist, addr)
   647  	}
   648  }
   649  
   650  type ErrorResponse struct {
   651  	Code    int
   652  	Message string
   653  	Payload interface{}
   654  }
   655  
   656  const (
   657  	ErrUnknownCode = iota
   658  	ErrHashNotFoundCode
   659  	ErrHashDeletedCode
   660  	ErrHashModifiedCode
   661  	ErrHashRejectedCode
   662  	ErrLinkNotFoundCode
   663  	ErrEntryTypeMismatchCode
   664  	ErrBlockedListedCode
   665  )
   666  
   667  // NewErrorResponse encodes standard errors for transmitting
   668  func NewErrorResponse(err error) (errResp ErrorResponse) {
   669  	switch err {
   670  	case ErrHashNotFound:
   671  		errResp.Code = ErrHashNotFoundCode
   672  	case ErrHashDeleted:
   673  		errResp.Code = ErrHashDeletedCode
   674  	case ErrHashModified:
   675  		errResp.Code = ErrHashModifiedCode
   676  	case ErrHashRejected:
   677  		errResp.Code = ErrHashRejectedCode
   678  	case ErrLinkNotFound:
   679  		errResp.Code = ErrLinkNotFoundCode
   680  	case ErrEntryTypeMismatch:
   681  		errResp.Code = ErrEntryTypeMismatchCode
   682  	case ErrBlockedListed:
   683  		errResp.Code = ErrBlockedListedCode
   684  	default:
   685  		errResp.Message = err.Error() //Code will be set to ErrUnknown by default cus it's 0
   686  	}
   687  	return
   688  }
   689  
   690  // DecodeResponseError creates a go error object from the ErrorResponse data
   691  func (errResp ErrorResponse) DecodeResponseError() (err error) {
   692  	switch errResp.Code {
   693  	case ErrHashNotFoundCode:
   694  		err = ErrHashNotFound
   695  	case ErrHashDeletedCode:
   696  		err = ErrHashDeleted
   697  	case ErrHashModifiedCode:
   698  		err = ErrHashModified
   699  	case ErrHashRejectedCode:
   700  		err = ErrHashRejected
   701  	case ErrLinkNotFoundCode:
   702  		err = ErrLinkNotFound
   703  	case ErrEntryTypeMismatchCode:
   704  		err = ErrEntryTypeMismatch
   705  	case ErrBlockedListedCode:
   706  		err = ErrBlockedListed
   707  	default:
   708  		err = errors.New(errResp.Message)
   709  	}
   710  	return
   711  }
   712  
   713  func distance(id peer.ID, hash Hash) *big.Int {
   714  	h := HashFromPeerID(id)
   715  	return HashXORDistance(h, hash)
   716  }
   717  
   718  // Distance returns the nodes peer distance to another node for purposes of gossip
   719  func (node *Node) Distance(id peer.ID) *big.Int {
   720  	return distance(id, HashFromPeerID(node.HashAddr))
   721  }
   722  
   723  // Context return node's context
   724  func (node *Node) Context() context.Context {
   725  	return node.ctx
   726  }
   727  
   728  // Process return node's process
   729  func (node *Node) Process() goprocess.Process {
   730  	return node.proc
   731  }