btcruby 1.6 → 1.7

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: 217d2c55943bb88f2a02a77774574a82f345845f
4
- data.tar.gz: 9e74dfbf5e332e4fbda8cca3c3d6f1dd8962ac1a
3
+ metadata.gz: ffee95a66b5f287235a52944ff6f92e3335b22df
4
+ data.tar.gz: 550a1d62ecea9b95a15294f3b65477566c9baa90
5
5
  SHA512:
6
- metadata.gz: 509d5068a72d3e04ea612a92348bc7edd9929aed0acc87e55dc10866c24294e6d2f84fb26d0d54f2c18ab19ff09cd6cc0bc267735cb6694be6fbd5e3d757dda0
7
- data.tar.gz: 39b60fbdd30baf9ffaa08005d07ac2d767c3f85a8e0c5761380e369ebeae96092bcf9d7d7f1406f4c5a30f63ef3694e1598980efacada1e23e9484aff6c2a40a
6
+ metadata.gz: 517e12449e58e4866826c6f28230f854bc26b04e788f9d7d3bd864dd15aeb60ccc948da70a4c2d69bfdeef84bd1475f5ac5d78aee599ea67ba52674a30703cb0
7
+ data.tar.gz: e175176b5a85c1eb40e17134179bf29acc04b2077228c26089b308321d17f94e29960a4f66f0c216e124c108173e40f353125b2e596cef0117687f82098b31bb
@@ -2,6 +2,12 @@
2
2
  BTCRuby Release Notes
3
3
  =====================
4
4
 
5
+ 1.7 (September 28, 2017)
6
+ -------------------------
7
+
8
+ * Various bugfixes
9
+ * WIP on API for the versioned scripts
10
+
5
11
  1.6 (January 15, 2015)
6
12
  -------------------------
7
13
 
@@ -21,7 +21,7 @@
21
21
  #
22
22
  # address = BTC::PublicKeyAddress.new(hash: hash)
23
23
  #
24
- # 3. To convert address to its Base68Check format call to_s:
24
+ # 3. To convert address to its Base58Check format call to_s:
25
25
  #
26
26
  # string = address.to_s
27
27
  #
@@ -24,7 +24,7 @@ module BTC
24
24
 
25
25
  PUBLIC_MAINNET_VERSION = 0x0488B21E # xpub
26
26
  PRIVATE_MAINNET_VERSION = 0x0488ADE4 # xprv
27
- PUBLIC_TESNET_VERSION = 0x043587CF # tpub
27
+ PUBLIC_TESTNET_VERSION = 0x043587CF # tpub
28
28
  PRIVATE_TESTNET_VERSION = 0x04358394 # tprv
29
29
 
30
30
  # Instance of BTC::Key that is a "head" of this keychain.
@@ -107,9 +107,9 @@ module BTC
107
107
 
108
108
  def key
109
109
  @key ||= if @private_key
110
- BTC::Key.new(private_key: @private_key, public_key_compressed: true)
110
+ BTC::Key.new(private_key: @private_key, public_key_compressed: true, network: @network)
111
111
  else
112
- BTC::Key.new(public_key: @public_key)
112
+ BTC::Key.new(public_key: @public_key, network: @network)
113
113
  end
114
114
  end
115
115
 
@@ -127,7 +127,7 @@ module BTC
127
127
 
128
128
  def extended_public_key
129
129
  @extended_public_key ||= begin
130
- prefix = _extended_key_prefix(mainnet? ? PUBLIC_MAINNET_VERSION : PUBLIC_TESNET_VERSION)
130
+ prefix = _extended_key_prefix(mainnet? ? PUBLIC_MAINNET_VERSION : PUBLIC_TESTNET_VERSION)
131
131
  BTC::Base58.base58check_from_data(prefix + @public_key)
132
132
  end
133
133
  end
@@ -205,7 +205,7 @@ module BTC
205
205
  elsif _components
