bitcoinrb 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/bitcoinrb.gemspec +7 -3
  4. data/exe/bitcoinrb-cli +1 -1
  5. data/exe/bitcoinrbd +9 -23
  6. data/lib/bitcoin/block.rb +66 -0
  7. data/lib/bitcoin/block_header.rb +33 -1
  8. data/lib/bitcoin/chain_params.rb +11 -4
  9. data/lib/bitcoin/chainparams/mainnet.yml +9 -2
  10. data/lib/bitcoin/chainparams/regtest.yml +9 -1
  11. data/lib/bitcoin/chainparams/testnet.yml +9 -1
  12. data/lib/bitcoin/constants.rb +13 -0
  13. data/lib/bitcoin/ext_key.rb +2 -1
  14. data/lib/bitcoin/merkle_tree.rb +50 -51
  15. data/lib/bitcoin/message/block.rb +5 -0
  16. data/lib/bitcoin/message.rb +5 -5
  17. data/lib/bitcoin/network/connection.rb +58 -0
  18. data/lib/bitcoin/network/message_handler.rb +192 -0
  19. data/lib/bitcoin/network/peer.rb +55 -0
  20. data/lib/bitcoin/network/peer_discovery.rb +34 -0
  21. data/lib/bitcoin/network/pool.rb +74 -0
  22. data/lib/bitcoin/network.rb +14 -0
  23. data/lib/bitcoin/node/spv.rb +39 -0
  24. data/lib/bitcoin/node/spv_block_chain.rb +15 -0
  25. data/lib/bitcoin/node.rb +6 -0
  26. data/lib/bitcoin/script/script.rb +13 -0
  27. data/lib/bitcoin/store/spv_block_store.rb +11 -0
  28. data/lib/bitcoin/store.rb +7 -0
  29. data/lib/bitcoin/tx.rb +11 -0
  30. data/lib/bitcoin/tx_out.rb +2 -0
  31. data/lib/bitcoin/validation.rb +33 -11
  32. data/lib/bitcoin/version.rb +1 -1
  33. data/lib/bitcoin.rb +5 -2
  34. data/lib/openassets/marker_output.rb +14 -0
  35. data/lib/openassets/payload.rb +45 -0
  36. data/lib/openassets.rb +8 -0
  37. metadata +59 -8
  38. data/lib/bitcoin/connection.rb +0 -68
  39. data/lib/bitcoin/message/handler.rb +0 -183
  40. data/lib/bitcoin/nodes/spv/cli.rb +0 -12
  41. data/lib/bitcoin/nodes/spv/daemon.rb +0 -21
  42. data/lib/bitcoin/nodes/spv.rb +0 -13
  43. data/lib/bitcoin/nodes.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a527d6ef43eda02e2ef56d64edb5da7dfa04a956
4
- data.tar.gz: b1a7902b2be175f6f771ca3a418cbf869ab9dc7e
3
+ metadata.gz: c1508c7b3cad66796b7ef2bde7e744e478eb5f6c
4
+ data.tar.gz: 11c7f275b40ec3a70f5f55607ec4f8aee4ea0bd4
5
5
  SHA512:
6
- metadata.gz: ec03a93f28a17efdd812eaf1dd13e3a3f5ad947393bd8e29e6040116558dd9bbfc193419cc1a69bd623b36c4bb141e5957010ec989fca9301d851b461a78f79a
7
- data.tar.gz: bb41bbb4b43700e9a587e2e8d157a1ab7be358a14b9bd44ab349fdc19275c124e407ea9093f68b8cb218d61c0800efc348c8b4fbc202884ecb8e0ab0c3baa347
6
+ metadata.gz: '095ba38bc01e7ef0b83091f63c537f2ce06e0cd91645fcbc7988da05ff54ea25dcf85f9725782d3f5e16057b5c5777275e7ad12c77388e32153f37100c724bbb'
7
+ data.tar.gz: 5aa55097029750cf282dc23a1caa5702e1b21a942409adeac25836b083d59fc6994f72300fc76c8415c5d9f21f01b3af0b5d188a9ca035734971cbac0ffd03d3
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ bitcoinrbd.yml
data/bitcoinrb.gemspec CHANGED
@@ -26,8 +26,12 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency 'daemon-spawn'
27
27
  spec.add_runtime_dependency 'thor'
