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 )