206
206
  init_with_components(*_components)
207
207
  else
208
- raise ArgumentError, "Either seed or an extended " if !private_key && !public_key
208
+ raise ArgumentError, "Either seed or an extended key must be provided"
209
209
  end
210
210
  end
211
211
 
@@ -251,13 +251,13 @@ module BTC
251
251
  @network = Network.testnet
252
252
  end
253
253
 
254
- elsif version == PUBLIC_MAINNET_VERSION || version == PUBLIC_TESNET_VERSION
254
+ elsif version == PUBLIC_MAINNET_VERSION || version == PUBLIC_TESTNET_VERSION
255
255
  # Should have a 33-byte public key with non-zero first byte.
256
256
  if keyprefix == 0x00
257
257
  raise BTCError, "Extended public key must have non-zero first byte (received #{keyprefix})"
258
258
  end
259
259
  @public_key = xkeydata[45, 33]
260
- if version == PUBLIC_TESNET_VERSION
260
+ if version == PUBLIC_TESTNET_VERSION
261
261
  @network = Network.testnet
262
262
  end
263
263
  else
@@ -452,25 +452,25 @@ module BTC
452
452
  end
453
453
  end
454
454
  end
455
-
455
+
456
456
  # BIP44 Support
457
-
457
+
458
458
  def bip44_keychain(network: Network.mainnet)
459
459
  network_index = network.mainnet? ? 0 : 1
460
460
  derived_keychain(44, hardened: true).derived_keychain(network_index, hardened: true)
461
461
  end
462
-
462
+
463
463
  def bip44_account_keychain(account_index)
464
464
  derived_keychain(account_index, hardened: true)
465
465
  end
466
-
466
+
467
467
  def bip44_external_keychain
468
468
  derived_keychain(0, hardened: false)
469
469
  end
470
-
470
+
471
471
  def bip44_internal_keychain
472
472
  derived_keychain(1, hardened: false)
473
473
  end
474
-
474
+
475
475
  end # Keychain
476
476
  end # BTC
@@ -1,4 +1,4 @@
1
- # BTC::Mnemonic implements BIP44: mnemonic-based hierarchical deterministic wallets.
1
+ # BTC::Mnemonic implements BIP39: mnemonic-based hierarchical deterministic wallets.
2
2
  # Currently only supports restoring keychain from words. Generating sentence.
3
3
  require 'openssl'
4
4
  require 'openssl/digest'
@@ -89,6 +89,14 @@ module BTC
89
89
  public_key_script? ||
90
90
  standard_op_return_script?
91
91
  end
92
+
93
+ # Returns true if this is an output script wrapped in a versioned pushdata for segwit softfork.
94
+ def versioned_script?
95
+ return chunks.size == 1 &&
96
+ chunks[0].pushdata? &&
97
+ chunks[0].canonical? &&
98
+ chunks[0].pushdata.bytesize > 2
99
+ end
92
100
 
93
101
  # Returns true if the script is a pay-to-pubkey script:
94
102
  # "<pubkey> OP_CHECKSIG"
@@ -248,7 +256,7 @@ module BTC
248
256
  # and a new script instance is returned.
249
257
  def without_dropped_prefix_data
250
258
  if dropped_prefix_data
251
- return self.class.new << @chunks[2..-1]
259
+ return Script.new << @chunks[2..-1]
252
260
  end
253
261
  self
254
262
  end
@@ -288,7 +296,7 @@ module BTC
288
296
 
289
297
  # Complete copy of a script.
290
298
  def dup
291
- self.class.new(data: self.data)
299
+ Script.new(data: self.data)
292
300
  end
293
301
 
294
302
  def ==(other)
@@ -324,7 +332,7 @@ module BTC
324
332
  # Wraps the recipient into an output P2SH script
325
333
  # (OP_HASH160 <20-byte hash of the recipient> OP_EQUAL).