28
28
  spec.add_runtime_dependency 'ffi'
29
+ spec.add_runtime_dependency 'parallel'
30
+ spec.add_runtime_dependency 'leb128', '~> 1.0.0'
31
+
32
+ spec.add_development_dependency 'bundler', '~> 1.11'
33
+ spec.add_development_dependency 'rake', '~> 10.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'timecop'
29
36
 
30
- spec.add_development_dependency "bundler", "~> 1.11"
31
- spec.add_development_dependency "rake", "~> 10.0"
32
- spec.add_development_dependency "rspec", "~> 3.0"
33
37
  end
data/exe/bitcoinrb-cli CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bitcoin/nodes/spv/cli'
3
+ require 'bitcoin/node/spv/cli'
4
4
 
5
5
  Bitcoin::Nodes::SPV::CLI.start(ARGV)
data/exe/bitcoinrbd CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'thor'
3
3
  require 'bitcoin'
4
- require 'bitcoin/nodes/spv/daemon'
4
+ require 'bitcoin/node/spv'
5
5
 
6
6
  class Bitcoinrbd < Thor
7
7
 
@@ -10,40 +10,26 @@ class Bitcoinrbd < Thor
10
10
  desc 'start', 'start bitcoinrbd daemon process'
11
11
  def start
12
12
  raise ArgumentError, 'currently only support spv mode.' unless options[:mode] == 'spv'
13
- execute_daemon(setup_base_dir(options[:network]), ['start'])
13
+ Bitcoin.chain_params = network.to_sym
14
+ FileUtils.mkdir_p(Bitcoin.base_dir)
15
+ execute_daemon(['start'])
14
16
  end
15
17
 
16
18
  option :mode, default: 'spv'
17
19
  option :network, default: 'mainnet'
18
20
  desc 'stop', 'start bitcoinrbd daemon process'
19
21
  def stop
20
- execute_daemon(setup_base_dir(options[:network]), ['stop'])
22
+ execute_daemon(['stop'])
21
23
  end
22
24
 
