btcruby 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d9eaa33fb43ddda93be8bb439718983f8595e41
4
- data.tar.gz: af06b8d5bcd07f02d8351e398c6b7a8595a8ddff
3
+ metadata.gz: 7296b8cbca8113b4795a800e581c220afdbe9b12
4
+ data.tar.gz: a318bf76d773d9f4bc4955e03bd70f0006bbaf1a
5
5
  SHA512:
6
- metadata.gz: 0f50ec59b1e00e03cf6d23de427ee7b3a50058be67f4931fb9db7b400eee94d54ad58fb8abc66f5337a0960d31efcd010abb276a7a779ef5496a7f489d3d7df4
7
- data.tar.gz: 444b559fcbf592eda67d82326510e2433810639b0530d55afdffdf241836d34396221c3fbdea1086c302c9063fe07b7dd2fa38412edcd4eeaf32d5289de8cba5
6
+ metadata.gz: ef71f62233c862f300abe91608cdc9f100a2ccdcc91f011436f543805fdceb0d8ff795240973a898edb1939c2ceceac43c00329430a0e78914bb97fe6ca5ae94
7
+ data.tar.gz: de2350b6b17e8c3de1f9e563916bdea830ed23fb0758e49ae1ea30de9d6ae4615fe786015860c1bf707f7a18e6c290eb52695ea77dc6bc63cf34ea546052fd3c
data/.gitignore CHANGED
@@ -16,3 +16,5 @@ DerivedData
16
16
  *.xcuserstate
17
17
  *.xcodeproj
18
18
  *.xcodeproj/
19
+ *.gem
20
+ .ruby-version
data/README.md CHANGED
@@ -52,6 +52,18 @@ $ bundle install
52
52
  $ rake