326
334
  def p2sh_script
327
- self.class.new << OP_HASH160 << BTC.hash160(self.data) << OP_EQUAL
335
+ Script.new << OP_HASH160 << BTC.hash160(self.data) << OP_EQUAL
328
336
  end
329
337
 
330
338
 
@@ -336,18 +344,18 @@ module BTC
336
344
  def simulated_signature_script(strict: true)
337
345
  if public_key_hash_script?
338
346
  # assuming non-compressed pubkeys to be conservative
339
- return self.class.new << Script.simulated_signature(hashtype: SIGHASH_ALL) << Script.simulated_uncompressed_pubkey
347
+ return Script.new << Script.simulated_signature(hashtype: SIGHASH_ALL) << Script.simulated_uncompressed_pubkey
340
348
 
341
349
  elsif public_key_script?
342
- return self.class.new << Script.simulated_signature(hashtype: SIGHASH_ALL)
350
+ return Script.new << Script.simulated_signature(hashtype: SIGHASH_ALL)
343
351
 
344
352
  elsif script_hash_script? && !strict
345
353
  # This is a wild approximation, but works well if most p2sh scripts are 2-of-3 multisig scripts.
346
354
  # If you have a very particular smart contract scheme you should not use TransactionBuilder which estimates fees this way.
347
- return self.class.new << OP_0 << [Script.simulated_signature(hashtype: SIGHASH_ALL)]*2 << Script.simulated_multisig_script(2,3).data
355
+ return Script.new << OP_0 << [Script.simulated_signature(hashtype: SIGHASH_ALL)]*2 << Script.simulated_multisig_script(2,3).data
348
356
 
349
357
  elsif multisig_script?
350
- return self.class.new << OP_0 << [Script.simulated_signature(hashtype: SIGHASH_ALL)]*self.multisig_signatures_required
358
+ return Script.new << OP_0 << [Script.simulated_signature(hashtype: SIGHASH_ALL)]*self.multisig_signatures_required
351
359
  else
352
360
  return nil
353
361
  end
@@ -463,7 +471,7 @@ module BTC
463
471
 
464
472
  # Same arguments as with Array#[].
465
473
  def subscript(*args)
466
- self.class.new << chunks[*args]
474
+ Script.new << chunks[*args]
467
475
  end
468
476
  alias_method :[], :subscript
469
477
 
@@ -478,7 +486,7 @@ module BTC
478
486
  subscriptsize = subscript.chunks.size
479
487
  buf = []
480
488
  i = 0
481
- result = self.class.new
489
+ result = Script.new
482
490
  chunks.each do |chunk|
483
491
  if chunk == subscript.chunks[i]
484
492
  buf << chunk
@@ -36,7 +36,7 @@ module BTC
36
36
  # (required if the scripts use signature-checking opcodes).
37
37
  # Checker can be transaction checker or block checker