23
- def execute_daemon(base_dir, cmd_args)
24
- Bitcoin::Nodes::SPV::Daemon.spawn!({working_dir: base_dir,
25
- log_file: "#{base_dir}/bitcoinrbd.log",
26
- pid_file: "#{base_dir}/bitcoinrbd.pid",
25
+ def execute_daemon(cmd_args)
26
+ Bitcoin::Nodes::SPV.spawn!({working_dir: Bitcoin.base_dir,
27
+ log_file: "#{Bitcoin.base_dir}/bitcoinrbd.log",
28
+ pid_file: "#{Bitcoin.base_dir}/bitcoinrbd.pid",
27
29
  sync_log: true,
28
30
  singleton: true}, cmd_args)
29
31
  end
30
32
 
31
- private
32
-
33
- def setup_base_dir(network)
34
- case network
35
- when 'mainnet'
36
- base_dir = Bitcoin.base_dir
37
- when 'testnet'
38
- base_dir = "#{Bitcoin.base_dir}/testnet3"
39
- when 'regtest'
40
- base_dir = "#{Bitcoin.base_dir}/regtest"
41
- else
42
- raise ArgumentError, 'Unsupported network specified.'
43
- end
44
- FileUtils.mkdir_p(base_dir)
45
- base_dir
46
- end
47
33
  end
48
34
 
49
35
  Bitcoinrbd.start(ARGV)
@@ -0,0 +1,66 @@
1
+ module Bitcoin
2
+ class Block
3
+
4
+ attr_accessor :header
5
+ attr_accessor :transactions
6
+
7
+ def initialize(header, transactions = [])
8
+ @header = header
9
+ @transactions = transactions
10
+ end
11
+
12
+ # calculate block weight
13
+ def weight
14
+ stripped_size * (WITNESS_SCALE_FACTOR - 1) + size
15
+ end
16
+
17
+ # calculate total size (include witness data.)
18
+ def size
19
+ 80 + Bitcoin.pack_var_int(transactions.size).bytesize +
20
+ transactions.inject(0){|sum, tx| sum + (tx.witness? ? tx.serialize_witness_format.bytesize : tx.serialize_old_format.bytesize)}
21
+ end
22
+
23
+ # calculate base size (not include witness data.)
24
+ def stripped_size
25
+ 80 + Bitcoin.pack_var_int(transactions.size).bytesize +
26
+ transactions.inject(0){|sum, tx| sum + tx.serialize_old_format.bytesize}
27
+ end
28
+
29
+ # check the merkle root in the block header matches merkle root calculated from tx list.
30
+ def valid_merkle_root?
31
+ calculate_merkle_root == header.merkle_root
32
+ end
33
+
34
+ # calculate merkle root from tx list.
35
+ def calculate_merkle_root
36
+ Bitcoin::MerkleTree.build_from_leaf(transactions.map(&:txid)).merkle_root
37
+ end
38
+
39
+ # check the witness commitment in coinbase tx matches witness commitment calculated from tx list.
40
+ def valid_witness_commitment?
41
+ transactions[0].witness_commitment == calculate_witness_commitment
42
+ end
43
+
44
+ # calculate witness commitment from tx list.
45
+ def calculate_witness_commitment
46
+ wtxid_list = [COINBASE_WTXID]
47
+ wtxid_list.concat(transactions[1..-1].map{|tx| tx.wtxid})
48
+ reserved_value = transactions[0].inputs[0].script_witness.stack.map(&:bth).join
49
+ root_hash = Bitcoin::MerkleTree.build_from_leaf(wtxid_list).merkle_root
50
+ Digest::SHA256.digest(Digest::SHA256.digest(
51
+ [reserved_value + root_hash].pack('H*').reverse )).bth
52
+ end
53
+
54
+ # return this block height. block height is included in coinbase.
55
+ # if block version under 1, height does not include in coinbase, so return nil.
56
+ def height
57
+ return nil if header.version < 2
58
+ coinbase_tx = transactions[0]
59
+ return nil unless coinbase_tx.coinbase_tx?
60
+ buf = StringIO.new(coinbase_tx.inputs[0].script_sig.to_payload)
61
+ len = Bitcoin.unpack_var_int_from_io(buf)
62
+ buf.read(len).reverse.bth.to_i(16)
63
+ end
64
+
65
+ end
66
+ end
@@ -7,7 +7,7 @@ module Bitcoin
7
7
  attr_accessor :version
8
8
  attr_accessor :prev_hash
9
9
  attr_accessor :merkle_root
10
- attr_accessor :time
10
+ attr_accessor :time # unix timestamp
11
11
  attr_accessor :bits
12
12
  attr_accessor :nonce
13
13
 
@@ -30,6 +30,38 @@ module Bitcoin
30
30
  [version, prev_hash.htb.reverse, merkle_root.htb.reverse, time, bits, nonce].pack('Va32a32VVV')
31
31
  end
32
32
 
33
+ # compute difficulty target from bits.
34
+ def difficulty_target
35
+ exponent = ((bits >> 24) & 0xff)
36
+ mantissa = bits & 0x7fffff
37
+ mantissa *= -1 if (bits & 0x800000) > 0
38
+ (mantissa * 2 ** (8 * (exponent - 3)))
39
+ end
40
+
41
+ # evaluate block header
42
+ def valid?
43
+ valid_pow? && valid_timestamp?
44
+ end
45
+
46
+ # evaluate valid proof of work.
47
+ def valid_pow?
48
+ hash.hex < difficulty_target
49
+ end
50
+
51
+ # evaluate valid timestamp.
52
+ # https://en.bitcoin.it/wiki/Block_timestamp
53
+ def valid_timestamp?
54
+ time <= Time.now.to_i + Bitcoin::MAX_FUTURE_BLOCK_TIME
55
+ end
56
+
57
+ # compute chain work of this block.
58
+ # @return [Integer] a chain work.
59
+ def work
60
+ target = difficulty_target
61
+ return 0 if target < 1
62
+ (2**256) / (target + 1)
63
+ end
64
+
33
65
  private
34
66
 
35
67
  def calc_hash
@@ -21,21 +21,21 @@ module Bitcoin
21
21
  attr_reader :target_spacing
22
22
  attr_reader :max_money
23
23
  attr_reader :bip34_height
24
- attr_reader :genesis_hash
25
24
  attr_reader :proof_of_work_limit
26
25
  attr_reader :dns_seeds
26
+ attr_reader :genesis
27
27
 
28
- # mainnet params
28
+ # mainnet genesis
29
29
  def self.mainnet
30
30
  YAML.load(File.open("#{__dir__}/chainparams/mainnet.yml"))
31
31
  end
32
32
 
33
- # testnet params
33
+ # testnet genesis
34
34
  def self.testnet
35
35
  YAML.load(File.open("#{__dir__}/chainparams/testnet.yml"))
36
36
  end
37
37
 
38
- # regtest params
38
+ # regtest genesis
39
39
  def self.regtest
40
40
  YAML.load(File.open("#{__dir__}/chainparams/regtest.yml"))
41
41
  end
@@ -52,6 +52,13 @@ module Bitcoin
52
52
  network == 'regtest'
53
53
  end
54
54
 
55
+ def genesis_block
56
+ header = Bitcoin::BlockHeader.new(
57
+ genesis['version'], genesis['prev_hash'], genesis['merkle_root'],
58
+ genesis['time'], genesis['bits'], genesis['nonce'])
59
+ Bitcoin::Block.new(header)
60
+ end
61
+
55
62
  end
56
63
 
57
64
  end
@@ -15,11 +15,18 @@ retarget_time: 1209600 # 2 weeks
15
15
  target_spacing: 600 # block interval
16
16
  max_money: 21000000
17
17
  bip34_height: 227931
18
- genesis_hash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
19
18
  proof_of_work_limit: 0x1d00ffff
20
19
  dns_seeds:
21
20
  - "seed.bitcoin.sipa.be"
22
21
  - "dnsseed.bluematt.me"
23
22
  - "dnsseed.bitcoin.dashjr.org"
24
23
  - "seed.bitcoinstats.com"
25
- - "seed.bitcoin.jonasschnelli.ch"
24
+ - "seed.bitcoin.jonasschnelli.ch"
25
+ genesis:
26
+ hash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
27
+ merkle_root: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
28
+ time: 1231006505
29
+ nonce: 2083236893
30
+ bits: 0x1d00ffff
31
+ version: 1
32
+ prev_hash: "0000000000000000000000000000000000000000000000000000000000000000"
@@ -17,4 +17,12 @@ max_money: 21000000
17
17
  bip34_height: 0
18
18
  genesis_hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
19
19
  proof_of_work_limit: 0x207fffff
20
- dns_seeds:
20
+ dns_seeds:
21
+ genesis:
22
+ hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
23
+ merkle_root: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
24
+ time: 1296688602
25
+ nonce: 2
26
+ bits: 0x207fffff
27
+ version: 1
28
+ prev_hash: "0000000000000000000000000000000000000000000000000000000000000000"
@@ -21,4 +21,12 @@ dns_seeds:
21
21
  - "testnet-seed.bitcoin.jonasschnelli.ch"
22
22
  - "seed.tbtc.petertodd.org"
23
23
  - "testnet-seed.bluematt.me"
24
- - "testnet-seed.bitcoin.schildbach.de"
24
+ - "testnet-seed.bitcoin.schildbach.de"
25
+ genesis:
26
+ hash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
27
+ merkle_root: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
28
+ time: 1296688602
29
+ nonce: 414098458
30
+ bits: 0x1d00ffff
31
+ version: 1
32
+ prev_hash: "0000000000000000000000000000000000000000000000000000000000000000"
@@ -154,4 +154,17 @@ module Bitcoin
154
154
  ERRCODES_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [const_get(c), c.to_s] }.flatten]