53
53
  ```
54
54
 
55
+ ## How to publish a gem
56
+
57
+ 1. Edit version.rb to bump the version.
58
+ 2. Update `RELEASE_NOTES.md`.
59
+ 3. Commit changes and tag it with new version.
60
+ 4. Generate and publish the gem:
61
+
62
+ ```
63
+ $ gem build btcruby
64
+ $ gem push btcruby-<version>.gem
65
+ ```
66
+
55
67
  ## Authors
56
68
 
57
69
  * [Oleg Andreev](http://oleganza.com/)
data/RELEASE_NOTES.md CHANGED
@@ -2,6 +2,11 @@
2
2
  BTCRuby Release Notes
3
3
  =====================
4
4
 
5
+ 1.0.5 (July 8, 2015)
6
+ --------------------
7
+
8
+ * Added MerkleTree API.
9
+
5
10
  1.0.4 (July 2, 2015)
6
11
  --------------------
7
12
 
@@ -213,7 +213,7 @@ module BTC
213
213
  end
214
214
 
215
215
  def data_for_base58check_encoding
216
- BTC::Data.data_from_bytes([self.version]) + @data
216
+ BTC.data_from_bytes([self.version].flatten) + @data
217
217
  end
218
218
  end
219
219
 
@@ -51,8 +51,6 @@ module BTC
51
51
  # The number of blocks that have been processed since the previous block (including the block itself).
52
52
  attr_accessor :confirmations
53
53
 
54
- attr_accessor :my_name
55
-
56
54
  def self.genesis_mainnet
57
55
  self.new(
58
56
  version: 1,
@@ -0,0 +1,91 @@
1
+ module BTC
2
+ class MerkleTree
3
+
4
+ attr_reader :merkle_root
5
+
6
+ def initialize(hashes: nil, transactions: nil, items: nil)
7
+ raise ArgumentError, "None of the arguments are used" if !transactions && !hashes && !items
8
+ if transactions
9
+ hashes = transactions.map{|tx| tx.transaction_hash}
10
+ elsif items
11
+ hashes = items.map{|item| BTC.hash256(item) }
12
+ end
13
+ raise ArgumentError, "Empty list is not allowed" if hashes.size == 0
14
+ @hashes = hashes
15
+ end
16
+
17
+ def merkle_root
18
+ @merkle_root ||= compute_merkle_root
19
+ end
20
+
21
+ def tail_duplicates?
22
+ if !@merkle_root
23
+ @merkle_root = compute_merkle_root
24
+ end
25
+ @tail_duplicates
26
+ end
27
+
28
+ private
29
+
30
+ def compute_merkle_root
31
+ # Based on original Satoshi implementation + vulnerability detection API:
32
+ # WARNING! If you're reading this because you're learning about crypto
33
+ # and/or designing a new system that will use merkle trees, keep in mind
34
+ # that the following merkle tree algorithm has a serious flaw related to
35
+ # duplicate txids, resulting in a vulnerability (CVE-2012-2459).
36
+ #
37
+ # The reason is that if the number of hashes in the list at a given time
38
+ # is odd, the last one is duplicated before computing the next level (which
39
+ # is unusual in Merkle trees). This results in certain sequences of
40
+ # transactions leading to the same merkle root. For example, these two
41
+ # trees:
42
+ #
43
+ # A A
44
+ # / \ / \
45
+ # B C B C
46
+ # / \ | / \ / \
47
+ # D E F D E F F
48
+ # / \ / \ / \ / \ / \ / \ / \
49
+ # 1 2 3 4 5 6 1 2 3 4 5 6 5 6
50
+ #
51
+ # for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
52
+ # 6 are repeated) result in the same root hash A (because the hash of both
53
+ # of (F) and (F,F) is C).
54
+ #
55
+ # The vulnerability results from being able to send a block with such a
56
+ # transaction list, with the same merkle root, and the same block hash as
57
+ # the original without duplication, resulting in failed validation. If the
58
+ # receiving node proceeds to mark that block as permanently invalid
59
+ # however, it will fail to accept further unmodified (and thus potentially
60
+ # valid) versions of the same block. We defend against this by detecting
61
+ # the case where we would hash two identical hashes at the end of the list
62
+ # together, and treating that identically to the block having an invalid
63
+ # merkle root. Assuming no double-SHA256 collisions, this will detect all
64
+ # known ways of changing the transactions without affecting the merkle
65
+ # root.
66
+
67
+ @tail_duplicates = false
68
+
69
+ tree = @hashes.dup
70
+ j = 0
71
+ size = tree.size
72
+ while size > 1
73
+ i = 0
74
+ while i < size
75
+ i2 = [i + 1, size - 1].min
76
+ if i2 == i + 1 && i2 + 1 == size && tree[j+i] == tree[j+i2]
77
+ # Two identical hashes at the end of the list at a particular level.
78
+ @tail_duplicates = true
79
+ end
80
+ hash = BTC.hash256(tree[j+i] + tree[j+i2])
81
+ tree << hash
82
+ i += 2
83
+ end
84
+ j += size
85
+ size = (size + 1) / 2
86
+ end
87
+ tree.last
88
+ end
89
+
90
+ end # MerkleTree
91
+ end # BTC
@@ -20,7 +20,7 @@ module BTC
20
20
  if string
21
21
  _raw_data ||= Base58.data_from_base58check(string)
22
22
  raise FormatError, "Too short AssetAddress" if _raw_data.bytesize < 2
23
- raise FormatError, "Invalid namespace for AssetAddress" if _raw_data.bytes[0] != NAMESPACE
23
+ raise FormatError, "Invalid namespace for AssetAddress" if _raw_data.bytes[0] != self.class.mainnet_version
24
24
  @bitcoin_address = BTC::Address.mux_parse_raw_data(_raw_data[1..-1])
25
25
  @base58check_string = string
26
26
  elsif bitcoin_address
@@ -46,7 +46,7 @@ module BTC
46
46
  end
47
47
 
48
48
  def data_for_base58check_encoding
49
- BTC::Data.data_from_bytes([NAMESPACE]) + @bitcoin_address.data_for_base58check_encoding
49
+ BTC::Data.data_from_bytes([self.class.mainnet_version]) + @bitcoin_address.data_for_base58check_encoding
50
50
  end
51
51
  end
52
52
  end
@@ -13,8 +13,6 @@ module BTC
13
13
  125 # 's' prefix
14
14
  end
15
15
 
16
- # Instantiates AssetID with output, output script or raw hash.
17
- # To compute an Asset ID for the Asset Definition file, use `trim_script_prefix: true`.
18
16
  def initialize(string: nil, hash: nil, network: nil, outpoint: nil, amount: nil, _raw_data: nil)
19
17
  if outpoint || amount
20
18
  raise ArgumentError, "Outpoint is missing" if !outpoint
@@ -1,3 +1,3 @@
1
1
  module BTC
2
- VERSION = "1.0.4".freeze
2
+ VERSION = "1.0.5".freeze
3
3
  end
data/lib/btcruby.rb CHANGED
@@ -34,6 +34,7 @@ require_relative 'btcruby/transaction_builder.rb'
34
34
  require_relative 'btcruby/proof_of_work.rb'
35
35
  require_relative 'btcruby/block_header.rb'
36
36
  require_relative 'btcruby/block.rb'
37
+ require_relative 'btcruby/merkle_tree.rb'
37
38
  require_relative 'btcruby/open_assets.rb'
38
39
 
39
40
  # TODO:
@@ -0,0 +1,30 @@
1
+ require_relative 'spec_helper'
2
+ describe BTC::MerkleTree do
3
+
4
+ it "should compute root of one hash equal to that hash" do
5
+ hash = "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456"
6
+ MerkleTree.new(hashes: [hash.from_hex]).merkle_root.to_hex.must_equal hash
7
+ end
8
+
9
+ it "merkle root of 2 hashes must equal hash(a+b)" do
10
+ a = "9c2e4d8fe97d881430de4e754b4205b9c27ce96715231cffc4337340cb110280".from_hex
11
+ b = "0c08173828583fc6ecd6ecdbcca7b6939c49c242ad5107e39deb7b0a5996b903".from_hex
12
+ r = "7de236613dd3d9fa1d86054a84952f1e0df2f130546b394a4d4dd7b76997f607".from_hex
13
+ r.to_hex.must_equal BTC.hash256(a+b).to_hex
14
+ mt = MerkleTree.new(hashes: [a,b])
15
+ mt.tail_duplicates?.must_equal false
16
+ mt.merkle_root.to_hex.must_equal r.to_hex
17
+ end
18
+
19
+ it "merkle root of 3 hashes must equal Hash(Hash(a+b)+Hash(c+c))" do
20
+ a = "9c2e4d8fe97d881430de4e754b4205b9c27ce96715231cffc4337340cb110280".from_hex
21
+ b = "0c08173828583fc6ecd6ecdbcca7b6939c49c242ad5107e39deb7b0a5996b903".from_hex
22
+ c = "80903da4e6bbdf96e8ff6fc3966b0cfd355c7e860bdd1caa8e4722d9230e40ac".from_hex
23
+ r = "5b7534123197114fa7e7459075f39d89ffab74b5c3f31fad48a025b931ff5a01".from_hex
24
+ r.to_hex.must_equal BTC.hash256(BTC.hash256(a+b)+BTC.hash256(c+c)).to_hex
25
+ mt = MerkleTree.new(hashes: [a,b,c])
26
+ mt.tail_duplicates?.must_equal false
27
+ mt.merkle_root.to_hex.must_equal r.to_hex
28
+ end
29
+
30
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: btcruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Andreev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-02 00:00:00.000000000 Z
12
+ date: 2015-07-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -92,6 +92,7 @@ files:
92
92
  - lib/btcruby/hash_id.rb
93
93
  - lib/btcruby/key.rb
94
94
  - lib/btcruby/keychain.rb
95
+ - lib/btcruby/merkle_tree.rb
95
96
  - lib/btcruby/network.rb
96
97
  - lib/btcruby/opcode.rb
97
98
  - lib/btcruby/open_assets.rb
@@ -140,6 +141,7 @@ files:
140
141
  - spec/diagnostics_spec.rb
141
142
  - spec/key_spec.rb
142
143
  - spec/keychain_spec.rb
144
+ - spec/merkle_tree_spec.rb
143
145
  - spec/network_spec.rb
144
146
  - spec/open_assets/asset_address_spec.rb
145
147
  - spec/open_assets/asset_id_spec.rb