38
38
  def initialize(flags: SCRIPT_VERIFY_NONE,
39
- extensions: nil,
39
+ extensions: nil,
40
40
  signature_checker: nil,
41
41
  raise_on_failure: false,
42
42
  max_pushdata_size: MAX_SCRIPT_ELEMENT_SIZE,
@@ -144,8 +144,8 @@ module BTC
144
144
  @altstack = []
145
145
  @run_script_chunks = script.chunks.to_a.dup # can be modified by `insert_script`
146
146
 
147
- number_zero = ScriptNumber.new(integer: 0)
148
- number_one = ScriptNumber.new(integer: 1)
147
+ number_zero = BTC::ScriptNumber.new(integer: 0)
148
+ number_one = BTC::ScriptNumber.new(integer: 1)
149
149
  zero_value = "".b
150
150
  false_value = "".b
151
151
  true_value = "\x01".b
@@ -216,7 +216,7 @@ module BTC
216
216
  case opcode
217
217
  when OP_1NEGATE, OP_1..OP_16
218
218
  # ( -- value)
219
- num = ScriptNumber.new(integer: opcode - (OP_1 - 1))
219
+ num = BTC::ScriptNumber.new(integer: opcode - (OP_1 - 1))
220
220
  stack_push(num.data)
221
221
  # The result of these opcodes should always be the minimal way to push the data
222
222
  # they push, so no need for a CheckMinimalPush here.
@@ -408,7 +408,7 @@ module BTC
408
408
 
409
409
  when OP_DEPTH
410
410
  # -- stacksize
411
- sn = ScriptNumber.new(integer: @stack.size)
411
+ sn = BTC::ScriptNumber.new(integer: @stack.size)
412
412
  stack_push(sn.data)
413
413
 
414
414
  when OP_DROP
@@ -489,7 +489,7 @@ module BTC
489
489
  if @stack.size < 1
490
490
  return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
491
491
  end
492
- sn = ScriptNumber.new(integer: @stack.last.size)
492
+ sn = BTC::ScriptNumber.new(integer: @stack.last.size)
493
493
  stack_push(sn.data)
494
494
 
495
495
 
@@ -548,9 +548,9 @@ module BTC
548
548
  when OP_ABS
549
549
  bn = -bn if bn < 0
550
550
  when OP_NOT
551
- bn = ScriptNumber.new(boolean: (bn == 0))
551
+ bn = BTC::ScriptNumber.new(boolean: (bn == 0))
552
552
  when OP_0NOTEQUAL
553
- bn = ScriptNumber.new(boolean: (bn != 0))
553
+ bn = BTC::ScriptNumber.new(boolean: (bn != 0))
554
554
  else
555
555
  raise "invalid opcode"
556
556
  end
@@ -566,7 +566,7 @@ module BTC
566
566
 
567
567
  bn1 = cast_to_number(@stack[-2])
568
568
  bn2 = cast_to_number(@stack[-1])
569
- bn = ScriptNumber.new(integer: 0)
569
+ bn = BTC::ScriptNumber.new(integer: 0)
570
570
 
571
571
  case opcode
572
572
  when OP_ADD
@@ -574,21 +574,21 @@ module BTC
574
574
  when OP_SUB
575
575
  bn = bn1 - bn2
576
576
  when OP_BOOLAND
577
- bn = ScriptNumber.new(boolean: ((bn1 != 0) && (bn2 != 0)))
577
+ bn = BTC::ScriptNumber.new(boolean: ((bn1 != 0) && (bn2 != 0)))
578
578
  when OP_BOOLOR
579
- bn = ScriptNumber.new(boolean: ((bn1 != 0) || (bn2 != 0)))
579
+ bn = BTC::ScriptNumber.new(boolean: ((bn1 != 0) || (bn2 != 0)))
580
580
  when OP_NUMEQUAL, OP_NUMEQUALVERIFY
581
- bn = ScriptNumber.new(boolean: (bn1 == bn2))
581
+ bn = BTC::ScriptNumber.new(boolean: (bn1 == bn2))
582
582
  when OP_NUMNOTEQUAL
583
- bn = ScriptNumber.new(boolean: (bn1 != bn2))
583
+ bn = BTC::ScriptNumber.new(boolean: (bn1 != bn2))
584
584
  when OP_LESSTHAN
585
- bn = ScriptNumber.new(boolean: (bn1 < bn2))
585
+ bn = BTC::ScriptNumber.new(boolean: (bn1 < bn2))
586
586
  when OP_GREATERTHAN
587
- bn = ScriptNumber.new(boolean: (bn1 > bn2))
587
+ bn = BTC::ScriptNumber.new(boolean: (bn1 > bn2))
588
588
  when OP_LESSTHANOREQUAL
589
- bn = ScriptNumber.new(boolean: (bn1 <= bn2))
589
+ bn = BTC::ScriptNumber.new(boolean: (bn1 <= bn2))
590
590
  when OP_GREATERTHANOREQUAL
591
- bn = ScriptNumber.new(boolean: (bn1 >= bn2))
591
+ bn = BTC::ScriptNumber.new(boolean: (bn1 >= bn2))
592
592
  when OP_MIN
593
593
  bn = (bn1 < bn2 ? bn1 : bn2)
594
594
  when OP_MAX
@@ -815,7 +815,7 @@ module BTC
815
815
  end
816
816
 
817
817
  return true
818
- rescue ScriptNumberError => e
818
+ rescue BTC::ScriptNumberError => e
819
819
  return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
820
820
  end # run_script
821
821
 
@@ -914,7 +914,7 @@ module BTC
914
914
  def cast_to_number(data,
915
915
  require_minimal: flag?(SCRIPT_VERIFY_MINIMALDATA),
916
916
  max_size: @integer_max_size)
917
- ScriptNumber.new(data: data, require_minimal: require_minimal, max_size: max_size)
917
+ BTC::ScriptNumber.new(data: data, require_minimal: require_minimal, max_size: max_size)
918
918
  end
919
919
 
920
920
  def cast_to_bool(data)
@@ -0,0 +1,54 @@
1
+ module BTC
2
+ class ScriptVersion
3
+ VERSION_DEFAULT = 0
4
+ VERSION_P2SH = 1
5
+
6
+ attr_reader :version # binary string containing the version
7
+ attr_reader :sighash_version
8
+
9
+ def initialize(version)
10
+ @version = version
11
+ end
12
+
13
+ # Returns a matching signature hash version for the given script version.
14
+ # All currently known script versions use sighash version 1.
15
+ def sighash_version
16
+ return 1
17
+ end
18
+
19
+ # Returns true if version is known.
20
+ # Unknown versions are supported too, but scripts are not even parsed and interpreted as "anyone can spend".
21
+ def known?
22
+ default? ||
23
+ p2sh?
24
+ end
25
+
26
+ def default?
27
+ @version == VERSION_DEFAULT
28
+ end
29
+
30
+ def p2sh?
31
+ @version == VERSION_P2SH
32
+ end
33
+
34
+ def name
35
+ case version
36
+ when VERSION_DEFAULT
37
+ "Default script"
38
+ when VERSION_P2SH
39
+ "P2SH v1"
40
+ else
41
+ "Unknown script version"
42
+ end
43
+ end
44
+
45
+ def to_i
46
+ @version
47
+ end
48
+
49
+ def to_s
50
+ "v#{@version} (#{name})"
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,64 @@
1
+ module BTC
2
+ # Versioned script is a wrapper around a regular script with a version prefix.
3
+ # Note that we support version of any length, but do not parse and interpret unknown versions.
4
+ class VersionedScript
5
+
6
+ attr_reader :version # Integer
7
+ attr_reader :data # Raw data representing script wrapped in VersionedScript. For 256-bit P2SH it's just a hash, not a script.
8
+ attr_reader :wrapper_script # BTC::Script that wraps version + data
9
+ attr_reader :script_version # BTC::ScriptVersion
10
+ attr_reader :inner_script # BTC::Script derived from data, if it makes sense for the given version.
11
+
12
+ # Initializers:
13
+ # - `VersionedScript.new(wrapper_script:)` that wraps the version and inner script data.
14
+ # - `VersionedScript.new(version:, data:)` where version is one of ScriptVersion::VERSION_* and data is a raw inner script data (hash for p2sh256).
15
+ # - `VersionedScript.new(p2sh_redeem_script:)` creates a versioned script with p2sh hash of the redeem script.
16
+ def initialize(wrapper_script: nil,
17
+ version: nil, data: nil,
18
+ script: nil,
19
+ p2sh_redeem_script: nil,
20
+ )
21
+ if wrapper_script
22
+ if !wrapper_script.versioned_script?
23
+ raise ArgumentError, "Script is not a canonical versioned script with minimal pushdata encoding"
24
+ end
25
+ @wrapper_script = wrapper_script
26
+ fulldata = BTC::Data.ensure_binary_encoding(wrapper_script.chunks.first.pushdata)
27
+ @version = fulldata.bytes[0]
28
+ @data = fulldata[1..-1]
29
+ elsif script
30
+ @version = ScriptVersion::VERSION_DEFAULT
31
+ @data = script.data
32
+ elsif p2sh_redeem_script
33
+ @version = ScriptVersion::VERSION_P2SH256
34
+ @data = BTC.hash256(p2sh_redeem_script.data)
35
+ else
36
+ @version = version or raise ArgumentError, "Version is missing"
37
+ @data = data
38
+ end
39
+ end
40
+
41
+ def wrapper_script
42
+ @wrapper_script ||= BTC::Script.new << (@version.chr.b + @data)
43
+ end
44
+
45
+ # Returns inner BTC::Script if it's a default script
46
+ def inner_script
47
+ if script_version.default?
48
+ BTC::Script.new(data: data)
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
54
+ def script_version
55
+ @script_version ||= ScriptVersion.new(@version)
56
+ end
57
+
58
+ def known_version?
59
+ script_version.known?
60
+ end
61
+
62
+ end
63
+ end
64
+
@@ -10,8 +10,10 @@ module BTC
10
10
 
11
11
  ffi_lib 'secp256k1'
12
12
 
13
- SECP256K1_CONTEXT_VERIFY = (1 << 0)
14
- SECP256K1_CONTEXT_SIGN = (1 << 1)
13
+ SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0)
14
+ SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8)
15
+ SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9)
16
+ SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
15
17
 
