Fix incoming connections / handshake / initial peer list

This commit is contained in:
DataHoarder 2023-04-19 21:48:30 +02:00
parent d6a46fb216
commit 072debb291
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 42 additions and 32 deletions

View file

@ -135,7 +135,7 @@ func getServerMux(instance *p2pool.P2Pool) *mux.Router {
Incoming: client.IsIncomingConnection,
BroadcastTime: client.LastBroadcastTimestamp.Load(),
BroadcastHeight: client.BroadcastMaxHeight.Load(),
TipHash: *client.LastKnownTip.Load(),
Tip: client.LastKnownTip.Load(),
Closed: client.Closed.Load(),
AlreadyConnected: alreadyConnected,
HandshakeComplete: client.HandshakeComplete.Load(),

View file

@ -37,13 +37,14 @@ func main() {
apiBind := flag.String("api-bind", "", "Bind to this address to serve blocks, and other utility methods. If -archive is specified, serve archived blocks.")
addPeers := flag.String("addpeers", "", "Comma-separated list of IP:port of other p2pool nodes to connect to")
lightMode := flag.Bool("light-mode", false, "Don't allocate RandomX dataset, saves 2GB of RAM")
peerList := flag.String("peer-list", "p2pool_peers.txt", "Either a path or an URL to obtain peer lists from. If it is a path, new peers will be saved to this path")
peerList := flag.String("peer-list", "p2pool_peers.txt", "Either a path or an URL to obtain peer lists from. If it is a path, new peers will be saved to this path. Set to empty to disable")
consensusConfigFile := flag.String("consensus-config", "", "Name of the p2pool consensus config file")
useMiniSidechain := flag.Bool("mini", false, "Connect to p2pool-mini sidechain. Note that it will also change default p2p port.")
outPeers := flag.Uint64("out-peers", 10, "Maximum number of outgoing connections for p2p server (any value between 10 and 450)")
inPeers := flag.Uint64("in-peers", 10, "Maximum number of incoming connections for p2p server (any value between 10 and 450)")
p2pExternalPort := flag.Uint64("p2p-external-port", 0, "Port number that your router uses for mapping to your local p2p port. Use it if you are behind a NAT and still want to accept incoming connections")
noDns := flag.Bool("no-dns", false, "Disable DNS queries, use only IP addresses to connect to peers (seed node DNS will be unavailable too)")
memoryLimitInGiB := flag.Uint64("memory-limit", 0, "Memory limit for go managed sections in GiB, set 0 to disable")
@ -153,6 +154,8 @@ func main() {
continue
}
//TODO: dns resolution of hosts
if addrPort, err := netip.ParseAddrPort(peerAddr); err != nil {
log.Panic(err)
} else {
@ -161,7 +164,7 @@ func main() {
}
}
if currentConsensus.SeedNode() != "" {
if !*noDns && currentConsensus.SeedNode() != "" {
log.Printf("Loading seed peers from %s", currentConsensus.SeedNode())
ips, _ := net.LookupIP(currentConsensus.SeedNode())
for _, seedNodeIp := range ips {

View file

@ -56,9 +56,10 @@ type Client struct {
NextOutgoingPeerListRequestTimestamp atomic.Uint64
//State properties
HandshakeComplete atomic.Bool
HandshakeComplete atomic.Bool
SentHandshakeSolution atomic.Bool
LastKnownTip atomic.Pointer[types.Hash]
LastKnownTip atomic.Pointer[sidechain.PoolBlock]
BroadcastedHashes *utils.CircularBuffer[types.Hash]
RequestedHashes *utils.CircularBuffer[types.Hash]
@ -86,7 +87,6 @@ func NewClient(owner *Server, conn *net.TCPConn) *Client {
RequestedHashes: utils.NewCircularBuffer[types.Hash](16),
blockPendingRequests: make(chan types.Hash, 100), //allow max 100 pending block requests at the same time
}
c.LastKnownTip.Store(&types.ZeroHash)
c.LastActiveTimestamp.Store(uint64(time.Now().Unix()))
@ -316,7 +316,9 @@ func (c *Client) OnConnection() {
c.expectedMessage = MessageHandshakeSolution
c.OnAfterHandshake()
if c.HandshakeComplete.Load() && c.SentHandshakeSolution.Load() {
c.OnAfterHandshake()
}
case MessageHandshakeSolution:
if c.HandshakeComplete.Load() {
@ -354,6 +356,10 @@ func (c *Client) OnConnection() {
}
c.HandshakeComplete.Store(true)
if c.HandshakeComplete.Load() && c.SentHandshakeSolution.Load() {
c.OnAfterHandshake()
}
case MessageListenPort:
if c.ListenPort.Load() != 0 {
c.Ban(DefaultBanTime, errors.New("got LISTEN_PORT but we already received it"))
@ -427,6 +433,7 @@ func (c *Client) OnConnection() {
isChainTipBlockRequest := expectedBlockId == types.ZeroHash
tipHash := types.HashFromBytes(block.CoinbaseExtra(sidechain.SideTemplateId))
if isChainTipBlockRequest {
c.LastKnownTip.Store(block)
log.Printf("[P2PClient] Peer %s tip is at id = %s, height = %d, main height = %d", c.AddressPort.String(), tipHash, block.Side.Height, block.Main.Coinbase.GenHeight)
peerHeight := block.Main.Coinbase.GenHeight
ourHeight := c.Owner.MainChain().GetMinerDataTip().Height
@ -437,7 +444,6 @@ func (c *Client) OnConnection() {
}
c.SendPeerListRequest()
c.LastKnownTip.Store(&tipHash)
}
if missingBlocks, err, ban := c.Owner.SideChain().AddPoolBlockExternal(block); err != nil {
if ban {
@ -500,8 +506,7 @@ func (c *Client) OnConnection() {
c.BroadcastedHashes.Push(tipHash)
c.LastBroadcastTimestamp.Store(uint64(time.Now().Unix()))
c.LastKnownTip.Store(&tipHash)
c.LastKnownTip.Store(block)
if missingBlocks, err := c.Owner.SideChain().PreprocessBlock(block); err != nil {
for _, id := range missingBlocks {
@ -557,7 +562,7 @@ func (c *Client) OnConnection() {
entriesToSend := make([]netip.AddrPort, 0, PeerListResponseMaxPeers)
// Send every 4th peer on average, selected at random
peersToSendTarget := utils.Min(PeerListResponseMaxPeers, utils.Max(len(entriesToSend)/4, 1))
peersToSendTarget := utils.Min(PeerListResponseMaxPeers, utils.Max(len(connectedPeerList)/4, 1))
n := 0
for _, peer := range connectedPeerList {
if peer.AddressPort.Addr().IsLoopback() || !peer.IsGood() || peer.AddressPort.Addr().Compare(c.AddressPort.Addr()) == 0 {
@ -671,7 +676,7 @@ func (c *Client) sendHandshakeSolution(challenge HandshakeChallenge) {
stop.Store(true)
}
if solution, hash, ok := FindChallengeSolution(challenge, c.Owner.Consensus().Id(), stop); ok {
if solution, hash, ok := FindChallengeSolution(challenge, c.Owner.Consensus().Id(), stop); ok || c.IsIncomingConnection {
var buf [HandshakeChallengeSize + types.HashSize]byte
copy(buf[:], hash[:])
@ -681,6 +686,7 @@ func (c *Client) sendHandshakeSolution(challenge HandshakeChallenge) {
MessageId: MessageHandshakeSolution,
Buffer: buf[:],
})
c.SentHandshakeSolution.Store(true)
}
}
@ -746,6 +752,6 @@ func (c *Client) Close() bool {
_ = c.Connection.Close()
close(c.closeChannel)
log.Printf("[P2PClient] Peer %s close", c.AddressPort.String())
log.Printf("[P2PClient] Peer %s connection closed", c.AddressPort.String())
return true
}

View file

@ -53,23 +53,24 @@ type P2PoolServerPeerResult struct {
}
type P2PoolConnectionCheckInformation struct {
Address string `json:"address"`
Port uint16 `json:"port"`
ListenPort uint16 `json:"listen_port"`
PeerId uint64 `json:"peer_id"`
SoftwareId string `json:"software_id"`
SoftwareVersion string `json:"software_version"`
ProtocolVersion string `json:"protocol_version"`
ConnectionTime uint64 `json:"connection_time"`
Latency uint64 `json:"latency"`
LastActive uint64 `json:"last_active"`
Incoming bool `json:"incoming"`
BroadcastTime uint64 `json:"broadcast_time"`
BroadcastHeight uint64 `json:"broadcast_height"`
TipHash types.Hash `json:"tip_hash"`
Closed bool `json:"closed"`
AlreadyConnected bool `json:"already_connected"`
HandshakeComplete bool `json:"handshake_complete"`
Banned bool `json:"banned"`
Error string `json:"error,omitempty"`
Address string `json:"address"`
Port uint16 `json:"port"`
ListenPort uint16 `json:"listen_port"`
PeerId uint64 `json:"peer_id"`
SoftwareId string `json:"software_id"`
SoftwareVersion string `json:"software_version"`
ProtocolVersion string `json:"protocol_version"`
ConnectionTime uint64 `json:"connection_time"`
Latency uint64 `json:"latency"`
LastActive uint64 `json:"last_active"`
Incoming bool `json:"incoming"`
BroadcastTime uint64 `json:"broadcast_time"`
BroadcastHeight uint64 `json:"broadcast_height"`
// Tip is a sidechain.PoolBlock
Tip any `json:"tip,omitempty"`
Closed bool `json:"closed"`
AlreadyConnected bool `json:"already_connected"`
HandshakeComplete bool `json:"handshake_complete"`
Banned bool `json:"banned"`
Error string `json:"error,omitempty"`
}