btcruby 1.0.4 → 1.0.5

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
  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