16
18
  # Note: this struct is opaque, but public. Its size will eventually be guaranteed.
17
19
  # See https://github.com/bitcoin/secp256k1/issues/288
@@ -42,7 +44,7 @@ module BTC
42
44
  privkey_buf = FFI::MemoryPointer.new(:uchar, privkey.bytesize)
43
45
  privkey_buf.put_bytes(0, privkey)
44
46
 
45
- if secp256k1_ecdsa_sign(ctx, hash_buf, sig.pointer, privkey_buf, nil, nil) == 1
47
+ if secp256k1_ecdsa_sign(ctx, sig.pointer, hash_buf, privkey_buf, nil, nil) == 1
46
48
  # Serialize an ECDSA signature in DER format.
47
49
  bufsize = 72
48
50
  output_pointer = FFI::MemoryPointer.new(:uint8, bufsize)
@@ -60,6 +60,10 @@ module BTC
60
60
  # Default is Transaction::DEFAULT_FEE_RATE
61
61
  attr_accessor :fee_rate
62
62
 
63
+ # Miner's fee for this transaction.
64
+ # If `fee` is not nil, fee_rate is ignored and transaction uses the specified fee.
65
+ attr_accessor :fee
66
+
63
67
  # Minimum amount of change below which transaction is not composed.
64
68
  # If change amount is non-zero and below this value, more unspent outputs are used.
