class Bitcoin::Network::Peer

remote peer class.

Constants

PING_INTERVAL

Interval for pinging peers.

Attributes

best_hash[RW]
best_height[RW]
bytes_recv[RW]
bytes_sent[RW]
chain[R]
conn[RW]

remote peer connection

conn_time[RW]
connected[RW]
fee_rate[RW]
host[R]

remote peer info

id[RW]
last_ping[RW]
last_ping_nonce[RW]
last_pong[RW]
last_recv[RW]
last_send[RW]
local_version[RW]
logger[R]
min_ping[RW]
outbound[RW]
pool[R]

parent pool

port[R]
primary[RW]

Public Class Methods

new(host, port, pool, configuration) click to toggle source
# 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

Public Instance Methods

addr() click to toggle source
# File lib/bitcoin/network/peer.rb, line 69
def addr
  "#{host}:#{port}"
end
block_type() click to toggle source

get peer's block type.

# 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) click to toggle source

broadcast tx.

# File lib/bitcoin/network/peer.rb, line 106
def broadcast_tx(tx)
  conn.send_message(Bitcoin::Message::Tx.new(tx, support_witness?))
end
close(msg = '') click to toggle source

close peer connection.

# File lib/bitcoin/network/peer.rb, line 165
def close(msg = '')
  conn.close(msg)
end
connect() click to toggle source
# File lib/bitcoin/network/peer.rb, line 57
def connect
  self.conn ||= EM.connect(host, port, Bitcoin::Network::Connection, self)
end
connected?() click to toggle source
# File lib/bitcoin/network/peer.rb, line 61
def connected?
  @connected
end
handle_block_inv(hashes) click to toggle source

handle block inv message.

# 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.send_message(getdata)
end
handle_error(e) click to toggle source

handle error

# File lib/bitcoin/network/peer.rb, line 156
def handle_error(e)
  pool.handle_error(e)
end
handle_headers(headers) click to toggle source

handle headers message @params [Bitcoin::Message::Headers]

# 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) click to toggle source
# 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) click to toggle source
# File lib/bitcoin/network/peer.rb, line 189
def handle_tx(tx)
  pool.changed
  pool.notify_observers(:tx, tx)
end
last_pong=(time) click to toggle source

set last pong

# File lib/bitcoin/network/peer.rb, line 79
def last_pong=(time)
  @last_pong = time
  @min_ping = ping_time if min_ping == -1 || ping_time < min_ping
end
outbound?() click to toggle source
# File lib/bitcoin/network/peer.rb, line 65
def outbound?
  @outbound
end
ping_time() click to toggle source

calculate ping-pong time.

# File lib/bitcoin/network/peer.rb, line 74
def ping_time
  last_pong ? (last_pong - last_ping) / 1e6 : -1
end
post_handshake() click to toggle source
# 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.send_message(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?() click to toggle source

Whether to try and download blocks and transactions from this peer.

# File lib/bitcoin/network/peer.rb, line 136
def primary?
  primary
end
remote_version() click to toggle source

get remote peer's version message. @return [Bitcoin::Message::Version]

# File lib/bitcoin/network/peer.rb, line 131
def remote_version
  conn.version
end
send_addrs() click to toggle source

send addr message to remote peer

# File lib/bitcoin/network/peer.rb, line 177
def send_addrs
  addrs = pool.peers.select{|p|p != self}.map(&:to_network_addr)
  conn.send_message(Bitcoin::Message::Addr.new(addrs))
end
send_filter_add(element) click to toggle source

send filteradd message.

# File lib/bitcoin/network/peer.rb, line 216
def send_filter_add(element)
  filter_add = Bitcoin::Message::FilterAdd.new(element)
  conn.send_message(filter_add)
end
send_filter_clear() click to toggle source

send filterclear message.

# File lib/bitcoin/network/peer.rb, line 222
def send_filter_clear
  filter_clear = Bitcoin::Message::FilterClear.new
  conn.send_message(filter_clear)
end
send_filter_load(bloom) click to toggle source

send filterload message.

# 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.send_message(filter_load)
end
send_ping() click to toggle source

send ping message.

# 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.send_message(ping)
end
start_block_header_download() click to toggle source

start block header download

# 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.send_message(get_headers)
end
support_cmpct?() click to toggle source

check the remote peer supports compact block.

# 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?() click to toggle source

check the remote peer support witness.

# 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() click to toggle source

generate Bitcoin::Message::NetworkAddr object from this peer info. @return [Bitcoin::Message::NetworkAddr]

# 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.timestamp)
end
unbind() click to toggle source
# File lib/bitcoin/network/peer.rb, line 160
def unbind
  pool.handle_close_peer(self)
end