155
155
  NAME_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [c.to_s, const_get(c)] }.flatten]
156
156
 
157
+ # witness commitment
158
+ WITNESS_COMMITMENT_HEADER = 'aa21a9ed'
159
+
160
+ COINBASE_WTXID = '00'* 32
161
+
162
+ # for message
163
+ MESSAGE_HEADER_SIZE = 24
164
+
165
+ # for peer
166
+ PARALLEL_THREAD = 3
167
+
168
+ # Maximum amount of time that a block timestamp is allowed to exceed the current network-adjusted time before the block will be accepted.
169
+ MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60
157
170
  end
@@ -17,11 +17,12 @@ module Bitcoin
17
17
  attr_accessor :parent_fingerprint
18
18
 
19
19
  # generate master key from seed.
20
+ # @params [String] seed a seed data with hex format.
20
21
  def self.generate_master(seed)
21
22
  ext_key = ExtKey.new
22
23
  ext_key.depth = ext_key.number = 0
23
24
  ext_key.parent_fingerprint = '00000000'
24
- l = Bitcoin.hmac_sha512('Bitcoin seed', seed)
25
+ l = Bitcoin.hmac_sha512('Bitcoin seed', seed.htb)
25
26
  left = l[0..31].bth.to_i(16)
26
27
  raise 'invalid key' if left >= CURVE_ORDER || left == 0