65
69
  # If change amount is zero, change output is not even created and this attribute is not used.
@@ -92,10 +96,10 @@ module BTC
92
96
  # A total size of all outputs in bytes (including change output).
93
97
  attr_reader :outputs_size
94
98
 
95
-
96
99
  # Implementation of the attributes declared above
97
100
  # ===============================================
98
101
 
102
+
99
103
  def network
100
104
  @network ||= Network.default
101
105
  end
@@ -223,7 +227,7 @@ module BTC
223
227
 
224
228
  # Check if inputs cover the fees
225
229
  if result.outputs_amount < 0
226
- raise InsufficientFundsError
230
+ raise InsufficientFundsError.new(result)
227
231
  end
228
232
 
229
233
  # Warn if the output amount is relatively small.
@@ -282,7 +286,7 @@ module BTC
282
286
 
283
287
  while true
284
288
  if (sorted_utxos.size + mandatory_utxos.size) == 0
285
- raise InsufficientFundsError
289
+ raise InsufficientFundsError.new(result)
286
290
  end
287
291
 
288
292
  utxo = nil
@@ -361,7 +365,7 @@ module BTC
361
365
  else
362
366
  # Change is negative, we need more funds for this transaction.
363
367
  # Try adding more utxos on the next cycle.
364
-
368
+ result.fee = fee
365
369
  end
