bitcoinrb 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/README.md +31 -9
  4. data/bitcoinrb.conf.sample +0 -0
  5. data/bitcoinrb.gemspec +6 -2
  6. data/exe/bitcoinrb-cli +2 -2
  7. data/lib/bitcoin/block_header.rb +9 -2
  8. data/lib/bitcoin/chainparams/regtest.yml +1 -1
  9. data/lib/bitcoin/constants.rb +3 -0
  10. data/lib/bitcoin/key.rb +70 -5
  11. data/lib/bitcoin/logger.rb +25 -1
  12. data/lib/bitcoin/message/addr.rb +0 -39
  13. data/lib/bitcoin/message/headers.rb +1 -0
  14. data/lib/bitcoin/message/inventory.rb +4 -0
  15. data/lib/bitcoin/message/network_addr.rb +44 -0
  16. data/lib/bitcoin/message/version.rb +8 -3
  17. data/lib/bitcoin/message.rb +12 -0
  18. data/lib/bitcoin/mnemonic.rb +2 -2
  19. data/lib/bitcoin/network/connection.rb +14 -1
  20. data/lib/bitcoin/network/message_handler.rb +52 -19
  21. data/lib/bitcoin/network/peer.rb +142 -5
  22. data/lib/bitcoin/network/peer_discovery.rb +16 -8
  23. data/lib/bitcoin/network/pool.rb +39 -14
  24. data/lib/bitcoin/network.rb +0 -1
  25. data/lib/bitcoin/node/cli.rb +66 -0
  26. data/lib/bitcoin/node/configuration.rb +37 -0
  27. data/lib/bitcoin/node/spv.rb +13 -3
  28. data/lib/bitcoin/node.rb +2 -1
  29. data/lib/bitcoin/rpc/http_server.rb +56 -0
  30. data/lib/bitcoin/rpc/request_handler.rb +84 -0
  31. data/lib/bitcoin/rpc.rb +6 -0
  32. data/lib/bitcoin/script/multisig.rb +92 -0
  33. data/lib/bitcoin/script/script.rb +17 -7
  34. data/lib/bitcoin/script/script_interpreter.rb +2 -38
  35. data/lib/bitcoin/store/chain_entry.rb +64 -0
  36. data/lib/bitcoin/store/db/level_db.rb +101 -0
  37. data/lib/bitcoin/store/db.rb +9 -0
  38. data/lib/bitcoin/store/spv_chain.rb +96 -0
  39. data/lib/bitcoin/store.rb +5 -1
  40. data/lib/bitcoin/tx.rb +6 -2
  41. data/lib/bitcoin/version.rb +1 -1
  42. data/lib/bitcoin/wallet/account.rb +82 -0
  43. data/lib/bitcoin/wallet/base.rb +84 -0
  44. data/lib/bitcoin/wallet/db.rb +57 -0
  45. data/lib/bitcoin/wallet/master_key.rb +100 -0
  46. data/lib/bitcoin/wallet.rb +8 -0
  47. data/lib/bitcoin.rb +4 -0
  48. data/lib/openassets/payload.rb +6 -2
  49. metadata +70 -13
  50. data/lib/bitcoin/node/spv_block_chain.rb +0 -15
  51. data/lib/bitcoin/store/spv_block_store.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bad0d642595251361c1e4f281ebe2bb7c08093cd
4
- data.tar.gz: 8a6ce86fdb345abb9fe19b2fb37d80402a92958e
3
+ metadata.gz: 8f25b7f5ff1de3882b880e49e858f3b49bf8c13a
4
+ data.tar.gz: 2a04f3a090503ffdc15d337b351c839d68b33929
5
5
  SHA512:
6
- metadata.gz: f57859bf2c0080092422681fcc9e7f66c6a4605ae4b00dcef291b4f13126264da9bf6c23424aec2450be5f5819364d74e9765159d77b6d9b74de30ddeeb000fd
7
- data.tar.gz: e7682dfea261c6456dc5f9e5c969836d338d5045a445b2141a63d97c9117cfea537b62683fe87dd7baae82e94c98dd5109b617db51933aa3656434c264ec1164
6
+ metadata.gz: abbfff02611cb216dc843414bc7e8e9f4e9799a72314ebc3f165f6b100fa2e2d77843975b77bca8ccce3d23d7fb749eb12c62f881ac7f3635840bb68eedb9791
7
+ data.tar.gz: a0a3fd06f7120bdff5c04375e1ab4214d3e962256d96f4c5f9a48811eeb5227ad602bd7ff2283c117219d3bb4d880dd529a9b0fde1567cc2ef03d2a9b2106cfd
data/.travis.yml CHANGED
@@ -2,3 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 2.3.0
4
4
  - 2.4.1
