bitcoinrb 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 524753cfa61041f101f72d76e914f70b20b504fb0eecad9d378a436afe7db718
4
- data.tar.gz: f3181a60120da9f892ceaaaaf22aba5923b26f495fb9fb9dd314c5cce8127129
3
+ metadata.gz: f552597dfd50a5df7cee6e6c29c10789afbbe5e78ad316af9833f25e99f15e76
4
+ data.tar.gz: 9044c1daafb7c4badee574cdd326a922354b64376b9b871da3b2f5ad6a8aa4e6
5
5
  SHA512:
6
- metadata.gz: da27669ddabc4d64bf3c96d4e83eb8c5d90ef837ed91b6f2e1d0e7d50c74153c62ff39eecb1867463f5a8435f7643d62ba6108e7a10d1fa46e4b10178fe8e2f1
7
- data.tar.gz: 2f85e04fecddba5bb1d1ce4fc61bf79fd972280f4834e56a4b56974958903e74bd1d19789c93d6bdebe8bead9b5fca8ad26d4c35967760cf0517da42ebfeb35d
6
+ metadata.gz: '09d270868f51f4a08af65dbedce68d87d1863bb8f82dbf32c8999eb40bad432910325d5d17efc7c8d23f2f0398614cca8d4852dd3a52bd232ab0576bb0e7ee61'
7
+ data.tar.gz: 0b958912e698973c4e1b4af4f9737a046b3d07566064bdd759ec7fa4c336a33861ec060a90f7bc9181c5a8a7f6fe91240359232ee0cefbcfc799580f59e861e5
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.0
1
+ 2.5.3
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.0
4
- - 2.4.1
5
- - 2.5.0
3
+ - 2.3.8
4
+ - 2.4.5
5
+ - 2.5.3
6
6
  addons:
7
7
  apt:
8
8
  packages:
data/README.md CHANGED
@@ -1,4 +1,4 @@
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">
1
+ # Bitcoinrb [![Build Status](https://travis-ci.org/chaintope/bitcoinrb.svg?branch=master)](https://travis-ci.org/chaintope/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
3
 
4
4
  Bitcoinrb is a Ruby implementation of Bitcoin Protocol.
@@ -68,7 +68,7 @@ The parameters of the blockchain are managed by `Bitcoin::ChainParams`. Switch c
68
68
  Bitcoin.chain_params = :mainnet
69
69
  ```
70
70
 
71
- This parameter is described in https://github.com/haw-itn/bitcoinrb/blob/master/lib/bitcoin/chainparams/mainnet.yml.
71
+ This parameter is described in https://github.com/chaintope/bitcoinrb/blob/master/lib/bitcoin/chainparams/mainnet.yml.
72
72
 
73
73
  * testnet
74
74
 
@@ -76,7 +76,7 @@ This parameter is described in https://github.com/haw-itn/bitcoinrb/blob/master/
76
76
  Bitcoin.chain_params = :testnet
77
77
  ```
78
78
 
79
- This parameter is described in https://github.com/haw-itn/bitcoinrb/blob/master/lib/bitcoin/chainparams/testnet.yml.
79
+ This parameter is described in https://github.com/chaintope/bitcoinrb/blob/master/lib/bitcoin/chainparams/testnet.yml.
80
80
 
81
81
  * regtest
82
82
 
@@ -84,20 +84,7 @@ This parameter is described in https://github.com/haw-itn/bitcoinrb/blob/master/
84
84
  Bitcoin.chain_params = :regtest