366
370
 
367
371
  end # if inputs_amount >= outputs_amount
@@ -374,6 +378,8 @@ module BTC
374
378
  # Helper to compute total fee for a given transaction.
375
379
  # Simulates signatures to estimate final size.
376
380
  def compute_fee_for_transaction(tx, fee_rate)
381
+ # Return mining fee if set manually
382
+ return fee if fee
377
383
  # Compute fees for this tx by composing a tx with properly sized dummy signatures.
378
384
  simulated_tx = tx.dup
379
385
  simulated_tx.inputs.each do |txin|
@@ -518,4 +524,3 @@ if $0 == __FILE__
518
524
 
519
525
 
520
526
  end
521
-
@@ -10,6 +10,11 @@ module BTC
10
10
  class MissingUnspentOutputsError < Error; end
11
11
 
12
12
  # Unspent outputs are not sufficient to build the transaction.
13
- class InsufficientFundsError < Error; end
13
+ class InsufficientFundsError < Error
14
+ attr_accessor :result
15
+ def initialize(result = nil)
16
+ @result = result
17
+ end
18
+ end
14
19
  end
15
20
  end
@@ -1,3 +1,3 @@
1
1
  module BTC
2
- VERSION = "1.6".freeze
2
+ VERSION = "1.7".freeze
3
3
  end
@@ -14,7 +14,6 @@ describe BTC::CurrencyFormatter do
14
14
  fm.string_from_number(42000*BTC::COIN + BTC::COIN/2).must_equal("42000.5")
15
15
 
16
16
  fm.number_from_string("1").must_equal 1*BTC::COIN
17
- fm.number_from_string("1.").must_equal 1*BTC::COIN
18
17
  fm.number_from_string("1.0").must_equal 1*BTC::COIN
19
18
  fm.number_from_string("42").must_equal 42*BTC::COIN
20
19
  fm.number_from_string("42.123").must_equal 42*BTC::COIN + 12300000
@@ -35,7 +34,6 @@ describe BTC::CurrencyFormatter do
35
34
  fm.string_from_number(42000*BTC::COIN + BTC::COIN/2).must_equal("42000.50000000")
36
35
 
37
36
  fm.number_from_string("1").must_equal 1*BTC::COIN
38
- fm.number_from_string("1.").must_equal 1*BTC::COIN
39
37
  fm.number_from_string("1.0").must_equal 1*BTC::COIN
40
38
  fm.number_from_string("42").must_equal 42*BTC::COIN
41
39
  fm.number_from_string("42.123").must_equal 42*BTC::COIN + 12300000
@@ -258,4 +258,9 @@ describe BTC::Keychain do
258
258
  m0pub.extended_public_key.must_equal "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
259
259
  m0pub.extended_private_key.must_equal nil
260
260
  end
261
+ it "should raise the ArgumentError when arguments are not passed" do
262
+ assert_raises ArgumentError do
263
+ BTC::Keychain.new
264
+ end
265
+ end
261
266
  end
@@ -22,6 +22,10 @@ describe BTC::ScriptNumber do
22
22
  BTC::ScriptNumber.new(data: "\x01").to_i.must_equal 1
23
23
  end
24
24
 
25
+ it "should parse 0x27 as 39" do
26
+ BTC::ScriptNumber.new(data: "\x27").to_i.must_equal 39
27
+ end
28
+
25
29
  it "should parse 0xff as -127" do