27
28
  ext_key.key = Bitcoin::Key.new(priv_key: l[0..31].bth)
@@ -52,69 +52,68 @@ module Bitcoin
52
52
  nodes.first
53
53
  end
54
54
 
55
- end
56
-
57
- # node of merkle tree
58
- class Node
55
+ # node of merkle tree
56
+ class Node
59
57
 
60
- attr_accessor :flag
61
- attr_accessor :hash
62
- attr_accessor :parent
63
- attr_accessor :left
64
- attr_accessor :right
58
+ attr_accessor :flag
59
+ attr_accessor :hash
60
+ attr_accessor :parent
61
+ attr_accessor :left
62
+ attr_accessor :right
65
63
 
66
- def initialize(hash = nil)
67
- @hash = hash
68
- end
64
+ def initialize(hash = nil)
65
+ @hash = hash
66
+ end
69
67
 
70
- def left=(node)
71
- node.parent = self
72
- @left = node
73
- end
68
+ def left=(node)
69
+ node.parent = self
70
+ @left = node
71
+ end
74
72
 
75
- def right=(node)
76
- node.parent = self
77
- @right = node
78
- end
73
+ def right=(node)
74
+ node.parent = self
75
+ @right = node
76
+ end
79
77
 
80
- def hash
81
- return @hash if @hash
82
- self.right = left.dup unless right
83
- Digest::SHA256.digest(Digest::SHA256.digest(
84
- [right.hash + left.hash].pack('H*').reverse )).reverse.bth
85
- end
78
+ def hash
79
+ return @hash if @hash
80
+ self.right = left.dup unless right
81
+ Digest::SHA256.digest(Digest::SHA256.digest(
82
+ [right.hash + left.hash].pack('H*').reverse )).reverse.bth
83
+ end
86
84
 
87
- def root?
88
- parent.nil?
89
- end
85
+ def root?
86
+ parent.nil?
87
+ end
90
88
 
91
- def leaf?
92
- right.nil? && left.nil?
93
- end
89
+ def leaf?
90
+ right.nil? && left.nil?
91
+ end
94
92
 
95
- def partial?
96
- !flag.nil?
97
- end
93
+ def partial?
94
+ !flag.nil?
95
+ end
98
96
 
99
- def next_partial
100
- return nil if root? && (flag.zero? || (left.partial? && right.partial?))
101
- return parent.next_partial if flag.zero? || leaf?
102
- return left unless left.partial?
103
- self.right = left.dup unless right
104
- right.partial? ? parent.next_partial : right
105
- end
97
+ def next_partial
98
+ return nil if root? && (flag.zero? || (left.partial? && right.partial?))
99
+ return parent.next_partial if flag.zero? || leaf?
100
+ return left unless left.partial?
101
+ self.right = left.dup unless right
102
+ right.partial? ? parent.next_partial : right
103
+ end
106
104
 
107
- # calculate the depth of this node in the tree.
108
- def depth
109
- d = 0
110
- current_node = self
111
- until current_node.root? do
112
- current_node = current_node.parent
113
- d += 1
105
+ # calculate the depth of this node in the tree.
106
+ def depth
107
+ d = 0
108
+ current_node = self
109
+ until current_node.root? do
110
+ current_node = current_node.parent
111
+ d += 1
112
+ end
113
+ d
114
114
  end
