btcruby 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.travis.yml +7 -0
  4. data/FAQ.md +7 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +18 -0
  7. data/HOWTO.md +17 -0
  8. data/LICENSE +19 -0
  9. data/README.md +59 -0
  10. data/Rakefile +6 -0
  11. data/TODO.txt +40 -0
  12. data/bin/console +19 -0
  13. data/btcruby.gemspec +20 -0
  14. data/documentation/address.md +73 -0
  15. data/documentation/base58.md +52 -0
  16. data/documentation/block.md +127 -0
  17. data/documentation/block_header.md +120 -0
  18. data/documentation/constants.md +88 -0
  19. data/documentation/data.md +54 -0
  20. data/documentation/diagnostics.md +90 -0
  21. data/documentation/extensions.md +76 -0
  22. data/documentation/hash_functions.md +58 -0
  23. data/documentation/hash_id.md +22 -0
  24. data/documentation/index.md +230 -0
  25. data/documentation/key.md +177 -0
  26. data/documentation/keychain.md +180 -0
  27. data/documentation/network.md +75 -0
  28. data/documentation/opcode.md +220 -0
  29. data/documentation/openssl.md +7 -0
  30. data/documentation/p2pkh.md +71 -0
  31. data/documentation/p2sh.md +64 -0
  32. data/documentation/proof_of_work.md +84 -0
  33. data/documentation/script.md +280 -0
  34. data/documentation/signature.md +71 -0
  35. data/documentation/transaction.md +213 -0
  36. data/documentation/transaction_builder.md +188 -0
  37. data/documentation/transaction_input.md +133 -0
  38. data/documentation/transaction_output.md +130 -0
  39. data/documentation/wif.md +72 -0
  40. data/documentation/wire_format.md +70 -0
  41. data/lib/btcruby/address.rb +296 -0
  42. data/lib/btcruby/base58.rb +108 -0
  43. data/lib/btcruby/big_number.rb +47 -0
  44. data/lib/btcruby/block.rb +170 -0
  45. data/lib/btcruby/block_header.rb +231 -0
  46. data/lib/btcruby/constants.rb +59 -0
  47. data/lib/btcruby/currency_formatter.rb +64 -0
  48. data/lib/btcruby/data.rb +98 -0
  49. data/lib/btcruby/diagnostics.rb +92 -0
  50. data/lib/btcruby/errors.rb +8 -0
  51. data/lib/btcruby/extensions.rb +65 -0
  52. data/lib/btcruby/hash_functions.rb +54 -0
  53. data/lib/btcruby/hash_id.rb +18 -0
  54. data/lib/btcruby/key.rb +517 -0
  55. data/lib/btcruby/keychain.rb +464 -0
  56. data/lib/btcruby/network.rb +73 -0
  57. data/lib/btcruby/opcode.rb +197 -0
  58. data/lib/btcruby/open_assets/asset.rb +35 -0
  59. data/lib/btcruby/open_assets/asset_address.rb +49 -0
  60. data/lib/btcruby/open_assets/asset_definition.rb +75 -0
  61. data/lib/btcruby/open_assets/asset_id.rb +24 -0
  62. data/lib/btcruby/open_assets/asset_marker.rb +94 -0
  63. data/lib/btcruby/open_assets/asset_processor.rb +377 -0
  64. data/lib/btcruby/open_assets/asset_transaction.rb +184 -0
  65. data/lib/btcruby/open_assets/asset_transaction_builder/errors.rb +15 -0
  66. data/lib/btcruby/open_assets/asset_transaction_builder/provider.rb +32 -0
  67. data/lib/btcruby/open_assets/asset_transaction_builder/result.rb +47 -0
  68. data/lib/btcruby/open_assets/asset_transaction_builder.rb +418 -0
  69. data/lib/btcruby/open_assets/asset_transaction_input.rb +64 -0
  70. data/lib/btcruby/open_assets/asset_transaction_output.rb +140 -0
  71. data/lib/btcruby/open_assets.rb +26 -0
  72. data/lib/btcruby/openssl.rb +536 -0
  73. data/lib/btcruby/proof_of_work.rb +110 -0
  74. data/lib/btcruby/safety.rb +26 -0
  75. data/lib/btcruby/script.rb +733 -0
  76. data/lib/btcruby/signature_hashtype.rb +37 -0
  77. data/lib/btcruby/transaction.rb +511 -0
  78. data/lib/btcruby/transaction_builder/errors.rb +15 -0
  79. data/lib/btcruby/transaction_builder/provider.rb +54 -0
  80. data/lib/btcruby/transaction_builder/result.rb +73 -0
  81. data/lib/btcruby/transaction_builder/signer.rb +28 -0
  82. data/lib/btcruby/transaction_builder.rb +520 -0
  83. data/lib/btcruby/transaction_input.rb +298 -0
  84. data/lib/btcruby/transaction_outpoint.rb +30 -0
  85. data/lib/btcruby/transaction_output.rb +315 -0
  86. data/lib/btcruby/version.rb +3 -0
  87. data/lib/btcruby/wif.rb +118 -0
  88. data/lib/btcruby/wire_format.rb +362 -0
  89. data/lib/btcruby.rb +44 -2
  90. data/sample_code/creating_a_p2sh_multisig_address.rb +21 -0
  91. data/sample_code/creating_a_transaction_manually.rb +44 -0
  92. data/sample_code/generating_an_address.rb +20 -0
  93. data/sample_code/using_transaction_builder.rb +49 -0
  94. data/spec/address_spec.rb +206 -0
  95. data/spec/all.rb +6 -0
  96. data/spec/base58_spec.rb +83 -0
  97. data/spec/block_header_spec.rb +18 -0
  98. data/spec/block_spec.rb +18 -0
  99. data/spec/currency_formatter_spec.rb +46 -0
  100. data/spec/data_spec.rb +50 -0
  101. data/spec/diagnostics_spec.rb +41 -0
  102. data/spec/key_spec.rb +205 -0
  103. data/spec/keychain_spec.rb +261 -0
  104. data/spec/network_spec.rb +48 -0
  105. data/spec/open_assets/asset_address_spec.rb +33 -0
  106. data/spec/open_assets/asset_id_spec.rb +15 -0
  107. data/spec/open_assets/asset_marker_spec.rb +47 -0
  108. data/spec/open_assets/asset_processor_spec.rb +567 -0
  109. data/spec/open_assets/asset_transaction_builder_spec.rb +273 -0
  110. data/spec/open_assets/asset_transaction_spec.rb +70 -0
  111. data/spec/proof_of_work_spec.rb +53 -0
  112. data/spec/script_spec.rb +66 -0
  113. data/spec/spec_helper.rb +8 -0
  114. data/spec/transaction_builder_spec.rb +338 -0
  115. data/spec/transaction_spec.rb +162 -0
  116. data/spec/wire_format_spec.rb +283 -0
  117. metadata +141 -7
