Class: Bitcoin::Protocol::Version

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/protocol/version.rb

Overview

Constant Summary collapse

NODE_NONE =

services bit constants

0
NODE_NETWORK =
(1 << 0)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Version

Returns a new instance of Version.



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/bitcoin/protocol/version.rb', line 13

def initialize(opts = {})
  @fields = {
    version: Bitcoin.network[:protocol_version],
    services: NODE_NETWORK,
    time: Time.now.tv_sec,
    from: '127.0.0.1:8333',
    to: '127.0.0.1:8333',
    nonce: Bitcoin::Protocol::Uniq,
    user_agent: "/bitcoin-ruby:#{Bitcoin::VERSION}/",
    last_block: 0, # 188617
    relay: true # BIP0037
  }.merge(opts.reject { |_k, v| v.nil? })
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*a) ⇒ Object



84
85
86
87
88
# File 'lib/bitcoin/protocol/version.rb', line 84

def method_missing(*a)
  @fields[a.first]
rescue StandardError
  super
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



11
12
13
# File 'lib/bitcoin/protocol/version.rb', line 11

def fields
  @fields
end

Class Method Details

.parse(payload) ⇒ Object



96
97
98
# File 'lib/bitcoin/protocol/version.rb', line 96

def self.parse(payload)
  new.parse(payload)
end

Instance Method Details

#pack_address_field(addr_str) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/bitcoin/protocol/version.rb', line 65

def pack_address_field(addr_str)
  host, port = addr_str.split(':')
  port = port ? port.to_i : 8333
  sockaddr = Socket.pack_sockaddr_in(port, host)
  # raise "invalid IPv4 Address: #{addr}" unless sockaddr[0...2] == "\x02\x00"
  port = sockaddr[2...4]
  host = sockaddr[4...8]
  [[1].pack('Q'), "\x00" * 10, "\xFF\xFF", host, port].join
end

#parse(payload) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/bitcoin/protocol/version.rb', line 44

def parse(payload)
  version, services, timestamp, to, from, nonce, payload = payload.unpack('VQQa26a26Qa*')
  to = unpack_address_field(to)
  from = unpack_address_field(from)
  user_agent, payload = Protocol.unpack_var_string(payload)
  last_block, payload = payload.unpack('Va*')
  relay, = unpack_relay_field(version, payload)

  @fields = {
    version: version, services: services, time: timestamp,
    from: from, to: to, nonce: nonce,
    user_agent: user_agent.to_s, last_block: last_block, relay: relay
  }
  self
end

#respond_to_missing?(*a) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
93
94
# File 'lib/bitcoin/protocol/version.rb', line 90

def respond_to_missing?(*a)
  @fields[a.first]
rescue StandardError
  super
end

#to_payloadObject



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/bitcoin/protocol/version.rb', line 27

def to_payload
  [
    @fields.values_at(:version, :services, :time).pack('VQQ'),
    pack_address_field(@fields[:from]),
    pack_address_field(@fields[:to]),
    @fields.values_at(:nonce).pack('Q'),
    Protocol.pack_var_string(@fields[:user_agent]),
    @fields.values_at(:last_block).pack('V'),
    # Satoshi 0.8.6 doesn't send this but it does respect it
    Protocol.pack_boolean(@fields[:relay])
  ].join
end

#to_pktObject



40
41
42
# File 'lib/bitcoin/protocol/version.rb', line 40

def to_pkt
  Bitcoin::Protocol.pkt('version', to_payload)
end

#unpack_address_field(payload) ⇒ Object



60
61
62
63
# File 'lib/bitcoin/protocol/version.rb', line 60

def unpack_address_field(payload)
  ip, port = payload.unpack('x8x12a4n')
  "#{ip.unpack('C*').join('.')}:#{port}"
end

#unpack_relay_field(version, payload) ⇒ Object

BIP0037: this field starts with version 70001 and is allowed to be missing, defaults to true



76
77
78
# File 'lib/bitcoin/protocol/version.rb', line 76

def unpack_relay_field(version, payload)
  version >= 70_001 && payload ? Protocol.unpack_boolean(payload) : [true, nil]
end

#uptimeObject



80
81
82
# File 'lib/bitcoin/protocol/version.rb', line 80

def uptime
  @fields[:time] - Time.now.tv_sec
end