Major refactoring of the code base into Backend structure. Increase version number to Alpha 6 to prepare for the upcoming release.

This commit is contained in:
Kleissner
2021-12-29 05:29:34 +01:00
parent ade13d6422
commit f2c344dc96
40 changed files with 642 additions and 649 deletions

View File

@@ -20,46 +20,40 @@ import (
"github.com/PeernetOfficial/core/protocol"
)
// 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 peerPublicKey *btcec.PublicKey
var nodeID []byte
func initPeerID() {
peerList = make(map[[btcec.PubKeyBytesLenCompressed]byte]*PeerInfo)
nodeList = make(map[[protocol.HashSize]byte]*PeerInfo)
func (backend *Backend) initPeerID() {
backend.peerList = make(map[[btcec.PubKeyBytesLenCompressed]byte]*PeerInfo)
backend.nodeList = make(map[[protocol.HashSize]byte]*PeerInfo)
// load existing key from config, if available
if len(config.PrivateKey) > 0 {
configPK, err := hex.DecodeString(config.PrivateKey)
if len(backend.Config.PrivateKey) > 0 {
configPK, err := hex.DecodeString(backend.Config.PrivateKey)
if err == nil {
peerPrivateKey, peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
nodeID = protocol.PublicKey2NodeID(peerPublicKey)
backend.peerPrivateKey, backend.peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
backend.nodeID = protocol.PublicKey2NodeID(backend.peerPublicKey)
if config.AutoUpdateSeedList {
configUpdateSeedList()
if backend.Config.AutoUpdateSeedList {
backend.configUpdateSeedList()
}
return
}
Filters.LogError("initPeerID", "private key in config is corrupted! Error: %s\n", err.Error())
backend.Filters.LogError("initPeerID", "private key in config is corrupted! Error: %s\n", err.Error())
os.Exit(ExitPrivateKeyCorrupt)
}
// if the peer ID is empty, create a new user public-private key pair
var err error
peerPrivateKey, peerPublicKey, err = Secp256k1NewPrivateKey()
backend.peerPrivateKey, backend.peerPublicKey, err = Secp256k1NewPrivateKey()
if err != nil {
Filters.LogError("initPeerID", "generating public-private key pairs: %s\n", err.Error())
backend.Filters.LogError("initPeerID", "generating public-private key pairs: %s\n", err.Error())
os.Exit(ExitPrivateKeyCreate)
}
nodeID = protocol.PublicKey2NodeID(peerPublicKey)
backend.nodeID = protocol.PublicKey2NodeID(backend.peerPublicKey)
// save the newly generated private key into the config
config.PrivateKey = hex.EncodeToString(peerPrivateKey.Serialize())
backend.Config.PrivateKey = hex.EncodeToString(backend.peerPrivateKey.Serialize())
saveConfig()
backend.SaveConfig()
}
// Secp256k1NewPrivateKey creates a new public-private key pair
@@ -73,18 +67,18 @@ func Secp256k1NewPrivateKey() (privateKey *btcec.PrivateKey, publicKey *btcec.Pu
}
// ExportPrivateKey returns the peers public and private key
func ExportPrivateKey() (privateKey *btcec.PrivateKey, publicKey *btcec.PublicKey) {
return peerPrivateKey, peerPublicKey
func (backend *Backend) ExportPrivateKey() (privateKey *btcec.PrivateKey, publicKey *btcec.PublicKey) {
return backend.peerPrivateKey, backend.peerPublicKey
}
// SelfNodeID returns the node ID used for DHT
func SelfNodeID() []byte {
return nodeID
func (backend *Backend) SelfNodeID() []byte {
return backend.nodeID
}
// SelfUserAgent returns the User Agent
func SelfUserAgent() string {
return userAgent
func (backend *Backend) SelfUserAgent() string {
return backend.userAgent
}
// PeerInfo stores information about a single remote peer
@@ -109,6 +103,8 @@ type PeerInfo struct {
// statistics
StatsPacketSent uint64 // Count of packets sent
StatsPacketReceived uint64 // Count of packets received
Backend *Backend
}
type peerAddress struct {
@@ -117,79 +113,72 @@ type peerAddress struct {
PortInternal uint16
}
// peerList keeps track of all peers
var peerList map[[btcec.PubKeyBytesLenCompressed]byte]*PeerInfo
var peerlistMutex sync.RWMutex
// nodeList is a mirror of peerList but using the node ID
var nodeList map[[protocol.HashSize]byte]*PeerInfo
// 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) {
func (backend *Backend) PeerlistAdd(PublicKey *btcec.PublicKey, connections ...*Connection) (peer *PeerInfo, added bool) {
if len(connections) == 0 {
return nil, false
}
publicKeyCompressed := publicKey2Compressed(PublicKey)
peerlistMutex.Lock()
defer peerlistMutex.Unlock()
backend.peerlistMutex.Lock()
defer backend.peerlistMutex.Unlock()
peer, ok := peerList[publicKeyCompressed]
peer, ok := backend.peerList[publicKeyCompressed]
if ok {
return peer, false
}
peer = &PeerInfo{PublicKey: PublicKey, connectionActive: connections, connectionLatest: connections[0], NodeID: protocol.PublicKey2NodeID(PublicKey), messageSequence: rand.Uint32()}
peer = &PeerInfo{Backend: backend, PublicKey: PublicKey, connectionActive: connections, connectionLatest: connections[0], NodeID: protocol.PublicKey2NodeID(PublicKey), messageSequence: rand.Uint32()}
_, peer.IsRootPeer = rootPeers[publicKeyCompressed]
peerList[publicKeyCompressed] = peer
backend.peerList[publicKeyCompressed] = peer
// also add to mirrored nodeList
var nodeID [protocol.HashSize]byte
copy(nodeID[:], peer.NodeID)
nodeList[nodeID] = peer
backend.nodeList[nodeID] = peer
// add to Kademlia
nodesDHT.AddNode(&dht.Node{ID: peer.NodeID, Info: peer})
backend.nodesDHT.AddNode(&dht.Node{ID: peer.NodeID, Info: peer})
// TODO: If the node isn't added to Kademlia, it should be either added temporarily to the peerList with an expiration, or to a temp list, or not at all.
// send to all channels non-blocking
for _, monitor := range peerMonitor {
for _, monitor := range backend.peerMonitor {
select {
case monitor <- peer:
default:
}
}
Filters.NewPeer(peer, connections[0])
Filters.NewPeerConnection(peer, connections[0])
backend.Filters.NewPeer(peer, connections[0])
backend.Filters.NewPeerConnection(peer, connections[0])
return peer, true
}
// PeerlistRemove removes a peer from the peer list.
func PeerlistRemove(peer *PeerInfo) {
peerlistMutex.Lock()
defer peerlistMutex.Unlock()
func (backend *Backend) PeerlistRemove(peer *PeerInfo) {
backend.peerlistMutex.Lock()
defer backend.peerlistMutex.Unlock()
// remove from Kademlia
nodesDHT.RemoveNode(peer.NodeID)
backend.nodesDHT.RemoveNode(peer.NodeID)
delete(peerList, publicKey2Compressed(peer.PublicKey))
delete(backend.peerList, publicKey2Compressed(peer.PublicKey))
var nodeID [protocol.HashSize]byte
copy(nodeID[:], peer.NodeID)
delete(nodeList, nodeID)
delete(backend.nodeList, nodeID)
}
// PeerlistGet returns the full peer list
func PeerlistGet() (peers []*PeerInfo) {
peerlistMutex.RLock()
defer peerlistMutex.RUnlock()
func (backend *Backend) PeerlistGet() (peers []*PeerInfo) {
backend.peerlistMutex.RLock()
defer backend.peerlistMutex.RUnlock()
for _, peer := range peerList {
for _, peer := range backend.peerList {
peers = append(peers, peer)
}
@@ -197,30 +186,30 @@ func PeerlistGet() (peers []*PeerInfo) {
}
// PeerlistLookup returns the peer from the list with the public key
func PeerlistLookup(publicKey *btcec.PublicKey) (peer *PeerInfo) {
peerlistMutex.RLock()
defer peerlistMutex.RUnlock()
func (backend *Backend) PeerlistLookup(publicKey *btcec.PublicKey) (peer *PeerInfo) {
backend.peerlistMutex.RLock()
defer backend.peerlistMutex.RUnlock()
return peerList[publicKey2Compressed(publicKey)]
return backend.peerList[publicKey2Compressed(publicKey)]
}
// NodelistLookup returns the peer from the list with the node ID
func NodelistLookup(nodeID []byte) (peer *PeerInfo) {
peerlistMutex.RLock()
defer peerlistMutex.RUnlock()
func (backend *Backend) NodelistLookup(nodeID []byte) (peer *PeerInfo) {
backend.peerlistMutex.RLock()
defer backend.peerlistMutex.RUnlock()
var nodeID2 [protocol.HashSize]byte
copy(nodeID2[:], nodeID)
return nodeList[nodeID2]
return backend.nodeList[nodeID2]
}
// PeerlistCount returns the current count of peers in the peer list
func PeerlistCount() (count int) {
peerlistMutex.RLock()
defer peerlistMutex.RUnlock()
func (backend *Backend) PeerlistCount() (count int) {
backend.peerlistMutex.RLock()
defer backend.peerlistMutex.RUnlock()
return len(peerList)
return len(backend.peerList)
}
func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompressed]byte {
@@ -229,11 +218,11 @@ func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompr
return key
}
// records2Nodes translates infoPeer structures to nodes. If the reported nodes are not in the peer table, it will create temporary PeerInfo structures.
// records2Nodes translates infoPeer structures to nodes reported by the peer. If the reported nodes are not in the peer table, it will create temporary PeerInfo structures.
// LastContact is passed on in the Node.LastSeen field.
func records2Nodes(records []protocol.PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) {
func (peerSource *PeerInfo) records2Nodes(records []protocol.PeerRecord) (nodes []*dht.Node) {
for _, record := range records {
if isReturnedPeerBadQuality(&record) {
if peerSource.Backend.isReturnedPeerBadQuality(&record) {
continue
}
@@ -241,7 +230,7 @@ func records2Nodes(records []protocol.PeerRecord, peerSource *PeerInfo) (nodes [
if record.PublicKey.IsEqual(peerSource.PublicKey) {
// Special case if peer that stores info = sender. In that case IP:Port in the record would be empty anyway.
peer = peerSource
} else if peer = PeerlistLookup(record.PublicKey); peer == nil {
} else if peer = peerSource.Backend.PeerlistLookup(record.PublicKey); peer == nil {
// Create temporary peer which is not added to the global list and not added to Kademlia.
// traversePeer is set to the peer who provided the node information.
addresses := peerRecordToAddresses(&record)
@@ -249,7 +238,7 @@ func records2Nodes(records []protocol.PeerRecord, peerSource *PeerInfo) (nodes [
continue
}
peer = &PeerInfo{PublicKey: record.PublicKey, connectionActive: nil, connectionLatest: nil, NodeID: protocol.PublicKey2NodeID(record.PublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses, traversePeer: peerSource, Features: record.Features}
peer = &PeerInfo{Backend: peerSource.Backend, PublicKey: record.PublicKey, connectionActive: nil, connectionLatest: nil, NodeID: protocol.PublicKey2NodeID(record.PublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses, traversePeer: peerSource, Features: record.Features}
}
nodes = append(nodes, &dht.Node{ID: peer.NodeID, LastSeen: record.LastContactT, Info: peer})
@@ -259,55 +248,53 @@ func records2Nodes(records []protocol.PeerRecord, peerSource *PeerInfo) (nodes [
}
// selfPeerRecord returns self as peer record
func selfPeerRecord() (result protocol.PeerRecord) {
func (backend *Backend) selfPeerRecord() (result protocol.PeerRecord) {
return protocol.PeerRecord{
PublicKey: peerPublicKey,
NodeID: nodeID,
PublicKey: backend.peerPublicKey,
NodeID: backend.nodeID,
//IP: network.address.IP,
//Port: uint16(network.address.Port),
LastContact: 0,
Features: FeatureSupport(),
Features: backend.FeatureSupport(),
}
}
var peerMonitor []chan<- *PeerInfo
// registerPeerMonitor registers a channel to receive all new peers
func registerPeerMonitor(channel chan<- *PeerInfo) {
peerlistMutex.Lock()
defer peerlistMutex.Unlock()
func (backend *Backend) registerPeerMonitor(channel chan<- *PeerInfo) {
backend.peerlistMutex.Lock()
defer backend.peerlistMutex.Unlock()
peerMonitor = append(peerMonitor, channel)
backend.peerMonitor = append(backend.peerMonitor, channel)
}
// unregisterPeerMonitor unregisters a channel
func unregisterPeerMonitor(channel chan<- *PeerInfo) {
peerlistMutex.Lock()
defer peerlistMutex.Unlock()
func (backend *Backend) unregisterPeerMonitor(channel chan<- *PeerInfo) {
backend.peerlistMutex.Lock()
defer backend.peerlistMutex.Unlock()
for n, channel2 := range peerMonitor {
for n, channel2 := range backend.peerMonitor {
if channel == channel2 {
peerMonitorNew := peerMonitor[:n]
if n < len(peerMonitor)-1 {
peerMonitorNew = append(peerMonitorNew, peerMonitor[n+1:]...)
peerMonitorNew := backend.peerMonitor[:n]
if n < len(backend.peerMonitor)-1 {
peerMonitorNew = append(peerMonitorNew, backend.peerMonitor[n+1:]...)
}
peerMonitor = peerMonitorNew
backend.peerMonitor = peerMonitorNew
break
}
}
}
// DeleteAccount deletes the account
func DeleteAccount() {
func (backend *Backend) DeleteAccount() {
// delete the blockchain
UserBlockchain.DeleteBlockchain()
backend.UserBlockchain.DeleteBlockchain()
// delete the warehouse
UserWarehouse.DeleteWarehouse()
backend.UserWarehouse.DeleteWarehouse()
// delete the private key
config.PrivateKey = ""
saveConfig()
backend.Config.PrivateKey = ""
backend.SaveConfig()
}
// PublicKeyFromPeerID decodes the peer ID (hex encoded) into a public key.