git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/p2pool/types/protocol.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"net/netip"
     9  )
    10  
    11  func IsPeerVersionInformation(addr netip.AddrPort) bool {
    12  	if addr.Port() != 0xFFFF {
    13  		return false
    14  	}
    15  	rawIp := addr.Addr().As16()
    16  	return bytes.Compare(rawIp[12:], []byte{0xFF, 0xFF, 0xFF, 0xFF}) == 0
    17  }
    18  
    19  // ProtocolFeature List of features to check to not depend on hardcoded protocol versions.
    20  // Use PeerVersionInformation.SupportsFeature() to query these.
    21  type ProtocolFeature int
    22  
    23  const (
    24  	// FeaturePeerInformationReceive Backwards compatible, can be sent to all clients
    25  	FeaturePeerInformationReceive = ProtocolFeature(iota)
    26  	FeaturePeerInformationExchange
    27  	FeaturePrunedBroadcast
    28  	FeatureCompactBroadcast
    29  	FeatureBlockNotify
    30  )
    31  
    32  type PeerVersionInformation struct {
    33  	Protocol        ProtocolVersion
    34  	SoftwareVersion SoftwareVersion
    35  	SoftwareId      SoftwareId
    36  }
    37  
    38  func (i *PeerVersionInformation) SupportsFeature(feature ProtocolFeature) bool {
    39  	switch feature {
    40  	case FeaturePeerInformationReceive:
    41  		return i.Protocol == ProtocolVersion_0_0 || i.Protocol >= ProtocolVersion_1_0
    42  	case FeaturePeerInformationExchange:
    43  		return i.Protocol >= ProtocolVersion_1_0
    44  	case FeaturePrunedBroadcast:
    45  		return i.Protocol == ProtocolVersion_0_0 || i.Protocol >= ProtocolVersion_1_0
    46  	case FeatureCompactBroadcast:
    47  		return i.Protocol >= ProtocolVersion_1_1
    48  	case FeatureBlockNotify:
    49  		return i.Protocol >= ProtocolVersion_1_2
    50  	default:
    51  		return false
    52  	}
    53  }
    54  
    55  func (i *PeerVersionInformation) String() string {
    56  	// Empty information
    57  	if i.Protocol == 0 && i.SoftwareVersion == 0 && i.SoftwareId == 0 {
    58  		return "Unknown"
    59  	}
    60  
    61  	return fmt.Sprintf("%s %s (protocol %s)", i.SoftwareId.String(), i.SoftwareVersion.String(), i.Protocol.String())
    62  }
    63  
    64  func (i *PeerVersionInformation) ToAddrPort() netip.AddrPort {
    65  	var addr [16]byte
    66  
    67  	binary.LittleEndian.PutUint32(addr[:], uint32(i.Protocol))
    68  	binary.LittleEndian.PutUint32(addr[4:], uint32(i.SoftwareVersion))
    69  	binary.LittleEndian.PutUint32(addr[8:], uint32(i.SoftwareId))
    70  	binary.LittleEndian.PutUint32(addr[12:], 0xFFFFFFFF)
    71  
    72  	return netip.AddrPortFrom(netip.AddrFrom16(addr), 0xFFFF)
    73  }
    74  
    75  type ProtocolVersion SemanticVersion
    76  
    77  func (v ProtocolVersion) Major() uint16 {
    78  	return SemanticVersion(v).Major()
    79  }
    80  func (v ProtocolVersion) Minor() uint16 {
    81  	return SemanticVersion(v).Minor()
    82  }
    83  
    84  func (v ProtocolVersion) String() string {
    85  	return SemanticVersion(v).String()
    86  }
    87  
    88  const (
    89  	ProtocolVersion_0_0 ProtocolVersion = (0 << 16) | 0
    90  	ProtocolVersion_1_0 ProtocolVersion = (1 << 16) | 0
    91  	ProtocolVersion_1_1 ProtocolVersion = (1 << 16) | 1
    92  	ProtocolVersion_1_2 ProtocolVersion = (1 << 16) | 2
    93  )
    94  
    95  type SoftwareVersion SemanticVersion
    96  
    97  func (v SoftwareVersion) Major() uint16 {
    98  	return SemanticVersion(v).Major()
    99  }
   100  func (v SoftwareVersion) Minor() uint16 {
   101  	return SemanticVersion(v).Minor()
   102  }
   103  
   104  func (v SoftwareVersion) String() string {
   105  	return SemanticVersion(v).String()
   106  }
   107  
   108  const SupportedProtocolVersion = ProtocolVersion_1_2
   109  const CurrentSoftwareVersion SoftwareVersion = (3 << 16) | 0
   110  const CurrentSoftwareId = SoftwareIdGoObserver
   111  
   112  type SoftwareId uint32
   113  
   114  func (c SoftwareId) String() string {
   115  	switch c {
   116  	case SoftwareIdP2Pool:
   117  		return "P2Pool"
   118  	case SoftwareIdGoObserver:
   119  		return "GoObserver"
   120  	default:
   121  		var buf = [17]byte{'U', 'n', 'k', 'n', 'o', 'w', 'n', '(', 0, 0, 0, 0, 0, 0, 0, 0, ')'}
   122  		var intBuf [4]byte
   123  		binary.LittleEndian.PutUint32(intBuf[:], uint32(c))
   124  		hex.Encode(buf[8:], intBuf[:])
   125  		return string(buf[:])
   126  	}
   127  }
   128  
   129  const (
   130  	SoftwareIdP2Pool     SoftwareId = 0x00000000
   131  	SoftwareIdGoObserver SoftwareId = 0x624F6F47 //GoOb, little endian
   132  )