btcruby 1.1.4 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/RELEASE_NOTES.md +7 -0
- data/lib/btcruby.rb +1 -1
- data/lib/btcruby/address.rb +1 -0
- data/lib/btcruby/open_assets/asset_marker.rb +1 -0
- data/lib/btcruby/script/opcode.rb +3 -0
- data/lib/btcruby/script/script.rb +2 -1
- data/lib/btcruby/script/script_chunk.rb +1 -0
- data/lib/btcruby/script/script_error.rb +41 -37
- data/lib/btcruby/script/script_interpreter.rb +2 -0
- data/lib/btcruby/script/script_interpreter_plugin.rb +2 -0
- data/lib/btcruby/transaction_builder.rb +1 -0
- data/lib/btcruby/version.rb +1 -1
- data/spec/address_spec.rb +22 -22
- data/spec/base58_spec.rb +8 -8
- data/spec/block_header_spec.rb +4 -4
- data/spec/block_spec.rb +4 -4
- data/spec/currency_formatter_spec.rb +30 -30
- data/spec/data_spec.rb +3 -3
- data/spec/key_spec.rb +11 -11
- data/spec/keychain_spec.rb +12 -12
- data/spec/merkle_tree_spec.rb +3 -3
- data/spec/open_assets/asset_address_spec.rb +7 -7
- data/spec/open_assets/asset_id_spec.rb +3 -3
- data/spec/open_assets/asset_marker_spec.rb +5 -5
- data/spec/open_assets/asset_processor_spec.rb +48 -48
- data/spec/open_assets/asset_transaction_builder_spec.rb +26 -26
- data/spec/open_assets/asset_transaction_spec.rb +9 -9
- data/spec/open_assets/issuance_id_spec.rb +3 -3
- data/spec/script_interpreter_spec.rb +4 -4
- data/spec/script_spec.rb +23 -23
- data/spec/spec_helper.rb +33 -31
- data/spec/transaction_builder_spec.rb +33 -33
- data/spec/transaction_spec.rb +18 -18
- data/spec/wire_format_spec.rb +5 -5
- metadata +2 -2
@@ -3,7 +3,7 @@ require_relative '../spec_helper'
|
|
3
3
|
describe BTC::AssetTransactionBuilder do
|
4
4
|
|
5
5
|
class SignerByKey
|
6
|
-
include TransactionBuilder::Signer
|
6
|
+
include BTC::TransactionBuilder::Signer
|
7
7
|
def initialize(&block)
|
8
8
|
@block = block
|
9
9
|
end
|
@@ -18,7 +18,7 @@ describe BTC::AssetTransactionBuilder do
|
|
18
18
|
builder = BTC::AssetTransactionBuilder.new
|
19
19
|
|
20
20
|
@all_wallet_utxos = self.mock_wallet_utxos
|
21
|
-
builder.bitcoin_provider = TransactionBuilder::Provider.new do |txb|
|
21
|
+
builder.bitcoin_provider = BTC::TransactionBuilder::Provider.new do |txb|
|
22
22
|
@all_wallet_utxos
|
23
23
|
end
|
24
24
|
builder.signer = SignerByKey.new do |output, address|
|
@@ -86,7 +86,7 @@ describe BTC::AssetTransactionBuilder do
|
|
86
86
|
builder = BTC::AssetTransactionBuilder.new
|
87
87
|
|
88
88
|
@all_wallet_utxos = self.mock_wallet_utxos
|
89
|
-
builder.bitcoin_provider = TransactionBuilder::Provider.new do |txb|
|
89
|
+
builder.bitcoin_provider = BTC::TransactionBuilder::Provider.new do |txb|
|
90
90
|
@all_wallet_utxos
|
91
91
|
end
|
92
92
|
builder.signer = SignerByKey.new do |output, address|
|
@@ -97,15 +97,15 @@ describe BTC::AssetTransactionBuilder do
|
|
97
97
|
# Each transfer may have its own unspents and its own change address.
|
98
98
|
# If those are not specified, a per-builder setting is chosen.
|
99
99
|
|
100
|
-
@asset1 = AssetID.new(script: Script.new << OP_1)
|
101
|
-
@asset2 = AssetID.new(script: Script.new << OP_2)
|
100
|
+
@asset1 = BTC::AssetID.new(script: BTC::Script.new << BTC::OP_1)
|
101
|
+
@asset2 = BTC::AssetID.new(script: BTC::Script.new << BTC::OP_2)
|
102
102
|
|
103
103
|
builder.transfer_asset(
|
104
104
|
asset_id: @asset1,
|
105
105
|
amount: 10_000,
|
106
106
|
address: holder2_asset_address,
|
107
107
|
unspent_outputs: [
|
108
|
-
AssetTransactionOutput.new(
|
108
|
+
BTC::AssetTransactionOutput.new(
|
109
109
|
transaction_output: mock_utxo(value: 1000),
|
110
110
|
asset_id: @asset1,
|
111
111
|
value: 11_000,
|
@@ -121,7 +121,7 @@ describe BTC::AssetTransactionBuilder do
|
|
121
121
|
amount: 50_000,
|
122
122
|
address: holder1_asset_address,
|
123
123
|
unspent_outputs: [
|
124
|
-
AssetTransactionOutput.new(
|
124
|
+
BTC::AssetTransactionOutput.new(
|
125
125
|
transaction_output: mock_utxo(value: 1000),
|
126
126
|
asset_id: @asset2,
|
127
127
|
value: 150_000,
|
@@ -136,7 +136,7 @@ describe BTC::AssetTransactionBuilder do
|
|
136
136
|
builder.bitcoin_change_address = wallet2_key.address
|
137
137
|
|
138
138
|
# Send leftover assets to this address.
|
139
|
-
builder.asset_change_address = AssetAddress.new(bitcoin_address: holder2_key.address)
|
139
|
+
builder.asset_change_address = BTC::AssetAddress.new(bitcoin_address: holder2_key.address)
|
140
140
|
|
141
141
|
# Build transactions.
|
142
142
|
@builder = builder
|
@@ -174,35 +174,35 @@ describe BTC::AssetTransactionBuilder do
|
|
174
174
|
# Mocked wallet
|
175
175
|
|
176
176
|
def wallet1_key
|
177
|
-
@wallet1_key ||= Key.new(private_key: "Wallet1".sha256)
|
177
|
+
@wallet1_key ||= BTC::Key.new(private_key: "Wallet1".sha256)
|
178
178
|
end
|
179
179
|
|
180
180
|
def wallet2_key
|
181
|
-
@wallet2_key ||= Key.new(private_key: "Wallet2".sha256)
|
181
|
+
@wallet2_key ||= BTC::Key.new(private_key: "Wallet2".sha256)
|
182
182
|
end
|
183
183
|
|
184
184
|
def issuer1_key
|
185
|
-
@issuer1_key ||= Key.new(private_key: "Issuer1".sha256)
|
185
|
+
@issuer1_key ||= BTC::Key.new(private_key: "Issuer1".sha256)
|
186
186
|
end
|
187
187
|
|
188
188
|
def issuer2_key
|
189
|
-
@issuer2_key ||= Key.new(private_key: "Issuer2".sha256)
|
189
|
+
@issuer2_key ||= BTC::Key.new(private_key: "Issuer2".sha256)
|
190
190
|
end
|
191
191
|
|
192
192
|
def holder1_key
|
193
|
-
@holder1_key ||= Key.new(private_key: "Holder1".sha256)
|
193
|
+
@holder1_key ||= BTC::Key.new(private_key: "Holder1".sha256)
|
194
194
|
end
|
195
195
|
|
196
196
|
def holder2_key
|
197
|
-
@holder2_key ||= Key.new(private_key: "Holder2".sha256)
|
197
|
+
@holder2_key ||= BTC::Key.new(private_key: "Holder2".sha256)
|
198
198
|
end
|
199
199
|
|
200
200
|
def holder1_asset_address
|
201
|
-
AssetAddress.new(bitcoin_address: holder1_key.address)
|
201
|
+
BTC::AssetAddress.new(bitcoin_address: holder1_key.address)
|
202
202
|
end
|
203
203
|
|
204
204
|
def holder2_asset_address
|
205
|
-
AssetAddress.new(bitcoin_address: holder2_key.address)
|
205
|
+
BTC::AssetAddress.new(bitcoin_address: holder2_key.address)
|
206
206
|
end
|
207
207
|
|
208
208
|
def mock_wallet_keys
|
@@ -222,17 +222,17 @@ describe BTC::AssetTransactionBuilder do
|
|
222
222
|
def mock_wallet_utxos
|
223
223
|
scripts = mock_wallet_addresses.map{|a| a.script }
|
224
224
|
(1..32).map do |i|
|
225
|
-
TransactionOutput.new(value: 100_000,
|
225
|
+
BTC::TransactionOutput.new(value: 100_000,
|
226
226
|
script: scripts[i % scripts.size],
|
227
227
|
transaction_hash: ((16+i).to_s(16)*32).from_hex,
|
228
228
|
index: i)
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
232
|
-
def mock_utxo(value: 100_000, index: 0, script: Script.new << OP_1)
|
233
|
-
TransactionOutput.new(value: value,
|
232
|
+
def mock_utxo(value: 100_000, index: 0, script: BTC::Script.new << BTC::OP_1)
|
233
|
+
BTC::TransactionOutput.new(value: value,
|
234
234
|
script: script,
|
235
|
-
transaction_hash: Key.random.private_key.sha256,
|
235
|
+
transaction_hash: BTC::Key.random.private_key.sha256,
|
236
236
|
index: index)
|
237
237
|
end
|
238
238
|
|
@@ -252,17 +252,17 @@ describe "Issuing an asset" do
|
|
252
252
|
issuing_script = issuer.address.script
|
253
253
|
holding_script = holder.address.script
|
254
254
|
|
255
|
-
source_output = TransactionOutput.new(value: 100, script: issuing_script)
|
255
|
+
source_output = BTC::TransactionOutput.new(value: 100, script: issuing_script)
|
256
256
|
|
257
257
|
# These are set automatically if source_output is a part of some BTC::Transaction
|
258
258
|
# We need these to complete the input for the transfer transaction.
|
259
|
-
source_output.transaction_hash = BTC
|
259
|
+
source_output.transaction_hash = BTC.hash256("some tx")
|
260
260
|
source_output.index = 0
|
261
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
|
262
|
+
transfer = BTC::Transaction.new
|
263
|
+
transfer.add_input(BTC::TransactionInput.new(transaction_output: source_output))
|
264
|
+
transfer.add_output(BTC::TransactionOutput.new(value: source_output.value, script: holding_script))
|
265
|
+
marker = BTC::AssetMarker.new
|
266
266
|
marker.quantities = [ 1000_000_000 ]
|
267
267
|
marker.metadata = "Chancellor bailing out banks"
|
268
268
|
transfer.outputs << marker.output
|
@@ -3,21 +3,21 @@ require_relative '../spec_helper'
|
|
3
3
|
describe "Serialization" do
|
4
4
|
|
5
5
|
def build_asset_transaction(inputs: [], issues: [], transfers: [])
|
6
|
-
tx = Transaction.new
|
7
|
-
script = PublicKeyAddress.new(hash: "some address".hash160).script
|
6
|
+
tx = BTC::Transaction.new
|
7
|
+
script = BTC::PublicKeyAddress.new(hash: "some address".hash160).script
|
8
8
|
inputs.each do
|
9
|
-
tx.add_input(TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
9
|
+
tx.add_input(BTC::TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
10
10
|
end
|
11
11
|
issues.each do |tuple|
|
12
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
12
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
13
13
|
end
|
14
14
|
qtys = issues.map{|tuple| tuple.first} + transfers.map{|tuple| tuple.first}
|
15
|
-
tx.add_output(AssetMarker.new(quantities: qtys).output)
|
15
|
+
tx.add_output(BTC::AssetMarker.new(quantities: qtys).output)
|
16
16
|
transfers.each do |tuple|
|
17
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
17
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
18
18
|
end
|
19
19
|
|
20
|
-
atx = AssetTransaction.new(transaction: tx)
|
20
|
+
atx = BTC::AssetTransaction.new(transaction: tx)
|
21
21
|
atx.inputs.each_with_index do |ain, i|
|
22
22
|
amount, name = inputs[i]
|
23
23
|
if amount
|
@@ -35,7 +35,7 @@ describe "Serialization" do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def asset_id(name)
|
38
|
-
name ? AssetID.new(hash: name.hash160) : nil
|
38
|
+
name ? BTC::AssetID.new(hash: name.hash160) : nil
|
39
39
|
end
|
40
40
|
|
41
41
|
before do
|
@@ -45,7 +45,7 @@ describe "Serialization" do
|
|
45
45
|
transfers: [ [40, "A"], [60, "A"], [44, "B"] ]
|
46
46
|
)
|
47
47
|
data = @atx.data
|
48
|
-
@atx2 = AssetTransaction.new(data: data)
|
48
|
+
@atx2 = BTC::AssetTransaction.new(data: data)
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should restore all outputs" do
|
@@ -2,14 +2,14 @@ require_relative '../spec_helper'
|
|
2
2
|
|
3
3
|
describe BTC::IssuanceID do
|
4
4
|
it "should encode script to a correct address" do
|
5
|
-
key = Key.new(private_key: "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725".from_hex, public_key_compressed: false)
|
6
|
-
issuance_id = IssuanceID.new(outpoint: Outpoint.new(transaction_hash: BTC.hash256("tx1"), index:1), amount:100, network: Network.mainnet)
|
5
|
+
key = BTC::Key.new(private_key: "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725".from_hex, public_key_compressed: false)
|
6
|
+
issuance_id = BTC::IssuanceID.new(outpoint: BTC::Outpoint.new(transaction_hash: BTC.hash256("tx1"), index:1), amount:100, network: BTC::Network.mainnet)
|
7
7
|
issuance_id.hash.to_hex.must_equal "29d2765469a299d1219a1cbf7561534eae4595f7"
|
8
8
|
issuance_id.to_s.must_equal "SR78rsv5RCMMay22D3ZUZmMgPkRGpqphnQ"
|
9
9
|
issuance_id.is_a?(BTC::IssuanceID).must_equal true
|
10
10
|
end
|
11
11
|
it "should decode an asset address" do
|
12
|
-
issuance_id = Address.parse("SR78rsv5RCMMay22D3ZUZmMgPkRGpqphnQ")
|
12
|
+
issuance_id = BTC::Address.parse("SR78rsv5RCMMay22D3ZUZmMgPkRGpqphnQ")
|
13
13
|
issuance_id.is_a?(BTC::IssuanceID).must_equal true
|
14
14
|
issuance_id.hash.to_hex.must_equal "29d2765469a299d1219a1cbf7561534eae4595f7"
|
15
15
|
end
|
@@ -9,11 +9,11 @@ describe BTC::ScriptInterpreter do
|
|
9
9
|
|
10
10
|
def verify_script(sig_script, output_script, flags, expected_result, record)
|
11
11
|
tx = build_spending_transaction(sig_script, build_crediting_transaction(output_script));
|
12
|
-
checker = TransactionSignatureChecker.new(transaction: tx, input_index: 0)
|
12
|
+
checker = BTC::TransactionSignatureChecker.new(transaction: tx, input_index: 0)
|
13
13
|
plugins = []
|
14
|
-
plugins << P2SHPlugin.new if (flags & ScriptFlags::SCRIPT_VERIFY_P2SH) != 0
|
15
|
-
plugins << CLTVPlugin.new if (flags & ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) != 0
|
16
|
-
interpreter = ScriptInterpreter.new(
|
14
|
+
plugins << BTC::P2SHPlugin.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_P2SH) != 0
|
15
|
+
plugins << BTC::CLTVPlugin.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) != 0
|
16
|
+
interpreter = BTC::ScriptInterpreter.new(
|
17
17
|
flags: flags,
|
18
18
|
plugins: plugins,
|
19
19
|
signature_checker: checker,
|
data/spec/script_spec.rb
CHANGED
@@ -1,42 +1,42 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
2
|
describe BTC::Script do
|
3
|
-
|
3
|
+
|
4
4
|
it "should instantiate with empty data" do
|
5
|
-
empty_script = Script.new
|
5
|
+
empty_script = BTC::Script.new
|
6
6
|
empty_script.data.must_equal "".b
|
7
7
|
empty_script.to_s.must_equal ''
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should support standard P2PKH script" do
|
11
|
-
script = (Script.new << OP_DUP << OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << OP_EQUALVERIFY << OP_CHECKSIG)
|
11
|
+
script = (BTC::Script.new << BTC::OP_DUP << BTC::OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG)
|
12
12
|
script.standard?.must_equal true
|
13
13
|
script.public_key_hash_script?.must_equal true
|
14
14
|
script.script_hash_script?.must_equal false
|
15
15
|
script.multisig_script?.must_equal false
|
16
16
|
script.standard_multisig_script?.must_equal false
|
17
|
-
script.standard_address.class.must_equal PublicKeyAddress
|
17
|
+
script.standard_address.class.must_equal BTC::PublicKeyAddress
|
18
18
|
script.standard_address.data.must_equal "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex
|
19
19
|
script.to_s.must_equal "OP_DUP OP_HASH160 5a73e920b7836c74f9e740a5bb885e8580557038 OP_EQUALVERIFY OP_CHECKSIG"
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should support standard P2SH script" do
|
23
|
-
script = (Script.new << OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << OP_EQUAL)
|
23
|
+
script = (BTC::Script.new << BTC::OP_HASH160 << "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex << BTC::OP_EQUAL)
|
24
24
|
script.standard?.must_equal true
|
25
25
|
script.public_key_hash_script?.must_equal false
|
26
26
|
script.script_hash_script?.must_equal true
|
27
27
|
script.multisig_script?.must_equal false
|
28
28
|
script.standard_multisig_script?.must_equal false
|
29
|
-
script.standard_address.class.must_equal ScriptHashAddress
|
29
|
+
script.standard_address.class.must_equal BTC::ScriptHashAddress
|
30
30
|
script.standard_address.data.must_equal "5a73e920b7836c74f9e740a5bb885e8580557038".from_hex
|
31
31
|
script.to_s.must_equal "OP_HASH160 5a73e920b7836c74f9e740a5bb885e8580557038 OP_EQUAL"
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should support standard multisig script" do
|
35
|
-
script = (Script.new << OP_1 <<
|
35
|
+
script = (BTC::Script.new << BTC::OP_1 <<
|
36
36
|
"c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a".from_hex <<
|
37
37
|
"bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19".from_hex <<
|
38
|
-
OP_2 <<
|
39
|
-
OP_CHECKMULTISIG)
|
38
|
+
BTC::OP_2 <<
|
39
|
+
BTC::OP_CHECKMULTISIG)
|
40
40
|
script.standard?.must_equal true
|
41
41
|
script.public_key_hash_script?.must_equal false
|
42
42
|
script.script_hash_script?.must_equal false
|
@@ -51,7 +51,7 @@ describe BTC::Script do
|
|
51
51
|
script.to_s.must_equal "OP_1 c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a "+
|
52
52
|
"bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19 OP_2 OP_CHECKMULTISIG"
|
53
53
|
|
54
|
-
script2 = Script.multisig(public_keys:[
|
54
|
+
script2 = BTC::Script.multisig(public_keys:[
|
55
55
|
"c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a".from_hex,
|
56
56
|
"bffbec99da8a6573bd4e359d85c8cb62e6f483d9afac4be2db963f0fe10bcb19".from_hex
|
57
57
|
], signatures_required: 1)
|
@@ -63,36 +63,36 @@ describe BTC::Script do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should support subscripts" do
|
66
|
-
s = Script.new << OP_DUP << OP_HASH160 << OP_CODESEPARATOR << "some data" << OP_EQUALVERIFY << OP_CHECKSIG
|
66
|
+
s = BTC::Script.new << BTC::OP_DUP << BTC::OP_HASH160 << BTC::OP_CODESEPARATOR << "some data" << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG
|
67
67
|
s.subscript(0..-1).must_equal s
|
68
68
|
s[0..-1].must_equal s
|
69
|
-
s.subscript(3..-1).must_equal(Script.new << "some data" << OP_EQUALVERIFY << OP_CHECKSIG)
|
70
|
-
s[3..-1].must_equal(Script.new << "some data" << OP_EQUALVERIFY << OP_CHECKSIG)
|
69
|
+
s.subscript(3..-1).must_equal(BTC::Script.new << "some data" << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG)
|
70
|
+
s[3..-1].must_equal(BTC::Script.new << "some data" << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG)
|
71
71
|
end
|
72
72
|
|
73
73
|
|
74
74
|
it "removing subscript does not modify the receiver" do
|
75
|
-
s = Script.new << OP_DUP << OP_HASH160 << OP_CODESEPARATOR << "some data" << OP_EQUALVERIFY << OP_CHECKSIG
|
75
|
+
s = BTC::Script.new << BTC::OP_DUP << BTC::OP_HASH160 << BTC::OP_CODESEPARATOR << "some data" << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG
|
76
76
|
s1 = s.dup
|
77
|
-
s2 = s1.find_and_delete(Script.new << OP_HASH160)
|
77
|
+
s2 = s1.find_and_delete(BTC::Script.new << BTC::OP_HASH160)
|
78
78
|
s.must_equal s1
|
79
|
-
s2.must_equal(Script.new << OP_DUP << OP_CODESEPARATOR << "some data" << OP_EQUALVERIFY << OP_CHECKSIG)
|
79
|
+
s2.must_equal(BTC::Script.new << BTC::OP_DUP << BTC::OP_CODESEPARATOR << "some data" << BTC::OP_EQUALVERIFY << BTC::OP_CHECKSIG)
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should find subsequence" do
|
83
|
-
s = Script.new << OP_1 << OP_3 << OP_1 << OP_2 << OP_1 << OP_2 << OP_1 << OP_3
|
84
|
-
s2 = s.find_and_delete(Script.new << OP_1 << OP_2 << OP_1)
|
85
|
-
s2.must_equal(Script.new << OP_1 << OP_3 << OP_2 << OP_1 << OP_3)
|
83
|
+
s = BTC::Script.new << BTC::OP_1 << BTC::OP_3 << BTC::OP_1 << BTC::OP_2 << BTC::OP_1 << BTC::OP_2 << BTC::OP_1 << BTC::OP_3
|
84
|
+
s2 = s.find_and_delete(BTC::Script.new << BTC::OP_1 << BTC::OP_2 << BTC::OP_1)
|
85
|
+
s2.must_equal(BTC::Script.new << BTC::OP_1 << BTC::OP_3 << BTC::OP_2 << BTC::OP_1 << BTC::OP_3)
|
86
86
|
end
|
87
87
|
|
88
88
|
it "should not find-and-delete non-matching encoding for the same pushdata" do
|
89
|
-
s = Script.new.append_pushdata("foo").append_pushdata("foo", opcode:OP_PUSHDATA1)
|
90
|
-
s2 = s.find_and_delete(Script.new << "foo")
|
91
|
-
s2.must_equal(Script.new.append_pushdata("foo", opcode:OP_PUSHDATA1))
|
89
|
+
s = BTC::Script.new.append_pushdata("foo").append_pushdata("foo", opcode:BTC::OP_PUSHDATA1)
|
90
|
+
s2 = s.find_and_delete(BTC::Script.new << "foo")
|
91
|
+
s2.must_equal(BTC::Script.new.append_pushdata("foo", opcode:BTC::OP_PUSHDATA1))
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should parse interpreted data and pushdata correctly" do
|
95
|
-
script = Script.new << OP_0 << OP_1NEGATE << OP_NOP << OP_RESERVED << OP_1 << OP_16 << "1" << "2" << "chancellor"
|
95
|
+
script = BTC::Script.new << BTC::OP_0 << BTC::OP_1NEGATE << BTC::OP_NOP << BTC::OP_RESERVED << BTC::OP_1 << BTC::OP_16 << "1" << "2" << "chancellor"
|
96
96
|
script.chunks.map{|c| c.interpreted_data }.must_equal ["", "\x81".b, nil, nil, "\x01".b, "\x10".b, "1", "2", "chancellor"]
|
97
97
|
script.chunks.map{|c| c.pushdata }.must_equal ["", nil, nil, nil, nil, nil, "1", "2", "chancellor"]
|
98
98
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,22 +5,22 @@ require_relative '../lib/btcruby'
|
|
5
5
|
require_relative '../lib/btcruby/extensions'
|
6
6
|
|
7
7
|
# So every test can access classes directly without prefixing them with BTC::
|
8
|
-
include BTC
|
8
|
+
#include BTC
|
9
9
|
|
10
10
|
# Script helper used by transaction_spec and script_interpreter_spec
|
11
11
|
FLAGS_MAP = {
|
12
|
-
"" => ScriptFlags::SCRIPT_VERIFY_NONE,
|
13
|
-
"NONE" => ScriptFlags::SCRIPT_VERIFY_NONE,
|
14
|
-
"P2SH" => ScriptFlags::SCRIPT_VERIFY_P2SH,
|
15
|
-
"STRICTENC" => ScriptFlags::SCRIPT_VERIFY_STRICTENC,
|
16
|
-
"DERSIG" => ScriptFlags::SCRIPT_VERIFY_DERSIG,
|
17
|
-
"LOW_S" => ScriptFlags::SCRIPT_VERIFY_LOW_S,
|
18
|
-
"NULLDUMMY" => ScriptFlags::SCRIPT_VERIFY_NULLDUMMY,
|
19
|
-
"SIGPUSHONLY" => ScriptFlags::SCRIPT_VERIFY_SIGPUSHONLY,
|
20
|
-
"MINIMALDATA" => ScriptFlags::SCRIPT_VERIFY_MINIMALDATA,
|
21
|
-
"DISCOURAGE_UPGRADABLE_NOPS" => ScriptFlags::SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
|
22
|
-
"CLEANSTACK" => ScriptFlags::SCRIPT_VERIFY_CLEANSTACK,
|
23
|
-
"CHECKLOCKTIMEVERIFY" => ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
|
12
|
+
"" => BTC::ScriptFlags::SCRIPT_VERIFY_NONE,
|
13
|
+
"NONE" => BTC::ScriptFlags::SCRIPT_VERIFY_NONE,
|
14
|
+
"P2SH" => BTC::ScriptFlags::SCRIPT_VERIFY_P2SH,
|
15
|
+
"STRICTENC" => BTC::ScriptFlags::SCRIPT_VERIFY_STRICTENC,
|
16
|
+
"DERSIG" => BTC::ScriptFlags::SCRIPT_VERIFY_DERSIG,
|
17
|
+
"LOW_S" => BTC::ScriptFlags::SCRIPT_VERIFY_LOW_S,
|
18
|
+
"NULLDUMMY" => BTC::ScriptFlags::SCRIPT_VERIFY_NULLDUMMY,
|
19
|
+
"SIGPUSHONLY" => BTC::ScriptFlags::SCRIPT_VERIFY_SIGPUSHONLY,
|
20
|
+
"MINIMALDATA" => BTC::ScriptFlags::SCRIPT_VERIFY_MINIMALDATA,
|
21
|
+
"DISCOURAGE_UPGRADABLE_NOPS" => BTC::ScriptFlags::SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
|
22
|
+
"CLEANSTACK" => BTC::ScriptFlags::SCRIPT_VERIFY_CLEANSTACK,
|
23
|
+
"CHECKLOCKTIMEVERIFY" => BTC::ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
|
24
24
|
}
|
25
25
|
|
26
26
|
def parse_script(json_script, expected_result = true)
|
@@ -33,7 +33,7 @@ def parse_script(json_script, expected_result = true)
|
|
33
33
|
oldsize = json_script.size
|
34
34
|
json_script.gsub!(/0x([0-9a-fA-F]+)\s+0x/, "0x\\1")
|
35
35
|
end
|
36
|
-
json_script.split(" ").inject(Script.new) do |parsed_script, x|
|
36
|
+
json_script.split(" ").inject(BTC::Script.new) do |parsed_script, x|
|
37
37
|
if x.size == 0
|
38
38
|
# Empty string, ignore.
|
39
39
|
parsed_script
|
@@ -41,25 +41,27 @@ def parse_script(json_script, expected_result = true)
|
|
41
41
|
# Number
|
42
42
|
n = x.to_i
|
43
43
|
if (n == -1) || (n >= 1 and n <= 16)
|
44
|
-
parsed_script << Opcode.opcode_for_small_integer(n)
|
44
|
+
parsed_script << BTC::Opcode.opcode_for_small_integer(n)
|
45
45
|
else
|
46
|
-
parsed_script << ScriptNumber.new(integer: n).data
|
46
|
+
parsed_script << BTC::ScriptNumber.new(integer: n).data
|
47
47
|
end
|
48
48
|
elsif x[0,2] == "0x"
|
49
49
|
# Raw hex data, inserted NOT pushed onto stack:
|
50
50
|
data = BTC.from_hex(x[2..-1])
|
51
|
-
Script.new(data: parsed_script.data + data)
|
51
|
+
BTC::Script.new(data: parsed_script.data + data)
|
52
52
|
elsif x =~ /^'.*'$/
|
53
53
|
# Single-quoted string, pushed as data.
|
54
54
|
parsed_script << x[1..-2]
|
55
55
|
else
|
56
56
|
# opcode, e.g. OP_ADD or ADD:
|
57
|
-
opcode = Opcode.opcode_for_name("OP_" + x)
|
58
|
-
opcode = Opcode.opcode_for_name(x) if opcode == OP_INVALIDOPCODE
|
57
|
+
opcode = BTC::Opcode.opcode_for_name("OP_" + x)
|
58
|
+
opcode = BTC::Opcode.opcode_for_name(x) if opcode == BTC::OP_INVALIDOPCODE
|
59
59
|
parsed_script << opcode
|
60
60
|
end
|
61
61
|
end
|
62
62
|
rescue => e
|
63
|
+
# puts e.backtrace.join("\n")
|
64
|
+
# raise "!!!!"
|
63
65
|
if expected_result
|
64
66
|
# puts "json_script = #{orig_string.inspect}"
|
65
67
|
# puts "json_script = #{json_script.inspect}"
|
@@ -76,14 +78,14 @@ def parse_flags(string)
|
|
76
78
|
end
|
77
79
|
|
78
80
|
def build_crediting_transaction(scriptPubKey)
|
79
|
-
txCredit = Transaction.new
|
80
|
-
txCredit.version = 1
|
81
|
-
txCredit.lock_time = 0
|
82
|
-
txCredit.add_input(TransactionInput.new(
|
81
|
+
txCredit = BTC::Transaction.new
|
82
|
+
txCredit.version = 1
|
83
|
+
txCredit.lock_time = 0
|
84
|
+
txCredit.add_input(BTC::TransactionInput.new(
|
83
85
|
previous_hash: nil,
|
84
|
-
coinbase_data: (Script.new << ScriptNumber.new(integer:0) << ScriptNumber.new(integer:0)).data
|
86
|
+
coinbase_data: (BTC::Script.new << BTC::ScriptNumber.new(integer:0) << BTC::ScriptNumber.new(integer:0)).data
|
85
87
|
))
|
86
|
-
txCredit.add_output(TransactionOutput.new(
|
88
|
+
txCredit.add_output(BTC::TransactionOutput.new(
|
87
89
|
script: scriptPubKey,
|
88
90
|
value: 0
|
89
91
|
))
|
@@ -91,16 +93,16 @@ def build_crediting_transaction(scriptPubKey)
|
|
91
93
|
end
|
92
94
|
|
93
95
|
def build_spending_transaction(scriptSig, txCredit)
|
94
|
-
txSpend = Transaction.new
|
95
|
-
txSpend.version = 1
|
96
|
-
txSpend.lock_time = 0
|
97
|
-
txSpend.add_input(TransactionInput.new(
|
96
|
+
txSpend = BTC::Transaction.new
|
97
|
+
txSpend.version = 1
|
98
|
+
txSpend.lock_time = 0
|
99
|
+
txSpend.add_input(BTC::TransactionInput.new(
|
98
100
|
previous_hash: txCredit.transaction_hash,
|
99
101
|
previous_index: 0,
|
100
102
|
signature_script: scriptSig
|
101
103
|
))
|
102
|
-
txSpend.add_output(TransactionOutput.new(
|
103
|
-
script: Script.new,
|
104
|
+
txSpend.add_output(BTC::TransactionOutput.new(
|
105
|
+
script: BTC::Script.new,
|
104
106
|
value: 0
|
105
107
|
))
|
106
108
|
txSpend
|