115
- d
116
- end
117
115
 
116
+ end
118
117
  end
119
118
 
120
119
  end
@@ -35,6 +35,11 @@ module Bitcoin
35
35
  transactions.map{|t|use_segwit ? t.to_payload : t.serialize_old_format}.join
36
36
  end
37
37
 
38
+ # generate Bitcoin::Block object.
39
+ def to_block
40
+ Bitcoin::Block.new(header, transactions)
41
+ end
42
+
38
43
  end
39
44
 
40
45
  end
@@ -1,7 +1,6 @@
1
1
  module Bitcoin
2
2
  module Message
3
3
 
4
- autoload :Handler, 'bitcoin/message/handler'
5
4
  autoload :Base, 'bitcoin/message/base'
6
5
  autoload :Inventory, 'bitcoin/message/inventory'
7
6
  autoload :InventoriesParser, 'bitcoin/message/inventories_parser'
@@ -31,19 +30,20 @@ module Bitcoin
31
30
  autoload :Reject, 'bitcoin/message/reject'
32
31
  autoload :SendCmpct, 'bitcoin/message/send_cmpct'
33
32
 
34
- HEADER_SIZE = 24
35
33
  USER_AGENT = "/bitcoinrb:#{Bitcoin::VERSION}/"
36
34
 
37
35
  SERVICE_FLAGS = {
38
36
  none: 0,
39
- network: 1 << 0, # the node is capable of serving the block chain. It is currently set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want network services but don't provide them.
37
+ network: 1 << 0, # the node is capable of serving the block chain. It is currently set by all Bitcoin Core node, and is unset by SPV clients or other peers that just want network services but don't provide them.
40
38
  # getutxo: 1 << 1, # BIP-64. not implemented in Bitcoin Core.
41
- bloom: 1 << 2, # the node is capable and willing to handle bloom-filtered connections. Bitcoin Core nodes used to support this by default, without advertising this bit, but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
39
+ bloom: 1 << 2, # the node is capable and willing to handle bloom-filtered connections. Bitcoin Core node used to support this by default, without advertising this bit, but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
42
40
  witness: 1 << 3, # the node can be asked for blocks and transactions including witness data.
43
41
  # xthin: 1 << 4 # support Xtreme Thinblocks. not implemented in Bitcoin Core
44
42
  }
45
43
 
46
- DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:network] | SERVICE_FLAGS[:bloom] | SERVICE_FLAGS[:witness]
44
+ # DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:network] | SERVICE_FLAGS[:bloom] | SERVICE_FLAGS[:witness]
45
+
46
+ DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:none] | SERVICE_FLAGS[:witness]
47
47
 
48
48
  DEFAULT_STOP_HASH = "00"*32
49
49
 
@@ -0,0 +1,58 @@
1
+ module Bitcoin
2
+
3
+ module Network
4
+
5
+ # Basic Bitcoin P2P connection class
6
+ class Connection < EM::Connection
7
+
8
+ include MessageHandler
9
+
10
+ attr_reader :peer, :logger
11
+
12
+ # remote peer version.
13
+ attr_accessor :version
14
+
15
+ # if true, this peer send new block announcements using a headers message rather than an inv message.
16
+ attr_accessor :sendheaders
17
+
18
+ # minimum fee(in satoshis per kilobyte) for relay tx
19
+ attr_accessor :fee_rate
20
+
21
+ def initialize(peer)
22
+ @peer = peer
23
+ @logger = Bitcoin::Logger.create(:debug)
24
+ @sendheaders = false
25
+ @attr_accessor = 0
26
+ @message = ''
27
+ end
28
+
29
+ def post_init
30
+ logger.info "connected. #{addr}"
31
+ begin_handshake
32
+ end
33
+
34
+ # handle receiving data from remote node.
35
+ def receive_data(data)
36
+ handle(data)
37
+ end
38
+
39
+ def post_handshake
40
+ peer.post_handshake
41
+ end
42
+
43
+ def addr
44
+ peer.addr
45
+ end
46
+
47
+ # close network connection.
48
+ def close(msg = '')
49
+ logger.info "close connection with #{addr}. #{msg}"
50
+ close_connection_after_writing
51
+ EM.stop
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end