mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
Kademlia: Use information requests from updated DHT library. More testing & fixes upcoming.
This commit is contained in:
@@ -6,7 +6,7 @@ Author: Peter Kleissner
|
|||||||
Strategy for sending our IPv6 Multicast and IPv4 Broadcast messages:
|
Strategy for sending our IPv6 Multicast and IPv4 Broadcast messages:
|
||||||
* During bootstrap: Immediately at the beginning, then every 10 seconds until there is at least 1 peer.
|
* During bootstrap: Immediately at the beginning, then every 10 seconds until there is at least 1 peer.
|
||||||
* Every 10 minutes during regular operation.
|
* Every 10 minutes during regular operation.
|
||||||
* Each time a network adapter / IP change is detected. [FUTURE]
|
* Each time a network adapter / IP change is detected.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ func autoMulticastBroadcast() {
|
|||||||
// Send out multicast/broadcast immediately.
|
// Send out multicast/broadcast immediately.
|
||||||
sendMulticastBroadcast()
|
sendMulticastBroadcast()
|
||||||
|
|
||||||
// Phase 1: Resend every 10 seconds until at least 1 peer in the peer list
|
// Phase 1: Resend every 10 seconds until at least 1 peer in the peer list.
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Second * 10)
|
time.Sleep(time.Second * 10)
|
||||||
|
|
||||||
|
|||||||
72
Commands.go
72
Commands.go
@@ -7,7 +7,6 @@ Author: Peter Kleissner
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -47,22 +46,36 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) {
|
|||||||
|
|
||||||
// FIND_SELF: Requesting peers close to the sender?
|
// FIND_SELF: Requesting peers close to the sender?
|
||||||
if msg.Actions&(1<<ActionFindSelf) > 0 {
|
if msg.Actions&(1<<ActionFindSelf) > 0 {
|
||||||
|
selfD := Hash2Peer{ID: KeyHash{peer.NodeID}}
|
||||||
|
|
||||||
// do not respond the caller's own peer (add to ignore list)
|
// do not respond the caller's own peer (add to ignore list)
|
||||||
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, peer.NodeID, filterFunc(msg.connection.IsLocal(), allowIPv4, allowIPv6), peer.NodeID) {
|
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, peer.NodeID, filterFunc(msg.connection.IsLocal(), allowIPv4, allowIPv6), peer.NodeID) {
|
||||||
if info := node.Info.(*PeerInfo).peer2Info(msg.connection.IsLocal(), allowIPv4, allowIPv6); info != nil {
|
if info := node.Info.(*PeerInfo).peer2Record(msg.connection.IsLocal(), allowIPv4, allowIPv6); info != nil {
|
||||||
hash2Peers = append(hash2Peers, Hash2Peer{ID: KeyHash{node.ID}, Closest: []InfoPeer{*info}})
|
selfD.Closest = append(selfD.Closest, *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash2Peers = append(hash2Peers, selfD)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIND_PEER: Find a different peer? Note that in this case no IPv4/IPv6 connectivity check is performed.
|
// FIND_PEER: Find a different peer?
|
||||||
if msg.Actions&(1<<ActionFindPeer) > 0 {
|
if msg.Actions&(1<<ActionFindPeer) > 0 && len(msg.FindPeerKeys) > 0 {
|
||||||
// TODO
|
for _, findPeer := range msg.FindPeerKeys {
|
||||||
|
details := Hash2Peer{ID: findPeer}
|
||||||
|
|
||||||
|
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, findPeer.Hash, filterFunc(msg.connection.IsLocal(), allowIPv4, allowIPv6)) {
|
||||||
|
if info := node.Info.(*PeerInfo).peer2Record(msg.connection.IsLocal(), allowIPv4, allowIPv6); info != nil {
|
||||||
|
details.Closest = append(details.Closest, *info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hash2Peers = append(hash2Peers, details)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a value?
|
// Find a value?
|
||||||
if msg.Actions&(1<<ActionFindValue) > 0 {
|
if msg.Actions&(1<<ActionFindValue) > 0 {
|
||||||
// TODO
|
// TODO query store
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information about files stored by the sender?
|
// Information about files stored by the sender?
|
||||||
@@ -74,9 +87,9 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) {
|
|||||||
peer.sendResponse(added, hash2Peers, nil, nil)
|
peer.sendResponse(added, hash2Peers, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *PeerInfo) peer2Info(allowLocal, allowIPv4, allowIPv6 bool) (result *InfoPeer) {
|
func (peer *PeerInfo) peer2Record(allowLocal, allowIPv4, allowIPv6 bool) (result *PeerRecord) {
|
||||||
if connection := peer.GetConnection2Share(allowLocal, allowIPv4, allowIPv6); connection != nil {
|
if connection := peer.GetConnection2Share(allowLocal, allowIPv4, allowIPv6); connection != nil {
|
||||||
return &InfoPeer{
|
return &PeerRecord{
|
||||||
PublicKey: peer.PublicKey,
|
PublicKey: peer.PublicKey,
|
||||||
NodeID: peer.NodeID,
|
NodeID: peer.NodeID,
|
||||||
IP: connection.Address.IP,
|
IP: connection.Address.IP,
|
||||||
@@ -89,22 +102,55 @@ func (peer *PeerInfo) peer2Info(allowLocal, allowIPv4, allowIPv6 bool) (result *
|
|||||||
|
|
||||||
// cmdResponse handles the response to the announcement
|
// cmdResponse handles the response to the announcement
|
||||||
func (peer *PeerInfo) cmdResponse(msg *MessageResponse) {
|
func (peer *PeerInfo) cmdResponse(msg *MessageResponse) {
|
||||||
// Future: We should only accept responses from peers that we contacted first for security reasons. This can be easily identified by Peer ID.
|
|
||||||
|
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
peer, _ = PeerlistAdd(msg.SenderPublicKey, msg.connection)
|
peer, _ = PeerlistAdd(msg.SenderPublicKey, msg.connection)
|
||||||
fmt.Printf("Incoming initial response from %s\n", msg.connection.Address.String())
|
fmt.Printf("Incoming initial response from %s\n", msg.connection.Address.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each result is checked against the list of information requests. Only 1 response by peer is permitted per query currently.
|
||||||
|
// Response packets could be duplicated, which could happen due to auto broadcast when the remote peer responds and has multiple connections to self but none was active.
|
||||||
|
|
||||||
|
for _, hash := range msg.HashesNotFound {
|
||||||
|
info := nodesDHT.IRLookup(peer.NodeID, hash)
|
||||||
|
if info == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info.ActiveNodesSub(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hash2Peer := range msg.Hash2Peers {
|
||||||
|
info := nodesDHT.IRLookup(peer.NodeID, hash2Peer.ID.Hash)
|
||||||
|
if info == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
info.ResultChan <- &dht.NodeMessage{SenderID: peer.NodeID, Closest: records2Nodes(hash2Peer.Closest, msg.connection.Network), Storing: records2Nodes(hash2Peer.Storing, msg.connection.Network)}
|
||||||
|
|
||||||
|
// Future: a terminate field inform wether the remote peer is done sending. For now terminate after 1 packet.
|
||||||
|
info.ActiveNodesSub(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range msg.FilesEmbed {
|
||||||
|
info := nodesDHT.IRLookup(peer.NodeID, file.ID.Hash)
|
||||||
|
if info == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
info.ResultChan <- &dht.NodeMessage{SenderID: peer.NodeID, Data: file.Data}
|
||||||
|
|
||||||
|
info.ActiveNodesSub(1)
|
||||||
|
info.Terminate() // file was found, terminate the request.
|
||||||
|
}
|
||||||
|
|
||||||
// check if incoming response to FIND_SELF
|
// check if incoming response to FIND_SELF
|
||||||
for _, hash2peer := range msg.Hash2Peers {
|
/*for _, hash2peer := range msg.Hash2Peers {
|
||||||
if !bytes.Equal(hash2peer.ID.Hash, nodeID) {
|
if !bytes.Equal(hash2peer.ID.Hash, nodeID) {
|
||||||
for _, closePeer := range hash2peer.Closest {
|
for _, closePeer := range hash2peer.Closest {
|
||||||
// Initiate contact. Once a response comes back, the peer is actually added to the list.
|
// Initiate contact. Once a response comes back, the peer is actually added to the list.
|
||||||
contactArbitraryPeer(closePeer.PublicKey, closePeer.IP, closePeer.Port)
|
contactArbitraryPeer(closePeer.PublicKey, closePeer.IP, closePeer.Port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//fmt.Printf("Incoming response from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String())
|
//fmt.Printf("Incoming response from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String())
|
||||||
}
|
}
|
||||||
|
|||||||
57
Kademlia.go
57
Kademlia.go
@@ -6,26 +6,65 @@ Author: Peter Kleissner
|
|||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import "github.com/PeernetOfficial/core/dht"
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/PeernetOfficial/core/dht"
|
||||||
|
)
|
||||||
|
|
||||||
var nodesDHT *dht.DHT
|
var nodesDHT *dht.DHT
|
||||||
|
|
||||||
func initKademlia() {
|
func initKademlia() {
|
||||||
nodesDHT = dht.NewDHT(&dht.Node{ID: nodeID}, 256, 20)
|
nodesDHT = dht.NewDHT(&dht.Node{ID: nodeID}, 256, 20, 5)
|
||||||
|
|
||||||
// ShouldEvict determines whether the given node shall be evicted
|
// ShouldEvict determines whether the given node shall be evicted
|
||||||
// TODO For now always return true.
|
|
||||||
nodesDHT.ShouldEvict = func(node *dht.Node) bool {
|
nodesDHT.ShouldEvict = func(node *dht.Node) bool {
|
||||||
|
// TODO: logic
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendStore sends a store message to the remote node. I.e. asking it to store the given key-value
|
// SendRequestStore sends a store message to the remote node. I.e. asking it to store the given key-value
|
||||||
nodesDHT.SendStore = func(node *dht.Node, key []byte, value []byte) {
|
nodesDHT.SendRequestStore = func(node *dht.Node, key []byte, value []byte) {
|
||||||
// TODO
|
node.Info.(*PeerInfo).sendAnnouncementStore(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendRequest sends an information request to the remote node. I.e. requesting information.
|
// SendRequestFindNode sends an information request to find a particular node. nodes are the nodes to send the request to.
|
||||||
nodesDHT.SendRequest = func(request *dht.InformationRequest, nodes []*dht.Node) {
|
nodesDHT.SendRequestFindNode = func(request *dht.InformationRequest) {
|
||||||
// TODO
|
for _, node := range request.Nodes {
|
||||||
|
node.Info.(*PeerInfo).sendAnnouncementFindNode(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendRequestFindValue sends an information request to find data. nodes are the nodes to send the request to.
|
||||||
|
nodesDHT.SendRequestFindValue = func(request *dht.InformationRequest) {
|
||||||
|
for _, node := range request.Nodes {
|
||||||
|
node.Info.(*PeerInfo).sendAnnouncementFindValue(request)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future sendAnnouncementX: If it detects that announcements are sent out to the same peer within 50ms it should activate a wait-and-group scheme.
|
||||||
|
|
||||||
|
func (peer *PeerInfo) sendAnnouncementFindNode(request *dht.InformationRequest) {
|
||||||
|
// If the key is self, send it as FIND_SELF
|
||||||
|
if bytes.Equal(request.Key, nodeID) {
|
||||||
|
peer.sendAnnouncement(false, true, nil, nil, nil)
|
||||||
|
} else {
|
||||||
|
peer.sendAnnouncement(false, false, []KeyHash{{Hash: request.Key}}, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (peer *PeerInfo) sendAnnouncementFindValue(request *dht.InformationRequest) {
|
||||||
|
|
||||||
|
findSelf := false
|
||||||
|
var findPeer []KeyHash
|
||||||
|
var findValue []KeyHash
|
||||||
|
|
||||||
|
findValue = append(findValue, KeyHash{Hash: request.Key})
|
||||||
|
|
||||||
|
peer.sendAnnouncement(false, findSelf, findPeer, findValue, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (peer *PeerInfo) sendAnnouncementStore(key []byte, value []byte) {
|
||||||
|
peer.sendAnnouncement(false, false, nil, nil, []InfoStore{{ID: KeyHash{Hash: key}, Size: uint64(len(value)), Type: 0}})
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ type InfoStore struct {
|
|||||||
Type uint8 // Type of the file: 0 = File, 1 = Header file containing list of parts
|
Type uint8 // Type of the file: 0 = File, 1 = Header file containing list of parts
|
||||||
}
|
}
|
||||||
|
|
||||||
// InfoPeer informs about a peer
|
// PeerRecord informs about a peer
|
||||||
type InfoPeer struct {
|
type PeerRecord struct {
|
||||||
PublicKey *btcec.PublicKey // Public Key
|
PublicKey *btcec.PublicKey // Public Key
|
||||||
NodeID []byte // Kademlia Node ID
|
NodeID []byte // Kademlia Node ID
|
||||||
IP net.IP // IP
|
IP net.IP // IP
|
||||||
@@ -103,9 +103,9 @@ type InfoPeer struct {
|
|||||||
|
|
||||||
// Hash2Peer links a hash to peers who are known to store the data and to peers who are considered close to the hash
|
// Hash2Peer links a hash to peers who are known to store the data and to peers who are considered close to the hash
|
||||||
type Hash2Peer struct {
|
type Hash2Peer struct {
|
||||||
ID KeyHash // Hash that was queried
|
ID KeyHash // Hash that was queried
|
||||||
Closest []InfoPeer // Closest peers
|
Closest []PeerRecord // Closest peers
|
||||||
Storing []InfoPeer // Peers known to store the data identified by the hash
|
Storing []PeerRecord // Peers known to store the data identified by the hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmbeddedFileData contains embedded data sent within a response
|
// EmbeddedFileData contains embedded data sent within a response
|
||||||
@@ -289,11 +289,15 @@ func msgDecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
|||||||
countHashesNotFound := binary.LittleEndian.Uint16(msg.Payload[read+4 : read+4+2])
|
countHashesNotFound := binary.LittleEndian.Uint16(msg.Payload[read+4 : read+4+2])
|
||||||
read += 6
|
read += 6
|
||||||
|
|
||||||
|
if countPeerResponses == 0 && countEmbeddedFiles == 0 && countHashesNotFound == 0 {
|
||||||
|
return nil, errors.New("response: empty")
|
||||||
|
}
|
||||||
|
|
||||||
data := msg.Payload[read:]
|
data := msg.Payload[read:]
|
||||||
|
|
||||||
// Peer response data
|
// Peer response data
|
||||||
if countPeerResponses > 0 {
|
if countPeerResponses > 0 {
|
||||||
hash2Peers, read, valid := decodeInfoPeer(data, int(countPeerResponses))
|
hash2Peers, read, valid := decodePeerRecord(data, int(countPeerResponses))
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, errors.New("response: peer info invalid data")
|
return nil, errors.New("response: peer info invalid data")
|
||||||
}
|
}
|
||||||
@@ -330,8 +334,8 @@ func msgDecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeInfoPeer decodes the response data for FIND_SELF, FIND_PEER and FIND_VALUE messages
|
// decodePeerRecord decodes the response data for FIND_SELF, FIND_PEER and FIND_VALUE messages
|
||||||
func decodeInfoPeer(data []byte, count int) (hash2Peers []Hash2Peer, read int, valid bool) {
|
func decodePeerRecord(data []byte, count int) (hash2Peers []Hash2Peer, read int, valid bool) {
|
||||||
index := 0
|
index := 0
|
||||||
|
|
||||||
for n := 0; n < count; n++ {
|
for n := 0; n < count; n++ {
|
||||||
@@ -352,7 +356,7 @@ func decodeInfoPeer(data []byte, count int) (hash2Peers []Hash2Peer, read int, v
|
|||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
peer := InfoPeer{}
|
peer := PeerRecord{}
|
||||||
|
|
||||||
peerIDcompressed := make([]byte, 33)
|
peerIDcompressed := make([]byte, 33)
|
||||||
copy(peerIDcompressed[:], data[index:index+33])
|
copy(peerIDcompressed[:], data[index:index+33])
|
||||||
@@ -773,3 +777,8 @@ func (peer *PeerInfo) sendResponse(sendUA bool, hash2Peers []Hash2Peer, filesEmb
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lastContact2Time translates a last contact time in seconds to a timestamp
|
||||||
|
func lastContact2Time(LastContact uint32) time.Time {
|
||||||
|
return time.Now().Add(-time.Second * time.Duration(LastContact))
|
||||||
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ func networkStart(iface net.Interface, addresses []net.Addr) {
|
|||||||
func networkPrepareListen(ipA string, port int) (network *Network, err error) {
|
func networkPrepareListen(ipA string, port int) (network *Network, err error) {
|
||||||
ip := net.ParseIP(ipA)
|
ip := net.ParseIP(ipA)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return nil, errors.New("Invalid input IP")
|
return nil, errors.New("invalid input IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
network = new(Network)
|
network = new(Network)
|
||||||
@@ -150,7 +150,7 @@ func networkPrepareListen(ipA string, port int) (network *Network, err error) {
|
|||||||
if ipA != "0.0.0.0" && ipA != "::" {
|
if ipA != "0.0.0.0" && ipA != "::" {
|
||||||
network.iface, network.ipnet = FindInterfaceByIP(ip)
|
network.iface, network.ipnet = FindInterfaceByIP(ip)
|
||||||
if network.iface == nil {
|
if network.iface == nil {
|
||||||
return nil, errors.New("Error finding the network interface belonging to IP")
|
return nil, errors.New("error finding the network interface belonging to IP")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,3 +147,6 @@ func hashData(data []byte) (hash []byte) {
|
|||||||
hash32 := blake3.Sum256(data)
|
hash32 := blake3.Sum256(data)
|
||||||
return hash32[:]
|
return hash32[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashSize is blake3 hash digest size = 256 bits
|
||||||
|
const HashSize = 32
|
||||||
|
|||||||
25
Peer ID.go
25
Peer ID.go
@@ -9,6 +9,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// peerID is the current peers ID. It is a ECDSA (secp256k1) 257-bit public key.
|
// peerID is the current peers ID. It is a ECDSA (secp256k1) 257-bit public key.
|
||||||
|
// The node ID is the blake3 hash of the public key compressed form.
|
||||||
var peerPrivateKey *btcec.PrivateKey
|
var peerPrivateKey *btcec.PrivateKey
|
||||||
var peerPublicKey *btcec.PublicKey
|
var peerPublicKey *btcec.PublicKey
|
||||||
var nodeID []byte
|
var nodeID []byte
|
||||||
@@ -158,3 +160,26 @@ func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompr
|
|||||||
func publicKey2NodeID(publicKey *btcec.PublicKey) (nodeID []byte) {
|
func publicKey2NodeID(publicKey *btcec.PublicKey) (nodeID []byte) {
|
||||||
return hashData(publicKey.SerializeCompressed())
|
return hashData(publicKey.SerializeCompressed())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// record2Peer translate a peer record (from a message) into an actual usable PeerInfo structure
|
||||||
|
// It requires the network parameter which must be the same as caller/supplier. This ensures that peer details do not "jump" between physical network adapters.
|
||||||
|
func record2Peer(record PeerRecord, network *Network) (peerN *PeerInfo) {
|
||||||
|
if peerN = PeerlistLookup(record.PublicKey); peerN != nil {
|
||||||
|
return peerN
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create temporary peer which is not added to the global list and not added to Kademlia.
|
||||||
|
connection := &Connection{Network: network, Address: &net.UDPAddr{IP: record.IP, Port: int(record.Port)}, Status: ConnectionActive}
|
||||||
|
return &PeerInfo{PublicKey: record.PublicKey, connectionActive: []*Connection{connection}, connectionLatest: connection, NodeID: publicKey2NodeID(record.PublicKey)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// records2Nodes translates infoPeer structures to nodes
|
||||||
|
// LastContact is passed on in the Node.LastSeen field.
|
||||||
|
func records2Nodes(records []PeerRecord, network *Network) (nodes []*dht.Node) {
|
||||||
|
for _, record := range records {
|
||||||
|
peer := record2Peer(record, network)
|
||||||
|
nodes = append(nodes, &dht.Node{ID: peer.NodeID, LastSeen: lastContact2Time(record.LastContact), Info: peer})
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -1,8 +1,10 @@
|
|||||||
# Peernet Core
|
# Peernet Core
|
||||||
|
|
||||||
The core library which is needed for any Peernet application. It provides connectivity to the network and all basic functions.
|
The core library which is needed for any Peernet application. It provides connectivity to the network and all basic functions. For details about Peernet see https://peernet.org/.
|
||||||
|
|
||||||
Current version: 0.1 (pre-alpha)
|
Current version: 0.2 (early alpha)
|
||||||
|
|
||||||
|
Current development status: Initial connectivity works. DHT functionality is in development.
|
||||||
|
|
||||||
## Use
|
## Use
|
||||||
|
|
||||||
@@ -42,11 +44,11 @@ func main() {
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Go 1.16 or higher is required. Before compiling, make sure to download and update all 3rd party packages:
|
Go 1.16 or higher is required. These are the major dependencies:
|
||||||
|
|
||||||
```
|
```
|
||||||
go get -u github.com/btcsuite/btcd/btcec
|
github.com/btcsuite/btcd/btcec
|
||||||
go get -u lukechampine.com/blake3
|
lukechampine.com/blake3
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -95,14 +97,10 @@ Above limits are constants and can be adjusted in the code via `pingTime`, `conn
|
|||||||
|
|
||||||
### Kademlia
|
### Kademlia
|
||||||
|
|
||||||
TBD
|
The routing table has a bucket size of 20 and the size of keys 256 bits (blake3 hash). Nodes within buckets are sorted by least recently seen. The number of nodes to contact concurrently in DHT lookups (also known as alpha number) is set to 5.
|
||||||
|
|
||||||
### Ongoing Peerlist Exchange
|
|
||||||
|
|
||||||
TBD
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Please note that by contributing code, documentation, ideas, snippets, or any other intellectual property you agree that you have all the necessary rights and you agree that we, the Peernet organization, may use it for any purpose.
|
Please note that by contributing code, documentation, ideas, snippets, or any other intellectual property you agree that you have all the necessary rights and you agree that we, the Peernet organization, may use it for any purpose.
|
||||||
|
|
||||||
© 2021 Peernet
|
© 2021 Peernet s.r.o.
|
||||||
|
|||||||
10
go.mod
10
go.mod
@@ -3,11 +3,11 @@ module github.com/PeernetOfficial/core
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9
|
github.com/PeernetOfficial/core/dht v0.0.0-20210409140720-c44e57a0a02b
|
||||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1
|
github.com/PeernetOfficial/core/reuseport v0.0.0-20210409140720-c44e57a0a02b
|
||||||
github.com/btcsuite/btcd v0.21.0-beta
|
github.com/btcsuite/btcd v0.21.0-beta.0.20210401013323-36a96f6a0025
|
||||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
lukechampine.com/blake3 v1.1.5
|
lukechampine.com/blake3 v1.1.5
|
||||||
)
|
)
|
||||||
|
|||||||
27
go.sum
27
go.sum
@@ -1,14 +1,14 @@
|
|||||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9 h1:J3SCdaAy8XnuwgwdqYimNzyt4HFQv+EKCPYbItoky8c=
|
github.com/PeernetOfficial/core/dht v0.0.0-20210409140720-c44e57a0a02b h1:4V7y4Kul7R57EAWxr85fVHG3/Gf6U6RBL3ZQFqjjSpU=
|
||||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw=
|
github.com/PeernetOfficial/core/dht v0.0.0-20210409140720-c44e57a0a02b/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw=
|
||||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1 h1:m1dEg5E8ZwT3l/F6xiDrU2Q/ZJ9BeVFAZt/OUBxtr4M=
|
github.com/PeernetOfficial/core/reuseport v0.0.0-20210409140720-c44e57a0a02b h1:9pYGclxvKWSDhe1qlVg8bzeIS78kYehdbNSYautAT+4=
|
||||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1/go.mod h1:j5lvi5jDpdDyuQrsUkCv4kkibVhPWj87sMol41sXIxc=
|
github.com/PeernetOfficial/core/reuseport v0.0.0-20210409140720-c44e57a0a02b/go.mod h1:j5lvi5jDpdDyuQrsUkCv4kkibVhPWj87sMol41sXIxc=
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||||
github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
|
github.com/btcsuite/btcd v0.21.0-beta.0.20210401013323-36a96f6a0025 h1:aoVqvZk4mLyF3WZbqEVPq+vXnwL2wekZg4P4mjYJNLs=
|
||||||
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
|
github.com/btcsuite/btcd v0.21.0-beta.0.20210401013323-36a96f6a0025/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA=
|
||||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
|
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=
|
||||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||||
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
|
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
|
||||||
@@ -17,6 +17,7 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
|
|||||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||||
@@ -39,22 +40,22 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa h1:ZYxPR6aca/uhfRJyaOAtflSHjJYiktO7QnJC5ut7iY4=
|
|
||||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|||||||
Reference in New Issue
Block a user