mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
More changes coming. Rename of organization to Peernet s.r.o. InformationRequest proper termination signal.
154 lines
4.7 KiB
Go
154 lines
4.7 KiB
Go
/*
|
|
File Name: Peer ID.go
|
|
Copyright: 2021 Peernet s.r.o.
|
|
Author: Peter Kleissner
|
|
*/
|
|
|
|
package core
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"log"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
)
|
|
|
|
// peerID is the current peers ID. It is a ECDSA (secp256k1) 257-bit public key.
|
|
var peerPrivateKey *btcec.PrivateKey
|
|
var peerPublicKey *btcec.PublicKey
|
|
var nodeID []byte
|
|
|
|
func initPeerID() {
|
|
peerList = make(map[[btcec.PubKeyBytesLenCompressed]byte]*PeerInfo)
|
|
|
|
// load existing key from config, if available
|
|
if len(config.PrivateKey) > 0 {
|
|
configPK, err := hex.DecodeString(config.PrivateKey)
|
|
if err == nil {
|
|
peerPrivateKey, peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
|
|
nodeID = publicKey2NodeID(peerPublicKey)
|
|
return
|
|
}
|
|
|
|
log.Printf("Private key in config is corrupted! Error: %s\n", err.Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
// if the peer ID is empty, create a new user public-private key pair
|
|
var err error
|
|
peerPrivateKey, peerPublicKey, err = Secp256k1NewPrivateKey()
|
|
if err != nil {
|
|
log.Printf("Error generating public-private key pairs: %s\n", err.Error())
|
|
os.Exit(1)
|
|
}
|
|
nodeID = publicKey2NodeID(peerPublicKey)
|
|
|
|
// save the newly generated private key into the config
|
|
config.PrivateKey = hex.EncodeToString(peerPublicKey.SerializeCompressed())
|
|
|
|
saveConfig()
|
|
}
|
|
|
|
// Secp256k1NewPrivateKey creates a new public-private key pair
|
|
func Secp256k1NewPrivateKey() (privateKey *btcec.PrivateKey, publicKey *btcec.PublicKey, err error) {
|
|
key, err := btcec.NewPrivateKey(btcec.S256())
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return key, (*btcec.PublicKey)(&key.PublicKey), nil
|
|
}
|
|
|
|
// ExportPrivateKey returns the peers public and private key
|
|
func ExportPrivateKey() (privateKey *btcec.PrivateKey, publicKey *btcec.PublicKey) {
|
|
return peerPrivateKey, peerPublicKey
|
|
}
|
|
|
|
// PeerInfo stores information about a single remote peer
|
|
type PeerInfo struct {
|
|
PublicKey *btcec.PublicKey // Public key
|
|
NodeID []byte // Node ID in Kademlia network = blake3(Public Key).
|
|
connectionActive []*Connection // List of active established connections to the peer.
|
|
connectionInactive []*Connection // List of former connections that are no longer valid. They may be removed after a while.
|
|
connectionLatest *Connection // Latest valid connection.
|
|
sync.RWMutex // Mutex for access to list of connections.
|
|
|
|
// statistics
|
|
StatsPacketSent uint64 // Count of packets sent
|
|
StatsPacketReceived uint64 // Count of packets received
|
|
}
|
|
|
|
var peerList map[[btcec.PubKeyBytesLenCompressed]byte]*PeerInfo
|
|
var peerlistMutex sync.RWMutex
|
|
|
|
// PeerlistAdd adds a new peer to the peer list. It does not validate the peer info. If the peer is already added, it does nothing. Connections must be live.
|
|
func PeerlistAdd(PublicKey *btcec.PublicKey, connections ...*Connection) (peer *PeerInfo, added bool) {
|
|
if len(connections) == 0 {
|
|
return nil, false
|
|
}
|
|
|
|
peerlistMutex.Lock()
|
|
defer peerlistMutex.Unlock()
|
|
|
|
peer, ok := peerList[publicKey2Compressed(PublicKey)]
|
|
if ok {
|
|
return peer, false
|
|
}
|
|
|
|
peer = &PeerInfo{PublicKey: PublicKey, connectionActive: connections, connectionLatest: connections[0], NodeID: publicKey2NodeID(PublicKey)}
|
|
peerList[publicKey2Compressed(peer.PublicKey)] = peer
|
|
|
|
return peer, true
|
|
}
|
|
|
|
// PeerlistRemove removes a peer from the peer list.
|
|
func PeerlistRemove(peer *PeerInfo) {
|
|
peerlistMutex.Lock()
|
|
defer peerlistMutex.Unlock()
|
|
|
|
delete(peerList, publicKey2Compressed(peer.PublicKey))
|
|
}
|
|
|
|
// PeerlistGet returns the full peer list
|
|
func PeerlistGet() (peers []*PeerInfo) {
|
|
peerlistMutex.RLock()
|
|
defer peerlistMutex.RUnlock()
|
|
|
|
for _, peer := range peerList {
|
|
peers = append(peers, peer)
|
|
}
|
|
|
|
return peers
|
|
}
|
|
|
|
// PeerlistLookup returns the peer from the list with the public key
|
|
func PeerlistLookup(publicKey *btcec.PublicKey) (peer *PeerInfo) {
|
|
peerlistMutex.RLock()
|
|
defer peerlistMutex.RUnlock()
|
|
|
|
peer, _ = peerList[publicKey2Compressed(publicKey)]
|
|
return peer
|
|
}
|
|
|
|
// PeerlistCount returns the current count of peers in the peer list
|
|
func PeerlistCount() (count int) {
|
|
peerlistMutex.RLock()
|
|
defer peerlistMutex.RUnlock()
|
|
|
|
return len(peerList)
|
|
}
|
|
|
|
func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompressed]byte {
|
|
var key [btcec.PubKeyBytesLenCompressed]byte
|
|
copy(key[:], publicKey.SerializeCompressed())
|
|
return key
|
|
}
|
|
|
|
// publicKey2NodeID translates the Public Key into the node ID used in the Kademlia network.
|
|
// This is very important for lookup of data in the DHT.
|
|
func publicKey2NodeID(publicKey *btcec.PublicKey) (nodeID []byte) {
|
|
return hashData(peerPublicKey.SerializeCompressed())
|
|
}
|