@@ -0,0 +1,273 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe BTC::AssetTransactionBuilder do
4
+
5
+ class SignerByKey
6
+ include TransactionBuilder::Signer
7
+ def initialize(&block)
8
+ @block = block
9
+ end
10
+ def signing_key_for_output(output: nil, address: nil)
11
+ @block.call(output, address)
12
+ end
13
+ end
14
+
15
+ describe "Issuing an asset with two transactions" do
16
+
17
+ before do
18
+ builder = BTC::AssetTransactionBuilder.new
19
+
20
+ @all_wallet_utxos = self.mock_wallet_utxos
21
+ builder.bitcoin_provider = TransactionBuilder::Provider.new do |txb|
22
+ @all_wallet_utxos
23
+ end
24
+ builder.signer = SignerByKey.new do |output, address|
25
+ mock_all_keys.find{|k| k.address == address }
26
+ end
27
+
28
+ # We want to issue 1M units to one address and 50K units for another.
29
+ # OpenAssets does not allow issuing different assets in one Asset Transaction because Asset ID is determined by the first input.
30
+ builder.issue_asset(source_script: issuer1_key.address.script, amount: 1000_000, address: holder1_asset_address)
31
+ builder.issue_asset(source_script: issuer1_key.address.script, amount: 50_000, address: holder2_asset_address)
32
+
33
+ # Just some payment to add.
34
+ builder.send_bitcoin(amount: 100, address: wallet1_key.address)
35
+
36
+ # Send btc change to this address.
37
+ builder.bitcoin_change_address = wallet2_key.address
38
+
39
+ # Send leftover assets to this address.
40
+ builder.asset_change_address = holder2_asset_address
41
+
42
+ # Build transactions.
43
+ @builder = builder
44
+ @result = builder.build
45
+ end
46
+
47
+ it "should have two transactions: asset definition and issuance" do
48
+ @result.transactions.size.must_equal(2)
49
+ end
50
+
51
+ it "should have last transaction wrapped in AssetTransaction" do
52
+ @result.asset_transaction.transaction.must_equal(@result.transactions.last)
53
+ end
54
+
55
+ it "should have two transactions linked up" do
56
+ @result.transactions.last.inputs.first.previous_hash.must_equal @result.transactions.first.transaction_hash
57
+ end
58
+
59
+ it "should have first transaction uncolored" do
60
+ @result.transactions.first.open_assets_transaction?.must_equal false
61
+ end
62
+
63
+ it "should have second transaction with colored outputs" do
64
+ @result.transactions.last.open_assets_transaction?.must_equal true
65
+ @result.asset_transaction.inputs.each do |ain|
66
+ ain.colored?.must_equal false
67
+ ain.verified?.must_equal true
68
+ end
69
+ @result.asset_transaction.outputs.each_with_index do |aout, i|
70
+ aout.colored?.must_equal(i < 2) # only first 2 outputs are colored because they issue asset
71
+ aout.verified?.must_equal true
72
+ end
73
+ end
74
+
75
+ it "should have an asset cost of two issuances" do
76
+ @result.assets_cost.must_equal 546*2
77
+ end
78
+ end
79
+
80
+ describe "Issuing an asset with an existing source output" do
81
+ end
82
+
83
+ describe "Transferring a few assets" do
84
+ before do
85
+
86
+ builder = BTC::AssetTransactionBuilder.new
87
+
88
+ @all_wallet_utxos = self.mock_wallet_utxos
89
+ builder.bitcoin_provider = TransactionBuilder::Provider.new do |txb|
90
+ @all_wallet_utxos
91
+ end
92
+ builder.signer = SignerByKey.new do |output, address|
93
+ mock_all_keys.find{|k| k.address == address }
94
+ end
95
+
96
+ # We want to be able to swap assets: when one user provides Apples and the other provides Oranges.
97
+ # Each transfer may have its own unspents and its own change address.
98
+ # If those are not specified, a per-builder setting is chosen.
99
+
100
+ @asset1 = AssetID.new(script: Script.new << OP_1)
101
+ @asset2 = AssetID.new(script: Script.new << OP_2)
102
+
103
+ builder.transfer_asset(
104
+ asset_id: @asset1,
105
+ amount: 10_000,
106
+ address: holder2_asset_address,
107
+ unspent_outputs: [
108
+ AssetTransactionOutput.new(
109
+ transaction_output: mock_utxo(value: 1000),
110
+ asset_id: @asset1,
111
+ value: 11_000,
112
+ transfer: true,
113
+ verified: true,
114
+ )
115
+ ],
116
+ change_address: holder1_asset_address
117
+ )
118
+
119
+ builder.transfer_asset(
120
+ asset_id: @asset2,
121
+ amount: 50_000,
122
+ address: holder1_asset_address,
123
+ unspent_outputs: [
124
+ AssetTransactionOutput.new(
125
+ transaction_output: mock_utxo(value: 1000),
126
+ asset_id: @asset2,
127
+ value: 150_000,
128
+ transfer: true,
129
+ verified: true,
130
+ )
131
+ ],
132
+ change_address: holder2_asset_address
133
+ )
134
+
135
+ # Send btc change to this address.
136
+ builder.bitcoin_change_address = wallet2_key.address
137
+
138
+ # Send leftover assets to this address.
139
+ builder.asset_change_address = AssetAddress.new(bitcoin_address: holder2_key.address)
140
+
141
+ # Build transactions.
142
+ @builder = builder
143
+ @result = builder.build
144
+ end
145
+
146
+ it "should have two change outputs: for each transfer" do
147
+ @result.asset_transaction.outputs.size.must_equal(1 + 2 + 2 + 1)
148
+ marker, transfer1, change1, transfer2, change2, btcchange = @result.asset_transaction.outputs
149
+
150
+ transfer1.transfer?.must_equal true
151
+ transfer1.value.must_equal 10_000
152
+ change1.transfer?.must_equal true
153
+ change1.value.must_equal 1_000
154
+ transfer1.asset_id.to_s.must_equal change1.asset_id.to_s
155
+ transfer1.asset_id.to_s.must_equal @asset1.to_s
156
+ transfer1.transaction_output.script.standard_address.to_s.must_equal holder2_key.address.to_s
157
+ change1.transaction_output.script.standard_address.to_s.must_equal holder1_key.address.to_s
158
+
159
+ transfer2.transfer?.must_equal true
160
+ transfer2.value.must_equal 50_000
161
+ change2.transfer?.must_equal true
162
+ change2.value.must_equal 100_000
163
+ transfer2.asset_id.to_s.must_equal change2.asset_id.to_s
164
+ transfer2.asset_id.to_s.must_equal @asset2.to_s
165
+ transfer2.transaction_output.script.standard_address.to_s.must_equal holder1_key.address.to_s
166
+ change2.transaction_output.script.standard_address.to_s.must_equal holder2_key.address.to_s
167
+
168
+ btcchange.colored?.must_equal false
169
+ btcchange.verified?.must_equal true
170
+ btcchange.asset_id.must_equal nil
171
+ end
172
+ end
173
+
174
+ # Mocked wallet
175
+
176
+ def wallet1_key
177
+ @wallet1_key ||= Key.new(private_key: "Wallet1".sha256)
178
+ end
179
+
180
+ def wallet2_key
181
+ @wallet2_key ||= Key.new(private_key: "Wallet2".sha256)
182
+ end
183
+
184
+ def issuer1_key
185
+ @issuer1_key ||= Key.new(private_key: "Issuer1".sha256)
186
+ end
187
+
188
+ def issuer2_key
189
+ @issuer2_key ||= Key.new(private_key: "Issuer2".sha256)
190
+ end
191
+
192
+ def holder1_key
193
+ @holder1_key ||= Key.new(private_key: "Holder1".sha256)
194
+ end
195
+
196
+ def holder2_key
197
+ @holder2_key ||= Key.new(private_key: "Holder2".sha256)
198
+ end
199
+
200
+ def holder1_asset_address
201
+ AssetAddress.new(bitcoin_address: holder1_key.address)
202
+ end
203
+
204
+ def holder2_asset_address
205
+ AssetAddress.new(bitcoin_address: holder2_key.address)
206
+ end
207
+
208
+ def mock_wallet_keys
209
+ @mock_wallet_keys ||= [wallet1_key, wallet2_key]
210
+ end
211
+
212
+ def mock_all_keys
213
+ @mock_all_keys ||= [wallet1_key, wallet2_key,
214
+ issuer1_key, issuer2_key,
215
+ holder1_key, holder2_key]
216
+ end
217
+
218
+ def mock_wallet_addresses
219
+ mock_wallet_keys.map{|k| k.address }
220
+ end
221
+
222
+ def mock_wallet_utxos
223
+ scripts = mock_wallet_addresses.map{|a| a.script }
224
+ (1..32).map do |i|
225
+ TransactionOutput.new(value: 100_000,
226
+ script: scripts[i % scripts.size],
227
+ transaction_hash: ((16+i).to_s(16)*32).from_hex,
228
+ index: i)
229
+ end
230
+ end
231
+
232
+ def mock_utxo(value: 100_000, index: 0, script: Script.new << OP_1)
233
+ TransactionOutput.new(value: value,
234
+ script: script,
235
+ transaction_hash: Key.random.private_key.sha256,
236
+ index: index)
237
+ end
238
+
239
+ def mock_asset_utxos
240
+
241
+ end
242
+
243
+ end
244
+
245
+ # Temporary test
246
+ describe "Issuing an asset" do
247
+
248
+ it "should issue a new asset from a given tx output" do
249
+ issuer = BTC::Key.new(private_key: "Treasury Key".sha256)
250
+ holder = BTC::Key.new(private_key: "Chancellor Key".sha256)
251
+
252
+ issuing_script = issuer.address.script
253
+ holding_script = holder.address.script
254
+
255
+ source_output = TransactionOutput.new(value: 100, script: issuing_script)
256
+
257
+ # These are set automatically if source_output is a part of some BTC::Transaction
258
+ # We need these to complete the input for the transfer transaction.
259
+ source_output.transaction_hash = BTC::Data.hash256("some tx")
260
+ source_output.index = 0
261
+
262
+ transfer = Transaction.new
263
+ transfer.add_input(TransactionInput.new(transaction_output: source_output))
264
+ transfer.add_output(TransactionOutput.new(value: source_output.value, script: holding_script))
265
+ marker = AssetMarker.new
266
+ marker.quantities = [ 1000_000_000 ]
267
+ marker.metadata = "Chancellor bailing out banks"
268
+ transfer.outputs << marker.output
269
+ end
270
+
271
+ end
272
+
273
+
@@ -0,0 +1,70 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "Serialization" do
4
+
5
+ def build_asset_transaction(inputs: [], issues: [], transfers: [])
6
+ tx = Transaction.new
7
+ script = PublicKeyAddress.new(hash: "some address".hash160).script
8
+ inputs.each do
9
+ tx.add_input(TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
10
+ end
11
+ issues.each do |tuple|
12
+ tx.add_output(TransactionOutput.new(value: 1, script: script))
13
+ end
14
+ qtys = issues.map{|tuple| tuple.first} + transfers.map{|tuple| tuple.first}
15
+ tx.add_output(AssetMarker.new(quantities: qtys).output)
16
+ transfers.each do |tuple|
17
+ tx.add_output(TransactionOutput.new(value: 1, script: script))
18
+ end
19
+
20
+ atx = AssetTransaction.new(transaction: tx)
21
+ atx.inputs.each_with_index do |ain, i|
22
+ amount, name = inputs[i]
23
+ if amount
24
+ ain.asset_id = asset_id(name)
25
+ ain.value = amount
26
+ ain.verified = true
27
+ else
28
+ ain.asset_id = nil
29
+ ain.value = nil
30
+ ain.verified = true
31
+ end
32
+ end
33
+
34
+ atx
35
+ end
36
+
37
+ def asset_id(name)
38
+ name ? AssetID.new(hash: name.hash160) : nil
39
+ end
40
+
41
+ before do
42
+ @atx = build_asset_transaction(
43
+ inputs: [ [100, "A"], [30, "B"], [14, "B"] ],
44
+ issues: [ ],
45
+ transfers: [ [40, "A"], [60, "A"], [44, "B"] ]
46
+ )
47
+ data = @atx.data
48
+ @atx2 = AssetTransaction.new(data: data)
49
+ end
50
+
51
+ it "should restore all outputs" do
52
+ @atx.inputs.each_with_index do |ain1, i|
53
+ ain2 = @atx2.inputs[i]
54
+ ain1.verified?.must_equal ain2.verified?
55
+ ain1.verified?.must_equal true
56
+ ain1.asset_id.must_equal ain2.asset_id
57
+ ain1.value.must_equal ain2.value
58
+ end
59
+ @atx.outputs.each_with_index do |aout1, i|
60
+ aout2 = @atx2.outputs[i]
61
+ aout1.verified?.must_equal aout2.verified?
62
+ aout1.verified?.must_equal aout1.marker?
63
+ aout1.asset_id.must_equal aout2.asset_id
64
+ aout1.asset_id.must_equal nil
65
+ aout1.value.must_equal aout2.value
66
+ end
67
+ end
68
+
69
+
70
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'spec_helper'
2
+ describe BTC::ProofOfWork do
3
+
4
+ POW = BTC::ProofOfWork
5
+
6
+ it "should convert target to bits" do
7
+ POW.bits_from_target(0x00000000ffff0000000000000000000000000000000000000000000000000000).must_equal 0x1d00ffff
8
+ POW.bits_from_target(0x00000007fff80000000000000000000000000000000000000000000000000000).must_equal 0x1d07fff8
9
+ POW.bits_from_target(0x0).must_equal 0x03000000
10
+ end
11
+
12
+ it "should convert bits to target" do
13
+ POW.target_from_bits(0x1d00ffff).must_equal 0x00000000ffff0000000000000000000000000000000000000000000000000000
14
+ POW.target_from_bits(0x1d07fff8).must_equal 0x00000007fff80000000000000000000000000000000000000000000000000000
15
+ POW.target_from_bits(0x03000000).must_equal 0x0
16
+ end
17
+
18
+ it "should convert hash to target integer" do
19
+ POW.target_from_hash("").must_equal 0
20
+ POW.target_from_hash("\x00").must_equal 0
21
+ POW.target_from_hash("\x12").must_equal 0x12
22
+ POW.target_from_hash("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000".from_hex).must_equal 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
23
+ end
24
+
25
+ it "should convert target integer to 32-byte hash" do
26
+ POW.hash_from_target(0).must_equal "\x00"*32
27
+ POW.hash_from_target(0xbabe).must_equal "\xbe\xba".b.ljust(32, "\x00")
28
+ POW.hash_from_target(0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f).must_equal "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000".from_hex
29
+ end
30
+
31
+ it "should convert target to difficulty (on mainnet)" do
32
+ POW.difficulty_from_target(0x00000000ffff0000000000000000000000000000000000000000000000000000).to_i.must_equal 1
33
+ POW.difficulty_from_target(0x000000007fff8000000000000000000000000000000000000000000000000000).to_i.must_equal 2
34
+ POW.difficulty_from_target(0x000000000ffff000000000000000000000000000000000000000000000000000).to_i.must_equal 16
35
+ POW.difficulty_from_target(0x0000000000ffff00000000000000000000000000000000000000000000000000).to_i.must_equal 256
36
+ end
37
+
38
+ it "should convert target to difficulty (on testnet)" do
39
+ POW.difficulty_from_target(0x00000007fff80000000000000000000000000000000000000000000000000000,
40
+ max_target: POW::MAX_TARGET_TESTNET).to_i.must_equal 1
41
+ POW.difficulty_from_target(0x00000003fff80000000000000000000000000000000000000000000000000000,
42
+ max_target: POW::MAX_TARGET_TESTNET).to_i.must_equal 2
43
+ POW.difficulty_from_target(0x000000007fff8000000000000000000000000000000000000000000000000000,
44
+ max_target: POW::MAX_TARGET_TESTNET).to_i.must_equal 16
45
+ POW.difficulty_from_target(0x0000000007fff800000000000000000000000000000000000000000000000000,
46
+ max_target: POW::MAX_TARGET_TESTNET).to_i.must_equal 256
47
+ end
48
+
49
+ it "should convert difficulty to target or bits" do
50
+ POW.target_from_difficulty(1.0).must_equal 0x00000000ffff0000000000000000000000000000000000000000000000000000
51
+ POW.bits_from_difficulty(39603666252.41841).must_equal 0x181bc330
52
+ end
53
+ end
@@ -0,0 +1,66 @@
1
+ require_relative 'spec_helper'
2
+ describe BTC::Script do
3
+
4
+ it "should instantiate with empty data" do
5
+ empty_script = Script.new
6
+ empty_script.data.must_equal "".b
7
+ empty_script.to_s.must_equal ''
8
+ end
9
+
10
+ it "should support standard P2PKH script" do
11
+ script = (Script.new << OP_DUP << OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << OP_EQUALVERIFY << OP_CHECKSIG)
12
+ script.standard?.must_equal true
13
+ script.public_key_hash_script?.must_equal true
14
+ script.script_hash_script?.must_equal false
15
+ script.multisig_script?.must_equal false
16
+ script.standard_multisig_script?.must_equal false
17
+ script.standard_address.class.must_equal PublicKeyAddress
18
+ script.standard_address.data.must_equal "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex
19
+ script.to_s.must_equal "OP_DUP OP_HASH160 5a73e920b7836c74f9e740a5bb885e8580557038 OP_EQUALVERIFY OP_CHECKSIG"
20
+ end
21
+
22
+ it "should support standard P2SH script" do
23
+ script = (Script.new << OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << OP_EQUAL)
24
+ script.standard?.must_equal true
25
+ script.public_key_hash_script?.must_equal false
26
+ script.script_hash_script?.must_equal true
27
+ script.multisig_script?.must_equal false
28
+ script.standard_multisig_script?.must_equal false
29
+ script.standard_address.class.must_equal ScriptHashAddress
30
+ script.standard_address.data.must_equal "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex
31
+ script.to_s.must_equal "OP_HASH160 5a73e920b7836c74f9e740a5bb885e8580557038 OP_EQUAL"
32
+ end
33
+
34
+ it "should support standard multisig script" do
35
+ script = (Script.new << OP_1 <<
36
+ "c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a".from_hex <<
37
+ "bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19".from_hex <<
38
+ OP_2 <<
39
+ OP_CHECKMULTISIG)
40
+ script.standard?.must_equal true
41
+ script.public_key_hash_script?.must_equal false
42
+ script.script_hash_script?.must_equal false
43
+ script.multisig_script?.must_equal true
44
+ script.standard_multisig_script?.must_equal true
45
+ script.standard_address.must_equal nil
46
+ script.multisig_public_keys.must_equal [
47
+ "c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a".from_hex,
48
+ "bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19".from_hex
49
+ ]
50
+ script.multisig_signatures_required.must_equal 1
51
+ script.to_s.must_equal "OP_1 c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a "+
52
+ "bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19 OP_2 OP_CHECKMULTISIG"
53
+
54
+ script2 = Script.multisig(public_keys:[
55
+ "c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a".from_hex,
56
+ "bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19".from_hex
57
+ ], signatures_required: 1)
58
+
59
+ script2.standard_multisig_script?.must_equal true
60
+ script.must_equal script2
61
+
62
+
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,8 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+
4
+ require_relative '../lib/btcruby'
5
+ require_relative '../lib/btcruby/extensions'
6
+
7
+ # So every test can access classes directly without prefixing them with BTC::
8
+ include BTC