Class: Bitcoin::Network::Peer
- Inherits:
-
Object
- Object
- Bitcoin::Network::Peer
- Defined in:
- lib/bitcoin/network/peer.rb
Overview
remote peer class.
Constant Summary collapse
- PING_INTERVAL =
Interval for pinging peers.
2 * 60
Instance Attribute Summary collapse
-
#best_hash ⇒ Object
Returns the value of attribute best_hash.
-
#best_height ⇒ Object
Returns the value of attribute best_height.
-
#bytes_recv ⇒ Object
Returns the value of attribute bytes_recv.
-
#bytes_sent ⇒ Object
Returns the value of attribute bytes_sent.
-
#chain ⇒ Object
readonly
Returns the value of attribute chain.
-
#conn ⇒ Object
remote peer connection.
-
#conn_time ⇒ Object
Returns the value of attribute conn_time.
-
#connected ⇒ Object
Returns the value of attribute connected.
-
#fee_rate ⇒ Object
Returns the value of attribute fee_rate.
-
#host ⇒ Object
readonly
remote peer info.
-
#id ⇒ Object
Returns the value of attribute id.
-
#last_ping ⇒ Object
Returns the value of attribute last_ping.
-
#last_ping_nonce ⇒ Object
Returns the value of attribute last_ping_nonce.
-
#last_pong ⇒ Object
Returns the value of attribute last_pong.
-
#last_recv ⇒ Object
Returns the value of attribute last_recv.
-
#last_send ⇒ Object
Returns the value of attribute last_send.
-
#local_version ⇒ Object
Returns the value of attribute local_version.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#min_ping ⇒ Object
Returns the value of attribute min_ping.
-
#outbound ⇒ Object
TODO need implements to accept inbound connection.
-
#pool ⇒ Object
readonly
parent pool.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#primary ⇒ Object
Returns the value of attribute primary.
Instance Method Summary collapse
- #addr ⇒ Object
-
#block_type ⇒ Object
get peer’s block type.
-
#broadcast_tx(tx) ⇒ Object
broadcast tx.
-
#close(msg = '') ⇒ Object
close peer connection.
- #connect ⇒ Object
- #connected? ⇒ Boolean
-
#handle_block_inv(hashes) ⇒ Object
handle block inv message.
-
#handle_error(e) ⇒ Object
handle error.
-
#handle_headers(headers) ⇒ Object
handle headers message.
- #handle_merkle_block(merkle_block) ⇒ Object
- #handle_tx(tx) ⇒ Object
-
#initialize(host, port, pool, configuration) ⇒ Peer
constructor
A new instance of Peer.
- #outbound? ⇒ Boolean
-
#ping_time ⇒ Object
calculate ping-pong time.
- #post_handshake ⇒ Object
-
#primary? ⇒ Boolean
Whether to try and download blocks and transactions from this peer.
-
#remote_version ⇒ Bitcoin::Message::Version
get remote peer’s version message.
-
#send_addrs ⇒ Object
send
addr
message to remote peer. -
#send_filter_add(element) ⇒ Object
send filteradd message.
-
#send_filter_clear ⇒ Object
send filterclear message.
-
#send_filter_load(bloom) ⇒ Object
send filterload message.
-
#send_ping ⇒ Object
send ping message.
-
#start_block_header_download ⇒ Object
start block header download.
-
#support_cmpct? ⇒ Boolean
check the remote peer supports compact block.
-
#support_witness? ⇒ Boolean
check the remote peer support witness.
-
#to_network_addr ⇒ Bitcoin::Message::NetworkAddr
generate Bitcoin::Message::NetworkAddr object from this peer info.
- #unbind ⇒ Object
Constructor Details
#initialize(host, port, pool, configuration) ⇒ Peer
Returns a new instance of Peer.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/bitcoin/network/peer.rb', line 37 def initialize(host, port, pool, configuration) @host = host @port = port @pool = pool @chain = pool.chain @connected = false @primary = false @logger = Bitcoin::Logger.create(:debug) @outbound = true @best_hash = -1 @best_height = -1 @min_ping = -1 @bytes_sent = 0 @bytes_recv = 0 @relay = configuration.conf[:relay] current_height = @chain.latest_block.height remote_addr = Bitcoin::Message::NetworkAddr.new(ip: host, port: port, time: nil) @local_version = Bitcoin::Message::Version.new(remote_addr: remote_addr, start_height: current_height, relay: @relay) end |
Instance Attribute Details
#best_hash ⇒ Object
Returns the value of attribute best_hash.
23 24 25 |
# File 'lib/bitcoin/network/peer.rb', line 23 def best_hash @best_hash end |
#best_height ⇒ Object
Returns the value of attribute best_height.
24 25 26 |
# File 'lib/bitcoin/network/peer.rb', line 24 def best_height @best_height end |
#bytes_recv ⇒ Object
Returns the value of attribute bytes_recv.
16 17 18 |
# File 'lib/bitcoin/network/peer.rb', line 16 def bytes_recv @bytes_recv end |
#bytes_sent ⇒ Object
Returns the value of attribute bytes_sent.
15 16 17 |
# File 'lib/bitcoin/network/peer.rb', line 15 def bytes_sent @bytes_sent end |
#chain ⇒ Object (readonly)
Returns the value of attribute chain.
34 35 36 |
# File 'lib/bitcoin/network/peer.rb', line 34 def chain @chain end |
#conn ⇒ Object
remote peer connection
29 30 31 |
# File 'lib/bitcoin/network/peer.rb', line 29 def conn @conn end |
#conn_time ⇒ Object
Returns the value of attribute conn_time.
17 18 19 |
# File 'lib/bitcoin/network/peer.rb', line 17 def conn_time @conn_time end |
#connected ⇒ Object
Returns the value of attribute connected.
30 31 32 |
# File 'lib/bitcoin/network/peer.rb', line 30 def connected @connected end |
#fee_rate ⇒ Object
Returns the value of attribute fee_rate.
35 36 37 |
# File 'lib/bitcoin/network/peer.rb', line 35 def fee_rate @fee_rate end |
#host ⇒ Object (readonly)
remote peer info
26 27 28 |
# File 'lib/bitcoin/network/peer.rb', line 26 def host @host end |
#id ⇒ Object
Returns the value of attribute id.
11 12 13 |
# File 'lib/bitcoin/network/peer.rb', line 11 def id @id end |
#last_ping ⇒ Object
Returns the value of attribute last_ping.
18 19 20 |
# File 'lib/bitcoin/network/peer.rb', line 18 def last_ping @last_ping end |
#last_ping_nonce ⇒ Object
Returns the value of attribute last_ping_nonce.
19 20 21 |
# File 'lib/bitcoin/network/peer.rb', line 19 def last_ping_nonce @last_ping_nonce end |
#last_pong ⇒ Object
Returns the value of attribute last_pong.
20 21 22 |
# File 'lib/bitcoin/network/peer.rb', line 20 def last_pong @last_pong end |
#last_recv ⇒ Object
Returns the value of attribute last_recv.
14 15 16 |
# File 'lib/bitcoin/network/peer.rb', line 14 def last_recv @last_recv end |
#last_send ⇒ Object
Returns the value of attribute last_send.
13 14 15 |
# File 'lib/bitcoin/network/peer.rb', line 13 def last_send @last_send end |
#local_version ⇒ Object
Returns the value of attribute local_version.
12 13 14 |
# File 'lib/bitcoin/network/peer.rb', line 12 def local_version @local_version end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
10 11 12 |
# File 'lib/bitcoin/network/peer.rb', line 10 def logger @logger end |
#min_ping ⇒ Object
Returns the value of attribute min_ping.
21 22 23 |
# File 'lib/bitcoin/network/peer.rb', line 21 def min_ping @min_ping end |
#outbound ⇒ Object
TODO need implements to accept inbound connection
22 23 24 |
# File 'lib/bitcoin/network/peer.rb', line 22 def outbound @outbound end |
#pool ⇒ Object (readonly)
parent pool
33 34 35 |
# File 'lib/bitcoin/network/peer.rb', line 33 def pool @pool end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
27 28 29 |
# File 'lib/bitcoin/network/peer.rb', line 27 def port @port end |
#primary ⇒ Object
Returns the value of attribute primary.
31 32 33 |
# File 'lib/bitcoin/network/peer.rb', line 31 def primary @primary end |
Instance Method Details
#addr ⇒ Object
69 70 71 |
# File 'lib/bitcoin/network/peer.rb', line 69 def addr "#{host}:#{port}" end |
#block_type ⇒ Object
get peer’s block type.
125 126 127 |
# File 'lib/bitcoin/network/peer.rb', line 125 def block_type Bitcoin::Message::Inventory::MSG_FILTERED_BLOCK # TODO need other implementation end |
#broadcast_tx(tx) ⇒ Object
broadcast tx.
106 107 108 |
# File 'lib/bitcoin/network/peer.rb', line 106 def broadcast_tx(tx) conn.(Bitcoin::Message::Tx.new(tx, support_witness?)) end |
#close(msg = '') ⇒ Object
close peer connection.
165 166 167 |
# File 'lib/bitcoin/network/peer.rb', line 165 def close(msg = '') conn.close(msg) end |
#connect ⇒ Object
57 58 59 |
# File 'lib/bitcoin/network/peer.rb', line 57 def connect self.conn ||= EM.connect(host, port, Bitcoin::Network::Connection, self) end |
#connected? ⇒ Boolean
61 62 63 |
# File 'lib/bitcoin/network/peer.rb', line 61 def connected? @connected end |
#handle_block_inv(hashes) ⇒ Object
handle block inv message.
183 184 185 186 187 |
# File 'lib/bitcoin/network/peer.rb', line 183 def handle_block_inv(hashes) getdata = Bitcoin::Message::GetData.new( hashes.map{|h|Bitcoin::Message::Inventory.new(block_type, h)}) conn.(getdata) end |
#handle_error(e) ⇒ Object
handle error
156 157 158 |
# File 'lib/bitcoin/network/peer.rb', line 156 def handle_error(e) pool.handle_error(e) end |
#handle_headers(headers) ⇒ Object
handle headers message
142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/bitcoin/network/peer.rb', line 142 def handle_headers(headers) headers.headers.each do |header| break unless header.valid? entry = chain.append_header(header) next unless entry @best_hash = entry.block_hash @best_height = entry.height end pool.changed pool.notify_observers(:header, {hash: @best_hash, height: @best_height}) start_block_header_download if headers.headers.size > 0 # next header download end |
#handle_merkle_block(merkle_block) ⇒ Object
194 195 196 197 |
# File 'lib/bitcoin/network/peer.rb', line 194 def handle_merkle_block(merkle_block) pool.changed pool.notify_observers(:merkleblock, merkle_block) end |
#handle_tx(tx) ⇒ Object
189 190 191 192 |
# File 'lib/bitcoin/network/peer.rb', line 189 def handle_tx(tx) pool.changed pool.notify_observers(:tx, tx) end |
#outbound? ⇒ Boolean
65 66 67 |
# File 'lib/bitcoin/network/peer.rb', line 65 def outbound? @outbound end |
#ping_time ⇒ Object
calculate ping-pong time.
74 75 76 |
# File 'lib/bitcoin/network/peer.rb', line 74 def ping_time last_pong ? (last_pong - last_ping) / 1e6 : -1 end |
#post_handshake ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/bitcoin/network/peer.rb', line 84 def post_handshake @connected = true if remote_version.support?(Bitcoin::Message::SERVICE_FLAGS[:bloom]) pool.handle_new_peer(self) # require remote peer to use headers message instead fo inv message. conn.(Bitcoin::Message::SendHeaders.new) EM.add_periodic_timer(PING_INTERVAL) {send_ping} else close("peer does not support NODE_BLOOM.") pool.pending_peers.delete(self) end end |
#primary? ⇒ Boolean
Whether to try and download blocks and transactions from this peer.
136 137 138 |
# File 'lib/bitcoin/network/peer.rb', line 136 def primary? primary end |
#remote_version ⇒ Bitcoin::Message::Version
get remote peer’s version message.
131 132 133 |
# File 'lib/bitcoin/network/peer.rb', line 131 def remote_version conn.version end |
#send_addrs ⇒ Object
send addr
message to remote peer
177 178 179 180 |
# File 'lib/bitcoin/network/peer.rb', line 177 def send_addrs addrs = pool.peers.select{|p|p != self}.map(&:to_network_addr) conn.(Bitcoin::Message::Addr.new(addrs)) end |
#send_filter_add(element) ⇒ Object
send filteradd message.
216 217 218 219 |
# File 'lib/bitcoin/network/peer.rb', line 216 def send_filter_add(element) filter_add = Bitcoin::Message::FilterAdd.new(element) conn.(filter_add) end |
#send_filter_clear ⇒ Object
send filterclear message.
222 223 224 225 |
# File 'lib/bitcoin/network/peer.rb', line 222 def send_filter_clear filter_clear = Bitcoin::Message::FilterClear.new conn.(filter_clear) end |
#send_filter_load(bloom) ⇒ Object
send filterload message.
209 210 211 212 213 |
# File 'lib/bitcoin/network/peer.rb', line 209 def send_filter_load(bloom) filter_load = Bitcoin::Message::FilterLoad.new( bloom, Bitcoin::Message::FilterLoad::BLOOM_UPDATE_ALL) conn.(filter_load) end |
#send_ping ⇒ Object
send ping message.
200 201 202 203 204 205 206 |
# File 'lib/bitcoin/network/peer.rb', line 200 def send_ping ping = Bitcoin::Message::Ping.new @last_ping = Time.now.to_i @last_pong = -1 @last_ping_nonce = ping.nonce conn.(ping) end |
#start_block_header_download ⇒ Object
start block header download
98 99 100 101 102 103 |
# File 'lib/bitcoin/network/peer.rb', line 98 def start_block_header_download logger.info("[#{addr}] start block header download.") get_headers = Bitcoin::Message::GetHeaders.new( Bitcoin.chain_params.protocol_version, [chain.latest_block.block_hash]) conn.(get_headers) end |
#support_cmpct? ⇒ Boolean
check the remote peer supports compact block.
117 118 119 120 121 122 |
# File 'lib/bitcoin/network/peer.rb', line 117 def support_cmpct? return false if remote_version.version < Bitcoin::Message::VERSION[:compact] return true unless local_version.services & Bitcoin::Message::SERVICE_FLAGS[:witness] > 0 return false unless support_witness? remote_version.version >= Bitcoin::Message::VERSION[:compact_witness] end |
#support_witness? ⇒ Boolean
check the remote peer support witness.
111 112 113 114 |
# File 'lib/bitcoin/network/peer.rb', line 111 def support_witness? return false unless remote_version remote_version.services & Bitcoin::Message::SERVICE_FLAGS[:witness] > 0 end |
#to_network_addr ⇒ Bitcoin::Message::NetworkAddr
generate Bitcoin::Message::NetworkAddr object from this peer info.
171 172 173 174 |
# File 'lib/bitcoin/network/peer.rb', line 171 def to_network_addr v = remote_version Bitcoin::Message::NetworkAddr.new(ip: host, port: port, services: v.services, time: v.) end |
#unbind ⇒ Object
160 161 162 |
# File 'lib/bitcoin/network/peer.rb', line 160 def unbind pool.handle_close_peer(self) end |