5
+ addons:
6
+ apt:
7
+ packages:
8
+ - libleveldb-dev
data/README.md CHANGED
@@ -1,8 +1,35 @@
1
- # Bitcoinrb
1
+ # Bitcoinrb [![Build Status](https://travis-ci.org/haw-itn/bitcoinrb.svg?branch=master)](https://travis-ci.org/haw-itn/bitcoinrb) [![Gem Version](https://badge.fury.io/rb/bitcoinrb.svg)](https://badge.fury.io/rb/bitcoinrb) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) <img src="http://segwit.co/static/public/images/logo.png" width="100">
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bitcoinrb`. To experiment with that code, run `bin/console` for an interactive prompt.
4
3
 
5
- TODO: Delete this and the text above, and describe your gem
4
+ Bitcoinrb is a Ruby implementation of Bitcoin Protocol.
5
+
6
+ NOTE: Bitcoinrb work in progress, and there is a possibility of incompatible change.
7
+
8
+ ## Features
9
+
10
+ Bitcoinrb supports following feature:
11
+
12
+ * Bitcoin script interpreter
13
+ * De/serialization of Bitcoin protocol network messages
14
+ * De/serialization of blocks and transactions
15
+ * Key generation and verification for ECDSA, including [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) supports.
16
+ * Segwit support (parsing segwit payload, Bech32 address, sign for segwit tx, etc..)
17
+ * [WIP] SPV node
18
+ * [WIP] 0ff-chain protocol
19
+
20
+ ## Requirements
21
+
22
+ bitcoinrb requires a `leveldb` library.
23
+
24
+ ### install LevelDB
25
+
26
+ * for Ubuntu
27
+
28
+ $ sudo apt-get install libleveldb-dev
29
+
30
+ + for Mac
31
+
32
+ $ brew install leveldb
6
33
 
7
34
  ## Installation
8
35
 
@@ -20,16 +47,11 @@ Or install it yourself as:
20
47
 
21
48
  $ gem install bitcoinrb
22
49
 
50
+
23
51
  ## Usage
24
52
 
25
53
  TODO: Write usage instructions here
26
54
 
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
55
  ## Contributing
34
56
 
35
57
  Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bitcoinrb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
File without changes
data/bitcoinrb.gemspec CHANGED
@@ -4,6 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'bitcoin/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
+
7
8
  spec.name = "bitcoinrb"
8
9
  spec.version = Bitcoin::VERSION
9
10
  spec.authors = ["azuchi"]
@@ -22,12 +23,15 @@ Gem::Specification.new do |spec|
22
23
  spec.add_runtime_dependency 'ecdsa'
23
24
  spec.add_runtime_dependency 'eventmachine'
24
25
  spec.add_runtime_dependency 'murmurhash3'
25
- spec.add_runtime_dependency 'bech32', '~> 1.0.1'
26
+ spec.add_runtime_dependency 'bech32', '~> 1.0.3'
26
27
  spec.add_runtime_dependency 'daemon-spawn'
27
28
  spec.add_runtime_dependency 'thor'
28
29
  spec.add_runtime_dependency 'ffi'
29
- spec.add_runtime_dependency 'parallel'
30
30
  spec.add_runtime_dependency 'leb128', '~> 1.0.0'
31
+ spec.add_runtime_dependency 'leveldb-ruby'
32
+ spec.add_runtime_dependency 'eventmachine_httpserver'
33
+ spec.add_runtime_dependency 'rest-client'
34
+ spec.add_runtime_dependency 'iniparse'
31
35
 
32
36
  spec.add_development_dependency 'bundler', '~> 1.11'
33
37
  spec.add_development_dependency 'rake', '~> 10.0'
data/exe/bitcoinrb-cli CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bitcoin/node/spv/cli'
3
+ require 'bitcoin'
4
4
 
5
- Bitcoin::Nodes::SPV::CLI.start(ARGV)
5
+ Bitcoin::Node::CLI.start(ARGV)
@@ -3,7 +3,6 @@ module Bitcoin
3
3
  # Block Header
4
4
  class BlockHeader
5
5
 
6
- attr_accessor :hash
7
6
  attr_accessor :version
8
7
  attr_accessor :prev_hash
9
8
  attr_accessor :merkle_root
@@ -18,7 +17,6 @@ module Bitcoin
18
17
  @time = time
19
18
  @bits = bits
20
19
  @nonce = nonce
21
- @hash = calc_hash
22
20
  end
23
21
 
24
22
  def self.parse_from_payload(payload)
@@ -38,6 +36,11 @@ module Bitcoin
38
36
  (mantissa * 2 ** (8 * (exponent - 3)))
39
37
  end
40
38
 
39
+ # block hash
40
+ def hash
41
+ calc_hash
42
+ end
43
+
41
44
  # evaluate block header
42
45
  def valid?
43
46
  valid_pow? && valid_timestamp?
@@ -62,6 +65,10 @@ module Bitcoin
62
65
  (2**256) / (target + 1)
63
66
  end
64
67
 
68
+ def ==(other)
69
+ other && other.to_payload == to_payload
70
+ end
71
+
65
72
  private
66
73
 
67
74
  def calc_hash
@@ -4,7 +4,7 @@ magic_head: "fabfb5da"
4
4
  message_magic: "Bitcoin Signed Message:\n"
5
5
  address_version: "6f"
6
6
  p2sh_version: "c4"
7
- bech32_hrp: 'tb'
7
+ bech32_hrp: 'bcrt'
8
8
  privkey_version: "ef"
9
9
  extended_privkey_version: "04358394"
10
10
  extended_pubkey_version: "043587cf"
@@ -167,4 +167,7 @@ module Bitcoin
167
167
 
168
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
169
  MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60
170
+
171
+ # Size of set to pick median time from.
172
+ MEDIAN_TIME_SPAN = 11
170
173
  end
data/lib/bitcoin/key.rb CHANGED
@@ -8,9 +8,16 @@ module Bitcoin
8
8
  attr_accessor :compressed
9
9
  attr_reader :secp256k1_module
10
10
 
11
+ MIN_PRIV_KEy_MOD_ORDER = 0x01
12
+ # Order of secp256k1's generator minus 1.
13
+ MAX_PRIV_KEY_MOD_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140
14
+
11
15
  def initialize(priv_key: nil, pubkey: nil, compressed: true)
12
16
  @secp256k1_module = Bitcoin.secp_impl
13
17
  @priv_key = priv_key
18
+ if @priv_key
19
+ raise ArgumentError, 'private key is not on curve' unless validate_private_key_range(@priv_key)
20
+ end
14
21
  if pubkey
15
22
  @pubkey = pubkey
16
23
  else
@@ -28,12 +35,23 @@ module Bitcoin
28
35
  # import private key from wif format
29
36
  # https://en.bitcoin.it/wiki/Wallet_import_format
30
37
  def self.from_wif(wif)
31
- compressed = wif.size == 52
32
38
  hex = Base58.decode(wif)
33
- version, key, flag, checksum = hex.unpack("a2a64a#{compressed ? 2 : 0}a8")
39
+ raise ArgumentError, 'data is too short' if hex.htb.bytesize < 4
40
+ version = hex[0..1]
41
+ data = hex[2...-8].htb
42
+ checksum = hex[-8..-1]
34
43
  raise ArgumentError, 'invalid version' unless version == Bitcoin.chain_params.privkey_version
35
- raise ArgumentError, 'invalid checksum' unless Bitcoin.calc_checksum(version + key + flag) == checksum
36
- new(priv_key: key, compressed: compressed)
44
+ raise ArgumentError, 'invalid checksum' unless Bitcoin.calc_checksum(version + data.bth) == checksum
45
+ key_len = data.bytesize
46
+ if key_len == 33 && data[-1].unpack('C').first == 1
47
+ compressed = true
48
+ data = data[0..-2]
49
+ elsif key_len == 32
50
+ compressed = false
51
+ else
52
+ raise ArgumentError, 'Wrong number of bytes for a private key, not 32 or 33'
53
+ end
54
+ new(priv_key: data.bth, compressed: compressed)
37
55
  end
38
56
 
39
57
  # export private key with wif format
@@ -47,7 +65,12 @@ module Bitcoin
47
65
 
48
66
  # sign +data+ with private key
49
67
  def sign(data)
50
- secp256k1_module.sign_data(data, priv_key)
68
+ sig = nil
69
+ until sig
70
+ signature = secp256k1_module.sign_data(data, priv_key)
71
+ sig = signature if Key.low_signature?(signature)
72
+ end
73
+ sig
51
74
  end
52
75
 
53
76
  # verify signature using public key
@@ -116,6 +139,42 @@ module Bitcoin
116
139
  compare_big_endian(val_s, max_mod_half_order) <= 0
117
140
  end
118
141
 
142
+
143
+ # check +sig+ is correct der encoding.
144
+ # This function is consensus-critical since BIP66.
145
+ def self.valid_signature_encoding?(sig)
146
+ return false if sig.bytesize < 9 || sig.bytesize > 73 # Minimum and maximum size check
147
+
148
+ s = sig.unpack('C*')
149
+
150
+ return false if s[0] != 0x30 || s[1] != s.size - 3 # A signature is of type 0x30 (compound). Make sure the length covers the entire signature.
151
+
152
+ len_r = s[3]
153
+ return false if 5 + len_r >= s.size # Make sure the length of the S element is still inside the signature.
154
+
155
+ len_s = s[5 + len_r]
156
+ return false unless len_r + len_s + 7 == s.size #Verify that the length of the signature matches the sum of the length of the elements.
157
+
158
+ return false unless s[2] == 0x02 # Check whether the R element is an integer.
159
+
160
+ return false if len_r == 0 # Zero-length integers are not allowed for R.
161
+
162
+ return false unless s[4] & 0x80 == 0 # Negative numbers are not allowed for R.
163
+
164
+ # Null bytes at the start of R are not allowed, unless R would otherwise be interpreted as a negative number.
165
+ return false if len_r > 1 && (s[4] == 0x00) && (s[5] & 0x80 == 0)
166
+
167
+ return false unless s[len_r + 4] == 0x02 # Check whether the S element is an integer.
168
+
169
+ return false if len_s == 0 # Zero-length integers are not allowed for S.
170
+ return false unless (s[len_r + 6] & 0x80) == 0 # Negative numbers are not allowed for S.
171
+
172
+ # Null bytes at the start of S are not allowed, unless S would otherwise be interpreted as a negative number.
173
+ return false if len_s > 1 && (s[len_r + 6] == 0x00) && (s[len_r + 7] & 0x80 == 0)
174
+
175
+ true
176
+ end
177
+
119
178
  private
120
179
 
121
180
  def self.compare_big_endian(c1, c2)
@@ -144,6 +203,12 @@ module Bitcoin
144
203
  pubkey.bth
145
204
  end
146
205
 
206
+ # check private key range.
207
+ def validate_private_key_range(private_key)
208
+ value = private_key.to_i(16)
209
+ MIN_PRIV_KEy_MOD_ORDER <= value && value <= MAX_PRIV_KEY_MOD_ORDER
210
+ end
211
+
147
212
  end
148
213
 
149
214
  end
@@ -5,14 +5,38 @@ module Bitcoin
5
5
  # Simple Logger module
6
6
  module Logger
7
7
 
8
+ Format = "%s, [%s#%d #%d] %5s -- %s: %s\n".freeze
9
+
10
+ module_function
11
+
8
12
  # Create a logger with given +name+.log in $HOME/.bitcoinrb/log.
9
- def self.create(name, level = ::Logger::INFO)
13
+ def create(name, level = ::Logger::INFO)
10
14
  dir = "#{Bitcoin.base_dir}/log"
11
15
  FileUtils.mkdir_p(dir)
12
16
  logger = ::Logger.new(dir + "/#{name}.log", 10)
13
17
  logger.level = level
18
+ logger.formatter = proc do |severity, datetime, progname, msg|
19
+ Format % [severity[0..0], format_datetime(datetime), $$,
20
+ Thread.current.object_id, severity, progname, msg2str(msg)]
21
+ end
14
22
  logger
15
23
  end
16
24
 
25
+ def self.msg2str(msg)
26
+ case msg
27
+ when ::String
28
+ msg
29
+ when ::Exception
30
+ "#{ msg.message } (#{ msg.class })\n" <<
31
+ (msg.backtrace || []).join("\n")
32
+ else
33
+ msg.inspect
34
+ end
35
+ end
36
+
37
+ def format_datetime(time)
38
+ time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
39
+ end
40
+
17
41
  end
18
42
  end
@@ -31,44 +31,5 @@ module Bitcoin
31
31
 
32
32
  end
33
33
 
34
- class NetworkAddr
35
-
36
- # unix time.
37
- # Nodes advertising their own IP address set this to the current time.
38
- # Nodes advertising IP addresses they’ve connected to set this to the last time they connected to that node.
39
- # Other nodes just relaying the IP address should not change the time. Nodes can use the time field to avoid relaying old addr messages.
40
- attr_accessor :time
41
-
42
- # The services the node advertised in its version message.
43
- attr_accessor :services
44
-
45
- attr_accessor :ip
46
-
47
- attr_accessor :port
48
-
49
- def initialize
50
- @time = Time.now.to_i
51
- @services = Bitcoin::Message::SERVICE_FLAGS[:network]
52
- end
53
-
54
- def self.parse_from_payload(payload)
55
- buf = payload.is_a?(String) ? StringIO.new(payload) : payload
56
- addr = new
57
- addr.time = buf.read(4).unpack('V').first
58
- addr.services = buf.read(8).unpack('Q').first
59
- ip = IPAddr::new_ntoh(buf.read(16))
60
- addr.ip = ip.ipv4_mapped? ? ip.native : ip.to_s
61
- addr.port = buf.read(2).unpack('n').first
62
- addr
63
- end
64
-
65
- def to_payload
66
- ip_addr = IPAddr.new (ip)
67
- ip_addr = ip_addr.ipv4_mapped if ip_addr.ipv4?
68
- [time, services].pack('VQ') << ip_addr.hton << [port].pack('n')
69
- end
70
-
71
- end
72
-
73
34
  end
74
35
  end
@@ -7,6 +7,7 @@ module Bitcoin
7
7
 
8
8
  COMMAND = 'headers'
9
9
 
10
+ # Array[Bitcoin::BlockHeader]
10
11
  attr_accessor :headers
11
12
 
12
13
  def initialize(headers = [])
@@ -35,6 +35,10 @@ module Bitcoin
35
35
  [identifier].pack('V') << hash.htb.reverse
36
36
  end
37
37
 
38
+ def block?
39
+ [MSG_BLOCK, MSG_WITNESS_BLOCK, MSG_FILTERED_WITNESS_BLOCK].include?(identifier)
40
+ end
41
+
38
42
  private
39
43
 
40
44
  def valid_identifier?(identifier)
@@ -0,0 +1,44 @@
1
+ module Bitcoin
2
+ module Message
3
+
4
+ class NetworkAddr
5
+
6
+ # unix time.
7
+ # Nodes advertising their own IP address set this to the current time.
8
+ # Nodes advertising IP addresses they’ve connected to set this to the last time they connected to that node.
9
+ # Other nodes just relaying the IP address should not change the time. Nodes can use the time field to avoid relaying old addr messages.
10
+ attr_accessor :time
11
+
12
+ # The services the node advertised in its version message.
13
+ attr_accessor :services
14
+
15
+ attr_accessor :ip
16
+
17
+ attr_accessor :port
18
+
19
+ def initialize
20
+ @time = Time.now.to_i
21
+ @services = Bitcoin::Message::SERVICE_FLAGS[:network]
22
+ end
23
+
24
+ def self.parse_from_payload(payload)
25
+ buf = payload.is_a?(String) ? StringIO.new(payload) : payload
26
+ addr = new
27
+ addr.time = buf.read(4).unpack('V').first
28
+ addr.services = buf.read(8).unpack('Q').first
29
+ ip = IPAddr::new_ntoh(buf.read(16))
30
+ addr.ip = ip.ipv4_mapped? ? ip.native : ip.to_s
31
+ addr.port = buf.read(2).unpack('n').first
32
+ addr
33
+ end
34
+
35
+ def to_payload
36
+ ip_addr = IPAddr.new (ip)
37
+ ip_addr = ip_addr.ipv4_mapped if ip_addr.ipv4?
38
+ [time, services].pack('VQ') << ip_addr.hton << [port].pack('n')
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -1,4 +1,5 @@
1
1
  # encoding: ascii-8bit
2
+ require 'ipaddr'
2
3
  module Bitcoin
3
4
  module Message
4
5
 
@@ -60,9 +61,13 @@ module Bitcoin
60
61
  end
61
62
 
62
63
  def pack_addr(addr)
63
- host, port = addr.split(':')
64
- sockaddr = Socket.pack_sockaddr_in(port.to_i, host)
65
- [[1].pack('Q'), "\x00" * 10, "\xFF\xFF", sockaddr[4...8], sockaddr[2...4]].join
64
+ separator = addr.rindex(':')
65
+ ip = addr[0...separator]
66
+ port = addr[separator + 1..-1].to_i
67
+ ip_addr = IPAddr.new(ip)
68
+ ip_addr = ip_addr.ipv4_mapped if ip_addr.ipv4?
69
+ [1].pack('Q') << ip_addr.hton << [port].pack('n')
70
+ # [[1].pack('Q'), "\x00" * 10, "\xFF\xFF", sockaddr[4...8], sockaddr[2...4]].join
66
71
  end
67
72
 
68
73
  def unpack_addr(addr)
@@ -8,6 +8,7 @@ module Bitcoin
8
8
  autoload :Version, 'bitcoin/message/version'
9
9
  autoload :VerAck, 'bitcoin/message/ver_ack'
10
10
  autoload :Addr, 'bitcoin/message/addr'
11
+ autoload :NetworkAddr, 'bitcoin/message/network_addr'
11
12
  autoload :Block, 'bitcoin/message/block'
12
13
  autoload :FilterLoad, 'bitcoin/message/filter_load'
13
14
  autoload :FilterAdd, 'bitcoin/message/filter_add'
@@ -47,5 +48,16 @@ module Bitcoin
47
48
 
48
49
  DEFAULT_STOP_HASH = "00"*32
49
50
 
51
+ # the protocol version.
52
+ VERSION = {
53
+ headers: 31800,
54
+ pong: 60001,
55
+ bloom: 70011,
56
+ send_headers: 70012,
57
+ fee_filter: 70013,
58
+ compact: 70014,
59
+ compact_witness: 70015
60
+ }
61
+
50
62
  end
51
63
  end
@@ -24,7 +24,7 @@ module Bitcoin
24
24
  def to_entropy(words)
25
25
  word_master = load_words
26
26
  mnemonic = words.map do |w|
27
- index = word_master.index(w)
27
+ index = word_master.index(w.downcase)
28
28
  raise IndexError, 'word not found in words list.' unless index
29
29
  index.to_s(2).rjust(11, '0')
30
30
  end.join
@@ -52,7 +52,7 @@ module Bitcoin
52
52
  # @param [String] passphrase a passphrase which protects mnemonic. the default value is an empty string.
53
53
  # @return [String] seed
54
54
  def to_seed(mnemonic, passphrase: '')
55
- OpenSSL::PKCS5.pbkdf2_hmac(mnemonic.join(' '),
55
+ OpenSSL::PKCS5.pbkdf2_hmac(mnemonic.join(' ').downcase,
56
56
  'mnemonic' + passphrase, 2048, 64, OpenSSL::Digest::SHA512.new).bth
57
57
  end
58
58
 
@@ -20,7 +20,7 @@ module Bitcoin
20
20
 
21
21
  def initialize(peer)
22
22
  @peer = peer
23
- @logger = Bitcoin::Logger.create(:debug)
23
+ @logger = peer.logger
24
24
  @sendheaders = false
25
25
  @attr_accessor = 0
26
26
  @message = ''
@@ -28,6 +28,7 @@ module Bitcoin
28
28
 
29
29
  def post_init
30
30
  logger.info "connected. #{addr}"
31
+ peer.conn_time = Time.now.to_i
31
32
  begin_handshake
32
33
  end
33
34
 
@@ -51,6 +52,18 @@ module Bitcoin
51
52
  EM.stop
52
53
  end
53
54
 
55
+ def handle_error(e)
56
+ peer.handle_error(e)
57
+ end
58
+
59
+ private
60
+
61
+ # start handshake
62
+ def begin_handshake
63
+ logger.info "begin handshake with #{addr}"
64
+ send_message(peer.local_version)
65
+ end
66
+
54
67
  end
55
68
 
56
69
  end