Class: Bitcoin::Message::NetworkAddr
- Inherits:
-
Object
- Object
- Bitcoin::Message::NetworkAddr
- Defined in:
- lib/bitcoin/message/network_addr.rb
Constant Summary collapse
- TYPE =
{legacy: 0x01, addr_v2: 0x02}
Instance Attribute Summary collapse
-
#addr ⇒ Object
Network address.
-
#net ⇒ Object
network ID that defined by BIP-155.
-
#port ⇒ Object
Returns the value of attribute port.
-
#services ⇒ Object
The services the node advertised in its version message.
-
#skip_time ⇒ Object
readonly
Returns the value of attribute skip_time.
-
#time ⇒ Object
unix time.
Class Method Summary collapse
-
.load_addr_v2_payload(payload) ⇒ Object
Load addr payload with addr v2 format.
-
.load_legacy_payload(payload) ⇒ Object
Load addr payload with legacy format.
- .local_addr ⇒ Object
-
.parse_from_payload(payload, type: TYPE[:legacy]) ⇒ NetworkAddr
Parse addr payload.
Instance Method Summary collapse
-
#addr_string ⇒ Object
Show addr string.
-
#initialize(ip: '127.0.0.1', port: Bitcoin.chain_params.default_port, services: DEFAULT_SERVICE_FLAGS, time: Time.now.to_i, net: NETWORK_ID[:ipv4]) ⇒ NetworkAddr
constructor
A new instance of NetworkAddr.
- #legacy_payload(skip_time) ⇒ Object
- #to_payload(skip_time = false, type: TYPE[:legacy]) ⇒ Object
- #v2_payload ⇒ Object
Constructor Details
#initialize(ip: '127.0.0.1', port: Bitcoin.chain_params.default_port, services: DEFAULT_SERVICE_FLAGS, time: Time.now.to_i, net: NETWORK_ID[:ipv4]) ⇒ NetworkAddr
Returns a new instance of NetworkAddr.
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/bitcoin/message/network_addr.rb', line 33 def initialize(ip: '127.0.0.1', port: Bitcoin.chain_params.default_port, services: DEFAULT_SERVICE_FLAGS, time: Time.now.to_i, net: NETWORK_ID[:ipv4]) @time = time @port = port @services = services @net = net case net when NETWORK_ID[:ipv4], NETWORK_ID[:ipv6] @addr = IPAddr.new(ip) if ip end end |
Instance Attribute Details
#addr ⇒ Object
Network address. The interpretation depends on networkID. If ipv4 or ipv6 this field is a IPAddr object, otherwise hex string.
27 28 29 |
# File 'lib/bitcoin/message/network_addr.rb', line 27 def addr @addr end |
#net ⇒ Object
network ID that defined by BIP-155
23 24 25 |
# File 'lib/bitcoin/message/network_addr.rb', line 23 def net @net end |
#port ⇒ Object
Returns the value of attribute port.
29 30 31 |
# File 'lib/bitcoin/message/network_addr.rb', line 29 def port @port end |
#services ⇒ Object
The services the node advertised in its version message.
21 22 23 |
# File 'lib/bitcoin/message/network_addr.rb', line 21 def services @services end |
#skip_time ⇒ Object (readonly)
Returns the value of attribute skip_time.
31 32 33 |
# File 'lib/bitcoin/message/network_addr.rb', line 31 def skip_time @skip_time end |
#time ⇒ Object
unix time. Nodes advertising their own IP address set this to the current time. Nodes advertising IP addresses they’ve connected to set this to the last time they connected to that node. Other nodes just relaying the IP address should not change the time. Nodes can use the time field to avoid relaying old addr messages.
18 19 20 |
# File 'lib/bitcoin/message/network_addr.rb', line 18 def time @time end |
Class Method Details
.load_addr_v2_payload(payload) ⇒ Object
Load addr payload with addr v2 format.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/bitcoin/message/network_addr.rb', line 117 def self.load_addr_v2_payload(payload) buf = payload.is_a?(String) ? StringIO.new(payload) : payload addr = NetworkAddr.new(time: buf.read(4).unpack1('V')) addr.services = Bitcoin.unpack_var_int_from_io(buf) addr.net = buf.read(1).unpack1('C') raise Bitcoin::Message::Error, "Unknown network id: #{addr.net}" unless NETWORK_ID.value?(addr.net) addr_len = Bitcoin.unpack_var_int_from_io(buf) addr.addr = case addr.net when NETWORK_ID[:ipv4] raise Bitcoin::Message::Error, "Invalid IPv4 address." unless addr_len == 4 IPAddr::new_ntoh(buf.read(addr_len)) when NETWORK_ID[:ipv6] raise Bitcoin::Message::Error, "Invalid IPv6 address." unless addr_len == 16 a = IPAddr::new_ntoh(buf.read(addr_len)) raise Bitcoin::Message::Error, "Invalid IPv6 address." if a.ipv4_mapped? a when NETWORK_ID[:tor_v2] raise Bitcoin::Message::Error, "Invalid Tor v2 address." unless addr_len == 10 buf.read(addr_len).bth when NETWORK_ID[:tor_v3] raise Bitcoin::Message::Error, "Invalid Tor v3 address." unless addr_len == 32 buf.read(addr_len).bth when NETWORK_ID[:i2p] raise Bitcoin::Message::Error, "Invalid I2P address." unless addr_len == 32 buf.read(addr_len).bth when NETWORK_ID[:cjdns] raise Bitcoin::Message::Error, "Invalid CJDNS address." unless addr_len == 16 a = IPAddr::new_ntoh(buf.read(addr_len)) raise Bitcoin::Message::Error, "Invalid CJDNS address." unless a.to_s.start_with?('fc00:') a end addr.port = buf.read(2).unpack1('n') addr end |
.load_legacy_payload(payload) ⇒ Object
Load addr payload with legacy format.
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/bitcoin/message/network_addr.rb', line 105 def self.load_legacy_payload(payload) buf = payload.is_a?(String) ? StringIO.new(payload) : payload has_time = buf.size > 26 addr = NetworkAddr.new(time: nil) addr.time = buf.read(4).unpack1('V') if has_time addr.services = buf.read(8).unpack1('Q') addr.addr = IPAddr::new_ntoh(buf.read(16)) addr.port = buf.read(2).unpack1('n') addr end |
.local_addr ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/bitcoin/message/network_addr.rb', line 60 def self.local_addr addr = new addr.addr = IPAddr.new('127.0.0.1') addr.port = Bitcoin.chain_params.default_port addr.services = DEFAULT_SERVICE_FLAGS addr end |
.parse_from_payload(payload, type: TYPE[:legacy]) ⇒ NetworkAddr
Parse addr payload
49 50 51 52 53 54 55 56 57 58 |
# File 'lib/bitcoin/message/network_addr.rb', line 49 def self.parse_from_payload(payload, type: TYPE[:legacy]) case type when TYPE[:legacy] load_legacy_payload(payload) when TYPE[:addr_v2] load_addr_v2_payload(payload) else raise Bitcoin::Message::Error, "Unknown type: #{type}." end end |
Instance Method Details
#addr_string ⇒ Object
Show addr string. e.g 127.0.0.1
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/bitcoin/message/network_addr.rb', line 69 def addr_string case net when NETWORK_ID[:ipv4] addr.native when NETWORK_ID[:ipv6] if addr.to_s.start_with?(INTERNAL_IN_IPV6_PREFIX) Base32.encode(addr.hton[6..-1]).downcase.delete('=') + ".internal" else addr.to_s end when NETWORK_ID[:tor_v2] Base32.encode(addr.htb).downcase + ".onion" when NETWORK_ID[:tor_v3] # TORv3 onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion" pubkey = addr.htb checksum = OpenSSL::Digest.new('SHA3-256').digest('.onion checksum' + pubkey + "\x03") Base32.encode(pubkey + checksum[0...2] + "\x03").downcase + ".onion" when NETWORK_ID[:i2p] Base32.encode(addr.htb).downcase.delete('=') + ".b32.i2p" when NETWORK_ID[:cjdns] addr.to_s end end |
#legacy_payload(skip_time) ⇒ Object
152 153 154 155 156 157 |
# File 'lib/bitcoin/message/network_addr.rb', line 152 def legacy_payload(skip_time) p = '' p << [time].pack('V') unless skip_time ip = addr.ipv4? ? addr.ipv4_mapped : addr p << [services].pack('Q') << ip.hton << [port].pack('n') end |
#to_payload(skip_time = false, type: TYPE[:legacy]) ⇒ Object
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/bitcoin/message/network_addr.rb', line 93 def to_payload(skip_time = false, type: TYPE[:legacy]) case type when TYPE[:legacy] legacy_payload(skip_time) when TYPE[:addr_v2] v2_payload else raise Bitcoin::Message::Error, "Unknown type: #{type}." end end |
#v2_payload ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/bitcoin/message/network_addr.rb', line 159 def v2_payload p = [time].pack('V') p << Bitcoin.pack_var_int(services) p << [net].pack('C') case net when NETWORK_ID[:ipv4] p << Bitcoin.pack_var_int(4) p << addr.to_i.to_s(16).htb when NETWORK_ID[:ipv6] p << Bitcoin.pack_var_int(16) p << addr.hton when NETWORK_ID[:tor_v2] p << Bitcoin.pack_var_int(10) when NETWORK_ID[:tor_v3] p << Bitcoin.pack_var_int(32) when NETWORK_ID[:i2p] p << Bitcoin.pack_var_int(32) when NETWORK_ID[:cjdns] p << Bitcoin.pack_var_int(16) end p << [port].pack('n') p end |