85
85
  ```
86
86
 
87
- This parameter is described in https://github.com/haw-itn/bitcoinrb/blob/master/lib/bitcoin/chainparams/regtest.yml.
88
-
89
- #### Fork coin
90
-
91
- When using with fork coin, please specify the fork_id of the coin as follows.
92
-
93
- ```ruby
94
- Bitcoin.chain_params.fork_id = 0 # 0 is bch fork id
95
- ```
96
-
97
- Currently bitcoinrb supports only support and verification of transaction replay protection using `SIGHASH_FORK_ID`.
98
- For details of `SIGHASH_FORK_ID`, refer to the following.
99
-
100
- https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md
87
+ This parameter is described in https://github.com/chaintope/bitcoinrb/blob/master/lib/bitcoin/chainparams/regtest.yml.
101
88
 
102
89
  ## Contributing
103
90
 
data/bitcoinrb.gemspec CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |spec|
8
8
  spec.name = "bitcoinrb"
9
9
  spec.version = Bitcoin::VERSION
10
10
  spec.authors = ["azuchi"]
11
- spec.email = ["azuchi@haw.co.jp"]
11
+ spec.email = ["azuchi@chaintope.com"]
12
12
 
13
13
  spec.summary = %q{[WIP]The implementation of Bitcoin Protocol for Ruby.}
14
14
  spec.description = %q{[WIP]The implementation of Bitcoin Protocol for Ruby.}
15
- spec.homepage = 'https://github.com/haw-itn/bitcoinrb'
15
+ spec.homepage = 'https://github.com/chaintope/bitcoinrb'
16
16
  spec.license = "MIT"
17
17
 
18
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_runtime_dependency 'iniparse'
34
34
  spec.add_runtime_dependency 'siphash'
35
35
  spec.add_runtime_dependency 'protobuf'
36
+ spec.add_runtime_dependency 'scrypt'
36
37
 
37
38
  # for options
38
39
  spec.add_development_dependency 'leveldb-ruby'
data/lib/bitcoin/key.rb CHANGED
@@ -87,9 +87,20 @@ module Bitcoin
87
87
 
88
88
  # sign +data+ with private key
89
89
  # @param [String] data a data to be signed with binary format
90
+ # @param [Boolean] low_r flag to apply low-R.
91
+ # @param [String] extra_entropy the extra entropy for rfc6979.
90
92
  # @return [String] signature data with binary format
91
- def sign(data)
92
- secp256k1_module.sign_data(data, priv_key)
93
+ def sign(data, low_r = true, extra_entropy = nil)
94
+ sig = secp256k1_module.sign_data(data, priv_key, extra_entropy)
95
+ if low_r && !sig_has_low_r?(sig)
96
+ counter = 1
97
+ until sig_has_low_r?(sig)
98
+ extra_entropy = [counter].pack('I*').bth.ljust(64, '0').htb
99
+ sig = secp256k1_module.sign_data(data, priv_key, extra_entropy)
100
+ counter += 1
101
+ end
102
+ end
103
+ sig
93
104
  end
94
105
 
95
106
  # verify signature using public key
@@ -242,8 +253,7 @@ module Bitcoin
242
253
  # @param [Boolean] compressed pubkey compressed?
243
254
  # @return [String] a pubkey which generate from privkey
244
255
  def generate_pubkey(privkey, compressed: true)
245
- private_key = ECDSA::Format::IntegerOctetString.decode(privkey.htb)
246
- public_key = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(private_key)
256
+ public_key = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(privkey.to_i(16))
247
257
  pubkey = ECDSA::Format::PointOctetString.encode(public_key, compression: compressed)
248
258
  pubkey.bth
249
259
  end
@@ -272,6 +282,13 @@ module Bitcoin
272
282
  !pubkey.nil? && pubkey.size > 0
273
283
  end
274
284
 
285
+ # check whether the signature is low-R
286
+ # @param [String] sig the signature data
287
+ # @return [Boolean] result
288
+ def sig_has_low_r?(sig)
289
+ sig[3].bth.to_i(16) == 0x20 && sig[4].bth.to_i(16) < 0x80
290
+ end
291
+
275
292
  end
276
293
 
277
294
  end
@@ -4,23 +4,15 @@ module Bitcoin
4
4
  # notfound message
5
5
  # https://bitcoin.org/en/developer-reference#notfound
6
6
  class NotFound < Base
7
+ include InventoriesParser
8
+ extend InventoriesParser
7
9
 
8
- attr_accessor :inventory
10
+ attr_reader :inventories
9
11
 
10
12
  COMMAND = 'notfound'
11
13
 
12
- def initialize(identifier, hash)
13
- @inventory = Inventory.new(identifier, hash)
14
- end
15
-
16
- def self.parse_from_payload(payload)
17
- size, inventory_payload = Bitcoin.unpack_var_int(payload)
18
- inventory = Inventory.parse_from_payload(inventory_payload)
19
- new(inventory.identifier, inventory.hash)
20
- end
21
-
22
- def to_payload
23
- Bitcoin.pack_var_int(1) << inventory.to_payload
14
+ def initialize(inventories = [])
15
+ @inventories = inventories
24
16
  end
25
17
 
26
18
  end
@@ -21,6 +21,7 @@ module Bitcoin
21
21
  attr_reader :logger
22
22
  attr_reader :peer_discovery
23
23
  attr_accessor :started
24
+ attr_reader :mutex
24
25
 
25
26
  def initialize(node, chain, configuration)
26
27
  @node = node
@@ -32,6 +33,7 @@ module Bitcoin
32
33
  @configuration = configuration
33
34
  @peer_discovery = PeerDiscovery.new(configuration)
34
35
  @started = false
36
+ @mutex = Mutex.new
35
37
  end
36
38
 
37
39
  # connecting other peers and begin network activity.
@@ -48,12 +50,14 @@ module Bitcoin
48
50
  # detect new peer connection.
49
51
  def handle_new_peer(peer)
50
52
  logger.debug "connected new peer #{peer.addr}."
51
- peer.id = allocate_peer_id
52
- unless peers.find(&:primary?)
53
- peer.primary = true
54
- peer.start_block_header_download
53
+ mutex.synchronize do
54
+ peer.id = allocate_peer_id
55
+ unless peers.find(&:primary?)
56
+ peer.primary = true
57
+ peer.start_block_header_download
58
+ end
59
+ peers << peer
55
60
  end
56
- peers << peer
57
61
  pending_peers.delete(peer)
58
62
  filter_load(peer) if node.wallet
59
63
  end
@@ -107,20 +107,23 @@ module Bitcoin
107
107
  # sign data.
108
108
  # @param [String] data a data to be signed with binary format
109
109
  # @param [String] privkey a private key using sign
110
+ # @param [String] extra_entropy a extra entropy for rfc6979
110
111
  # @return [String] signature data with binary format
111
- def sign_data(data, privkey)
112
+ def sign_data(data, privkey, extra_entropy)
112
113
  with_context do |context|
113
114
  secret = FFI::MemoryPointer.new(:uchar, privkey.htb.bytesize).put_bytes(0, privkey.htb)
114
115
  raise 'priv_key invalid' unless secp256k1_ec_seckey_verify(context, secret)
115
116
 
116
117
  internal_signature = FFI::MemoryPointer.new(:uchar, 64)
117
118
  msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
119
+ entropy = extra_entropy ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, extra_entropy) : nil
118
120
 
119
121
  ret, tries, max = 0, 0, 20
122
+
120
123
  while ret != 1
121
124
  raise 'secp256k1_ecdsa_sign failed.' if tries >= max
122
125
  tries += 1
123
- ret = secp256k1_ecdsa_sign(context, internal_signature, msg32, secret, nil, nil)
126
+ ret = secp256k1_ecdsa_sign(context, internal_signature, msg32, secret, nil, entropy)
124
127
  end
125
128
 
126
129
  signature = FFI::MemoryPointer.new(:uchar, 72)
@@ -26,10 +26,11 @@ module Bitcoin
26
26
  # @param [String] data a data to be signed with binary format
27
27
  # @param [String] privkey a private key using sign
28
28
  # @return [String] signature data with binary format
29
- def sign_data(data, privkey)
29
+ def sign_data(data, privkey, extra_entropy)
30
30
  privkey = privkey.htb
31
31
  private_key = ECDSA::Format::IntegerOctetString.decode(privkey)
32
- nonce = generate_rfc6979_nonce(data, privkey)
32
+ extra_entropy ||= ''
33
+ nonce = generate_rfc6979_nonce(data, privkey, extra_entropy)
33
34
 
34
35
  # port form ecdsa gem.
35
36
  r_point = GROUP.new_point(nonce)
@@ -83,15 +84,15 @@ module Bitcoin
83
84
 
84
85
  # generate temporary key k to be used when ECDSA sign.
85
86
  # https://tools.ietf.org/html/rfc6979#section-3.2
86
- def generate_rfc6979_nonce(data, privkey)
87
- v = ('01' * 32).htb
88
- k = ('00' * 32).htb
87
+ def generate_rfc6979_nonce(data, privkey, extra_entropy)
88
+ v = ('01' * 32).htb # 3.2.b
89
+ k = ('00' * 32).htb # 3.2.c
89
90
  # 3.2.d
90
- k = Bitcoin.hmac_sha256(k, v + '00'.htb + privkey + data)
91
+ k = Bitcoin.hmac_sha256(k, v + '00'.htb + privkey + data + extra_entropy)
91
92
  # 3.2.e
92
93
  v = Bitcoin.hmac_sha256(k, v)
93
94
  # 3.2.f
94
- k = Bitcoin.hmac_sha256(k, v + '01'.htb + privkey + data)
95
+ k = Bitcoin.hmac_sha256(k, v + '01'.htb + privkey + data + extra_entropy)
95
96
  # 3.2.g
96
97
  v = Bitcoin.hmac_sha256(k, v)
97
98
  # 3.2.h
@@ -102,7 +103,7 @@ module Bitcoin
102
103
  t_num = t.bth.to_i(16)
103
104
  return t_num if 1 <= t_num && t_num < GROUP.order
104
105
  k = Bitcoin.hmac_sha256(k, v + '00'.htb)
105
- v = Bitcoin.hmac_sha256(v)
106
+ v = Bitcoin.hmac_sha256(k, v)
106
107
  end
107
108
  raise 'A valid nonce was not found.'
108
109
  end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.4"
3
3
  end
@@ -57,7 +57,7 @@ module Bitcoin
57
57
  def create_receive
58
58
  @receive_depth += 1
59
59
  save
60
- derive_key(0, @receive_depth)
60
+ save_key(0, @receive_depth, derive_key(0, @receive_depth))
61
61
  end
62
62
 
63
63
  # create new change key
@@ -65,12 +65,21 @@ module Bitcoin
65
65
  def create_change
66
66
  @change_depth += 1
67
67
  save
68
- derive_key(1, @change_depth)
68
+ save_key(1, @change_depth, derive_key(1, @change_depth))
69
69
  end
70
70
 
71
71
  # save this account payload to database.
72
72
  def save
73
73
  wallet.db.save_account(self)
74
+ save_key(0, receive_depth, derive_key(0, receive_depth)) if receive_depth.zero?
75
+ save_key(1, change_depth, derive_key(1, change_depth)) if change_depth.zero?
76
+ end
77
+
78
+ # @param purpose 0:recieve, 1:change
79
+ # @param index receive_depth or change_depth
80
+ # @param key the key to be saved
81
+ def save_key(purpose, index, key)
82
+ wallet.db.save_key(self, purpose, index, key)
74
83
  end
75
84
 
76
85
  # get the list of derived keys for receive key.
@@ -111,7 +120,7 @@ module Bitcoin
111
120
  # get data elements tobe monitored with Bloom Filter.
112
121
  # @return [Array[String]]
113
122
  def watch_targets
114
- derived_receive_keys.map(&:hash160) + derived_change_keys.map(&:hash160)
123
+ wallet.db.get_keys(self).map { |key| Bitcoin.hash160(key) }
115
124
  end
116
125
 
117
126
  def to_h
@@ -7,6 +7,7 @@ module Bitcoin
7
7
  account: 'a', # key: account index, value: Account raw data.
8
8
  master: 'm', # value: wallet seed.
9
9
  version: 'v', # value: wallet version
10
+ key: 'k', # key: path to the key, value: public key
10
11
  }
11
12
 
12
13
  attr_reader :level_db
@@ -37,6 +38,21 @@ module Bitcoin
37
38
  end
38
39
  end
39
40
 
41
+ def save_key(account, purpose, index, key)
42
+ pubkey = key.pub
43
+ id = [account.purpose, account.index, purpose, index].pack('I*').bth
44
+ k = KEY_PREFIX[:key] + id
45
+ level_db.put(k, pubkey)
46
+ key
47
+ end
48
+
49
+ def get_keys(account)
50
+ id = [account.purpose, account.index].pack('I*').bth
51
+ from = KEY_PREFIX[:key] + id + '00000000'
52
+ to = KEY_PREFIX[:key] + id + 'ffffffff'
53
+ level_db.each(from: from, to: to).map { |k, v| v}
54
+ end
55
+
40
56
  # get master_key
41
57
  def master_key
42
58
  @master_key ||= Bitcoin::Wallet::MasterKey.parse_from_payload(level_db.get(KEY_PREFIX[:master]))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitcoinrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-29 00:00:00.000000000 Z
11
+ date: 2018-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: scrypt
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: leveldb-ruby
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -264,7 +278,7 @@ dependencies:
264
278
  version: '0'
265
279
  description: "[WIP]The implementation of Bitcoin Protocol for Ruby."
266
280
  email:
267
- - azuchi@haw.co.jp
281
+ - azuchi@chaintope.com
268
282
  executables:
269
283
  - bitcoinrb-cli
270
284
  - bitcoinrbd
@@ -403,7 +417,7 @@ files:
403
417
  - lib/openassets/marker_output.rb
404
418
  - lib/openassets/payload.rb
405
419
  - lib/openassets/util.rb
406
- homepage: https://github.com/haw-itn/bitcoinrb
420
+ homepage: https://github.com/chaintope/bitcoinrb
407
421
  licenses:
408
422
  - MIT
409
423
  metadata: {}
@@ -423,7 +437,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
423
437
  version: '0'
424
438
  requirements: []
425
439
  rubyforge_project:
426
- rubygems_version: 2.7.3
440
+ rubygems_version: 2.7.8
427
441
  signing_key:
428
442
  specification_version: 4
429
443
  summary: "[WIP]The implementation of Bitcoin Protocol for Ruby."