26
30
  BTC::ScriptNumber.new(data: "\xff").to_i.must_equal -127
27
31
  end
@@ -9,22 +9,34 @@ describe BTC::Secp256k1 do
9
9
  sig.to_hex.must_equal sighex
10
10
  end
11
11
 
12
- it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979" do
12
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 01" do
13
13
  verify_rfc6979_signature("cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
14
14
  "sample",
15
15
  "3045022100af340daf02cc15c8d5d08d7735dfe6b98a474ed373bdb5fbecf7571be52b384202205009fb27f37034a9b24b707b7c6b79ca23ddef9e25f7282e8a797efe53a8f124")
16
+ end
17
+
18
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 02" do
16
19
  verify_rfc6979_signature("0000000000000000000000000000000000000000000000000000000000000001",
17
20
  "Satoshi Nakamoto",
18
21
  "3045022100934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d802202442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5")
22
+ end
23
+
24
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 03" do
19
25
  verify_rfc6979_signature("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
20
26
  "Satoshi Nakamoto",
21
27
  "3045022100fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d002206b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5")
28
+ end
29
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 04" do
22
30
  verify_rfc6979_signature("f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181",
23
31
  "Alan Turing",
24
32
  "304402207063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c022058dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea")
33
+ end
34
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 05" do
25
35
  verify_rfc6979_signature("0000000000000000000000000000000000000000000000000000000000000001",
26
36
  "All those moments will be lost in time, like tears in rain. Time to die...",
27
37
  "30450221008600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b0220547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21")
38
+ end
39
+ it "should produce deterministic ECDSA signatures Bitcoin-canonical using nonce from RFC6979 06" do
28
40
  verify_rfc6979_signature("e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2",
29
41
  "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!",
30
42
  "3045022100b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b0220279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6")
@@ -68,6 +68,12 @@ describe BTC::TransactionBuilder do
68
68
  result.fee.must_be :<, 0.01 * BTC::COIN
69
69
  end
70
70
 
71
+ it "should be able to set mining fee" do
72
+ @builder.fee =50690
73
+ result = @builder.build()
74
+ result.fee.must_equal 50690
75
+ end
76
+
71
77
  it "should have valid amounts" do
72
78
  result = @builder.build
73
79
  result.inputs_amount.must_equal mock_utxos.inject(0){|sum, out| sum + out.value}
@@ -190,6 +196,12 @@ describe BTC::TransactionBuilder do
190
196
  result.fee.must_be :<, 0.01 * BTC::COIN
191
197
  end
192
198
 
199
+ it "should be able to set mining fee" do
200
+ @builder.fee =50690
201
+ result = @builder.build()
202
+ result.fee.must_equal 50690
203
+ end
204
+
193
205
  it "should have valid amounts" do
194
206
  result = @builder.build
195
207
  result.inputs_amount.must_equal 11*1000_00
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.6'
4
+ version: '1.7'
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: 2016-01-15 00:00:00.000000000 Z
12
+ date: 2017-09-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -115,10 +115,12 @@ files:
115
115
  - lib/btcruby/script/script_interpreter.rb
116
116
  - lib/btcruby/script/script_interpreter_extension.rb
117
117
  - lib/btcruby/script/script_number.rb
118
+ - lib/btcruby/script/script_version.rb
118
119
  - lib/btcruby/script/signature_checker.rb
119
120
  - lib/btcruby/script/signature_hashtype.rb
120
121
  - lib/btcruby/script/test_signature_checker.rb
121
122
  - lib/btcruby/script/transaction_signature_checker.rb
123
+ - lib/btcruby/script/versioned_script.rb
122
124
  - lib/btcruby/secp256k1.rb
123
125
  - lib/btcruby/ssss.rb
124
126
  - lib/btcruby/transaction.rb