tapyrus 0.1.0 → 0.2.0

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -14
  3. data/exe/tapyrusrbd +2 -2
  4. data/lib/openassets/util.rb +2 -4
  5. data/lib/schnorr.rb +83 -0
  6. data/lib/schnorr/signature.rb +38 -0
  7. data/lib/tapyrus.rb +9 -11
  8. data/lib/tapyrus/block.rb +1 -32
  9. data/lib/tapyrus/block_header.rb +7 -6
  10. data/lib/tapyrus/chain_params.rb +13 -26
  11. data/lib/tapyrus/chainparams/{testnet.yml → dev.yml} +7 -9
  12. data/lib/tapyrus/chainparams/{mainnet.yml → prod.yml} +7 -10
  13. data/lib/tapyrus/constants.rb +12 -34
  14. data/lib/tapyrus/ext.rb +5 -0
  15. data/lib/tapyrus/ext/json_parser.rb +47 -0
  16. data/lib/tapyrus/ext_key.rb +5 -10
  17. data/lib/tapyrus/key.rb +57 -29
  18. data/lib/tapyrus/message.rb +2 -2
  19. data/lib/tapyrus/message/base.rb +1 -0
  20. data/lib/tapyrus/message/block.rb +3 -3
  21. data/lib/tapyrus/message/cmpct_block.rb +3 -5
  22. data/lib/tapyrus/message/tx.rb +2 -2
  23. data/lib/tapyrus/network/peer.rb +1 -15
  24. data/lib/tapyrus/node/cli.rb +15 -11
  25. data/lib/tapyrus/node/configuration.rb +1 -1
  26. data/lib/tapyrus/node/spv.rb +1 -1
  27. data/lib/tapyrus/opcodes.rb +5 -0
  28. data/lib/tapyrus/out_point.rb +1 -1
  29. data/lib/tapyrus/rpc/request_handler.rb +3 -3
  30. data/lib/tapyrus/rpc/tapyrus_core_client.rb +17 -15
  31. data/lib/tapyrus/script/color.rb +79 -0
  32. data/lib/tapyrus/script/multisig.rb +0 -27
  33. data/lib/tapyrus/script/script.rb +74 -89
  34. data/lib/tapyrus/script/script_error.rb +8 -14
  35. data/lib/tapyrus/script/script_interpreter.rb +65 -86
  36. data/lib/tapyrus/script/tx_checker.rb +16 -4
  37. data/lib/tapyrus/secp256k1.rb +1 -0
  38. data/lib/tapyrus/secp256k1/rfc6979.rb +43 -0
  39. data/lib/tapyrus/secp256k1/ruby.rb +5 -31
  40. data/lib/tapyrus/store/chain_entry.rb +1 -0
  41. data/lib/tapyrus/tx.rb +18 -160
  42. data/lib/tapyrus/tx_in.rb +4 -11
  43. data/lib/tapyrus/tx_out.rb +2 -1
  44. data/lib/tapyrus/util.rb +8 -0
  45. data/lib/tapyrus/validation.rb +1 -6
  46. data/lib/tapyrus/version.rb +1 -1
  47. data/lib/tapyrus/wallet/account.rb +1 -0
  48. data/lib/tapyrus/wallet/master_key.rb +1 -0
  49. data/tapyrusrb.gemspec +3 -3
  50. metadata +42 -39
  51. data/lib/tapyrus/chainparams/regtest.yml +0 -38
  52. data/lib/tapyrus/descriptor.rb +0 -147
  53. data/lib/tapyrus/script_witness.rb +0 -38
@@ -78,24 +78,18 @@ module Tapyrus
78
78
  'Witness version reserved for soft-fork upgrades'
79
79
  when SCRIPT_ERR_PUBKEYTYPE
80
80
  'Public key is neither compressed or uncompressed'
81
- when SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH
82
- 'Witness program has incorrect length'
83
- when SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY
84
- 'Witness program was passed an empty witness'
85
- when SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH
86
- 'Witness program hash mismatch'
87
- when SCRIPT_ERR_WITNESS_MALLEATED
88
- 'Witness requires empty scriptSig'
89
- when SCRIPT_ERR_WITNESS_MALLEATED_P2SH
90
- 'Witness requires only-redeemscript scriptSig'
91
- when SCRIPT_ERR_WITNESS_UNEXPECTED
92
- 'Witness provided for non-witness script'
93
- when SCRIPT_ERR_WITNESS_PUBKEYTYPE
94
- 'Using non-compressed keys in segwit'
95
81
  when SCRIPT_ERR_OP_CODESEPARATOR
96
82
  'Using OP_CODESEPARATOR in non-witness scrip'
97
83
  when SCRIPT_ERR_SIG_FINDANDDELETE
98
84
  'Signature is found in scriptCode'
85
+ when SCRIPT_ERR_OP_COLOR_UNEXPECTED
86
+ 'Unexpected OP_COLOR in script'
87
+ when SCRIPT_ERR_OP_COLOR_ID_INVALID
88
+ 'Invalid ColorId in script'
89
+ when SCRIPT_ERR_OP_COLOR_MULTIPLE
90
+ 'Multiple OP_COLOR found in script'
91
+ when SCRIPT_ERR_OP_COLOR_IN_BRANCH
92
+ 'OP_COLOR is not permitted in a script branch'
99
93
  when SCRIPT_ERR_UNKNOWN_ERROR, SCRIPT_ERR_ERROR_COUNT
100
94
  'unknown error'
101
95
  else
@@ -32,32 +32,21 @@ module Tapyrus
32
32
  # eval script
33
33
  # @param [Tapyrus::Script] script_sig a signature script (unlock script which data push only)
34
34
  # @param [Tapyrus::Script] script_pubkey a script pubkey (locking script)
35
- # @param [Tapyrus::ScriptWitness] witness a witness script
36
35
  # @return [Boolean] result
37
- def verify_script(script_sig, script_pubkey, witness = ScriptWitness.new)
36
+ def verify_script(script_sig, script_pubkey)
38
37
 
39
38
  return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?
40
39
 
41
40
  stack_copy = nil
42
- had_witness = false
43
41
 
44
- return false unless eval_script(script_sig, :base)
42
+ return false unless eval_script(script_sig, :base, false)
45
43
 
46
44
  stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)
47
45
 
48
- return false unless eval_script(script_pubkey, :base)
46
+ return false unless eval_script(script_pubkey, :base, false)
49
47
 
50
48
  return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)
51
49
 
52
- # Bare witness programs
53
- if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
54
- had_witness = true
55
- return set_error(SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
56
- version, program = script_pubkey.witness_data
57
- stack_copy = stack.dup
58
- return false unless verify_witness_program(witness, version, program)
59
- end
60
-
61
50
  # Additional validation for spend-to-script-hash transactions
62
51
  if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
63
52
  return set_error(SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.push_only?
@@ -69,18 +58,8 @@ module Tapyrus
69
58
  rescue Exception => e
70
59
  return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
71
60
  end
72
- return false unless eval_script(redeem_script, :base)
61
+ return false unless eval_script(redeem_script, :base, true)
73
62
  return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
74
-
75
- # P2SH witness program
76
- if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
77
- had_witness = true
78
- # The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
79
- return set_error(SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Tapyrus::Script.new << redeem_script.to_payload.bth)
80
-
81
- version, program = redeem_script.witness_data
82
- return false unless verify_witness_program(witness, version, program)
83
- end
84
63
  end
85
64
 
86
65
  # The CLEANSTACK check is only performed after potential P2SH evaluation,
@@ -93,11 +72,6 @@ module Tapyrus
93
72
  return set_error(SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
94
73
  end
95
74
 
96
- if flag?(SCRIPT_VERIFY_WITNESS)
97
- raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
98
- return set_error(SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
99
- end
100
-
101
75
  true
102
76
  end
103
77
 
@@ -106,45 +80,14 @@ module Tapyrus
106
80
  false
107
81
  end
108
82
 
109
- def verify_witness_program(witness, version, program)
110
- if version == 0
111
- if program.bytesize == 32
112
- return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY) if witness.stack.size == 0
113
- script_pubkey = Tapyrus::Script.parse_from_payload(witness.stack.last)
114
- @stack = witness.stack[0..-2].map{|w|w.bth}
115
- script_hash = Tapyrus.sha256(script_pubkey.to_payload)
116
- return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless script_hash == program
117
- elsif program.bytesize == 20
118
- return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless witness.stack.size == 2
119
- script_pubkey = Tapyrus::Script.to_p2pkh(program.bth)
120
- @stack = witness.stack.map{|w|w.bth}
121
- else
122
- return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)
123
- end
124
- elsif flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
125
- return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
126
- else
127
- return true # Higher version witness scripts return true for future softfork compatibility
128
- end
129
-
130
- stack.each do |s| # Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
131
- return set_error(SCRIPT_ERR_PUSH_SIZE) if s.htb.bytesize > MAX_SCRIPT_ELEMENT_SIZE
132
- end
133
-
134
- return false unless eval_script(script_pubkey, :witness_v0)
135
-
136
- return set_error(SCRIPT_ERR_EVAL_FALSE) unless stack.size == 1
137
- return set_error(SCRIPT_ERR_EVAL_FALSE) unless cast_to_bool(stack.last)
138
- true
139
- end
140
-
141
- def eval_script(script, sig_version)
83
+ def eval_script(script, sig_version, is_redeem_script)
142
84
  return set_error(SCRIPT_ERR_SCRIPT_SIZE) if script.size > MAX_SCRIPT_SIZE
143
85
  begin
144
86
  flow_stack = []
145
87
  alt_stack = []
146
88
  last_code_separator_index = 0
147
89
  op_count = 0
90
+ color_id = nil
148
91
 
149
92
  script.chunks.each_with_index do |c, index|
150
93
  need_exec = !flow_stack.include?(false)
@@ -209,7 +152,7 @@ module Tapyrus
209
152
  if need_exec
210
153
  return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
211
154
  value = pop_string.htb
212
- if sig_version == :witness_v0 && flag?(SCRIPT_VERIFY_MINIMALIF)
155
+ if flag?(SCRIPT_VERIFY_MINIMALIF)
213
156
  if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
214
157
  return set_error(SCRIPT_ERR_MINIMALIF)
215
158
  end
@@ -409,8 +352,8 @@ module Tapyrus
409
352
  return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
410
353
  subscript = tmp
411
354
  end
412
-
413
- return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
355
+ return false if (sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ?
356
+ !check_schnorr_signature_encoding(sig) : !check_ecdsa_signature_encoding(sig)) || !check_pubkey_encoding(pubkey)
414
357
 
415
358
  success = checker.check_sig(sig, pubkey, subscript, sig_version)
416
359
 
@@ -428,6 +371,19 @@ module Tapyrus
428
371
  return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
429
372
  end
430
373
  end
374
+ when OP_CHECKDATASIG, OP_CHECKDATASIGVERIFY
375
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
376
+ sig, msg, pubkey = pop_string(3)
377
+ # check signature encoding without hashtype byte
378
+ return false if (sig.htb.bytesize != (Tapyrus::Key::COMPACT_SIGNATURE_SIZE - 1) && !check_ecdsa_signature_encoding(sig, true)) || !check_pubkey_encoding(pubkey)
379
+ digest = Tapyrus.sha256(msg)
380
+ success = checker.verify_sig(sig, pubkey, digest)
381
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
382
+ push_int(success ? 1 : 0)
383
+ if opcode == OP_CHECKDATASIGVERIFY
384
+ stack.pop if success
385
+ return set_error(SCRIPT_ERR_CHECKDATASIGVERIFY) unless success
386
+ end
431
387
  when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
432
388
  return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
433
389
  pubkey_count = pop_int
@@ -463,10 +419,17 @@ module Tapyrus
463
419
  end
464
420
 
465
421
  success = true
422
+ current_sig_scheme = nil
466
423
  while success && sig_count > 0
467
424
  sig = sigs.pop
468
425
  pubkey = pubkeys.pop
469
- return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
426
+ sig_scheme = sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ? :schnorr : :ecdsa
427
+ current_sig_scheme = sig_scheme if current_sig_scheme.nil?
428
+
429
+ return false if (sig_scheme == :schnorr ? !check_schnorr_signature_encoding(sig) : !check_ecdsa_signature_encoding(sig)) || !check_pubkey_encoding(pubkey) # error already set.
430
+
431
+ return set_error(SCRIPT_ERR_MIXED_SCHEME_MULTISIG) unless sig_scheme == current_sig_scheme
432
+
470
433
  ok = checker.check_sig(sig, pubkey, subscript, sig_version)
471
434
  if ok
472
435
  sig_count -= 1
@@ -488,9 +451,8 @@ module Tapyrus
488
451
  # Unfortunately this is a potential source of mutability,
489
452
  # so optionally verify it is exactly equal to zero prior to removing it from the stack.
490
453
  return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
491
- if flag?(SCRIPT_VERIFY_NULLDUMMY) && stack[-1].size > 0
492
- return set_error(SCRIPT_ERR_SIG_NULLDUMMY)
493
- end
454
+ return set_error(SCRIPT_ERR_SIG_NULLDUMMY) if stack[-1].size > 0
455
+
494
456
  stack.pop
495
457
 
496
458
  push_int(success ? 1 : 0)
@@ -503,6 +465,25 @@ module Tapyrus
503
465
  end
504
466
  when OP_RETURN
505
467
  return set_error(SCRIPT_ERR_OP_RETURN)
468
+ when OP_COLOR
469
+ # Color id is not permitted in p2sh redeem script
470
+ return set_error(SCRIPT_ERR_OP_COLOR_UNEXPECTED) if is_redeem_script
471
+
472
+ # if Color id is already initialized this must be an extra
473
+ return set_error(SCRIPT_ERR_OP_COLOR_MULTIPLE) if color_id && color_id.type != Tapyrus::Color::TokenTypes::NONE
474
+
475
+ # color id is not allowed inside OP_IF
476
+ return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless flow_stack.empty?
477
+
478
+ # pop one stack element and verify that it exists
479
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size() < 1
480
+
481
+ color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
482
+
483
+ # check ColorIdentifier is valid
484
+ return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless color_id.valid?
485
+
486
+ stack.pop
506
487
  else
507
488
  return set_error(SCRIPT_ERR_BAD_OPCODE)
508
489
  end
@@ -586,20 +567,26 @@ module Tapyrus
586
567
  end
587
568
  end
588
569
 
589
- def check_signature_encoding(sig)
570
+ def check_ecdsa_signature_encoding(sig, data_sig = false)
590
571
  return true if sig.size.zero?
591
- if (flag?(SCRIPT_VERIFY_DERSIG) || flag?(SCRIPT_VERIFY_LOW_S) || flag?(SCRIPT_VERIFY_STRICTENC)) && !Key.valid_signature_encoding?(sig.htb)
572
+ if !Key.valid_signature_encoding?(sig.htb, data_sig)
592
573
  return set_error(SCRIPT_ERR_SIG_DER)
593
- elsif flag?(SCRIPT_VERIFY_LOW_S) && !low_der_signature?(sig)
574
+ elsif !low_der_signature?(sig, data_sig)
594
575
  return false
595
- elsif flag?(SCRIPT_VERIFY_STRICTENC) && !defined_hashtype_signature?(sig)
576
+ elsif !data_sig && !defined_hashtype_signature?(sig)
596
577
  return set_error(SCRIPT_ERR_SIG_HASHTYPE)
597
578
  end
598
579
  true
599
580
  end
600
581
 
601
- def low_der_signature?(sig)
602
- return set_error(SCRIPT_ERR_SIG_DER) unless Key.valid_signature_encoding?(sig.htb)
582
+ def check_schnorr_signature_encoding(sig, data_sig = false)
583
+ return false unless sig.htb.bytesize == (data_sig ? 64 : 65)
584
+ return set_error(SCRIPT_ERR_SIG_HASHTYPE) if !data_sig && !defined_hashtype_signature?(sig)
585
+ true
586
+ end
587
+
588
+ def low_der_signature?(sig, data_sig = false)
589
+ return set_error(SCRIPT_ERR_SIG_DER) unless Key.valid_signature_encoding?(sig.htb, data_sig)
603
590
  return set_error(SCRIPT_ERR_SIG_HIGH_S) unless Key.low_signature?(sig.htb)
604
591
  true
605
592
  end
@@ -609,20 +596,12 @@ module Tapyrus
609
596
  return false if sig.empty?
610
597
  s = sig.unpack('C*')
611
598
  hash_type = s[-1] & (~(SIGHASH_TYPE[:anyonecanpay]))
612
- hash_type &= (~(Tapyrus::SIGHASH_FORK_ID)) if Tapyrus.chain_params.fork_chain? # for fork coin.
613
599
  return false if hash_type < SIGHASH_TYPE[:all] || hash_type > SIGHASH_TYPE[:single]
614
600
  true
615
601
  end
616
602
 
617
- def check_pubkey_encoding(pubkey, sig_version)
618
- if flag?(SCRIPT_VERIFY_STRICTENC) && !Key.compress_or_uncompress_pubkey?(pubkey)
619
- return set_error(SCRIPT_ERR_PUBKEYTYPE)
620
- end
621
- # Only compressed keys are accepted in segwit
622
- if flag?(SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) &&
623
- sig_version == :witness_v0 && !Key.compress_pubkey?(pubkey)
624
- return set_error(SCRIPT_ERR_WITNESS_PUBKEYTYPE)
625
- end
603
+ def check_pubkey_encoding(pubkey)
604
+ return set_error(SCRIPT_ERR_PUBKEYTYPE) unless Key.compress_or_uncompress_pubkey?(pubkey)
626
605
  true
627
606
  end
628
607
 
@@ -12,10 +12,11 @@ module Tapyrus
12
12
  end
13
13
 
14
14
  # check signature
15
- # @param [String] script_sig
16
- # @param [String] pubkey
15
+ # @param [String] script_sig a signature with hex format.
16
+ # @param [String] pubkey a public key with hex format.
17
17
  # @param [Tapyrus::Script] script_code
18
18
  # @param [Integer] sig_version
19
+ # @return [Boolean] if check is passed return true, otherwise false.
19
20
  def check_sig(script_sig, pubkey, script_code, sig_version)
20
21
  return false if script_sig.empty?
21
22
  script_sig = script_sig.htb
@@ -23,9 +24,20 @@ module Tapyrus
23
24
  sig = script_sig[0..-2]
24
25
  sighash = tx.sighash_for_input(input_index, script_code, hash_type: hash_type,
25
26
  amount: amount, sig_version: sig_version)
27
+ verify_sig(sig.bth, pubkey, sighash)
28
+ end
29
+
30
+ # Check data signature.
31
+ # @param [String] sig a signature with hex format.
32
+ # @param [String] pubkey a public key with hex format.
33
+ # @param [String] digest a message digest with binary format to be verified.
34
+ # @return [Boolean] if check is passed return true, otherwise false.
35
+ def verify_sig(sig, pubkey, digest)
26
36
  key_type = pubkey.start_with?('02') || pubkey.start_with?('03') ? Key::TYPES[:compressed] : Key::TYPES[:uncompressed]
37
+ sig = sig.htb
38
+ algo = sig.bytesize == 64 ? :schnorr : :ecdsa
27
39
  key = Key.new(pubkey: pubkey, key_type: key_type)
28
- key.verify(sig, sighash)
40
+ key.verify(sig, digest, algo: algo)
29
41
  end
30
42
 
31
43
  def check_locktime(locktime)
@@ -53,7 +65,7 @@ module Tapyrus
53
65
  def check_sequence(sequence)
54
66
  tx_sequence = tx.inputs[input_index].sequence
55
67
  # Fail if the transaction's version number is not set high enough to trigger BIP 68 rules.
56
- return false if tx.version < 2
68
+ return false if tx.features < 2
57
69
 
58
70
  # Sequence numbers with their most significant bit set are not consensus constrained.
59
71
  # Testing that the transaction's sequence number do not have this bit set prevents using this property to get around a CHECKSEQUENCEVERIFY check.
@@ -6,6 +6,7 @@ module Tapyrus
6
6
 
7
7
  autoload :Ruby, 'tapyrus/secp256k1/ruby'
8
8
  autoload :Native, 'tapyrus/secp256k1/native'
9
+ autoload :RFC6979, 'tapyrus/secp256k1/rfc6979'
9
10
 
10
11
  end
11
12
 
@@ -0,0 +1,43 @@
1
+ module Tapyrus
2
+ module Secp256k1
3
+ module RFC6979
4
+
5
+ INITIAL_V = '0101010101010101010101010101010101010101010101010101010101010101'.htb
6
+ INITIAL_K = '0000000000000000000000000000000000000000000000000000000000000000'.htb
7
+ ZERO_B = '00'.htb
8
+ ONE_B = '01'.htb
9
+
10
+ module_function
11
+
12
+ # generate temporary key k to be used when ECDSA sign.
13
+ # https://tools.ietf.org/html/rfc6979#section-3.2
14
+ # @param [String] key_data a data contains private key and message.
15
+ # @param [String] extra_entropy extra entropy with binary format.
16
+ # @return [Integer] a nonce.
17
+ def generate_rfc6979_nonce(key_data, extra_entropy)
18
+ v = INITIAL_V # 3.2.b
19
+ k = INITIAL_K # 3.2.c
20
+ # 3.2.d
21
+ k = Tapyrus.hmac_sha256(k, v + ZERO_B + key_data + extra_entropy)
22
+ # 3.2.e
23
+ v = Tapyrus.hmac_sha256(k, v)
24
+ # 3.2.f
25
+ k = Tapyrus.hmac_sha256(k, v + ONE_B + key_data + extra_entropy)
26
+ # 3.2.g
27
+ v = Tapyrus.hmac_sha256(k, v)
28
+ # 3.2.h
29
+ t = ''
30
+ 10000.times do
31
+ v = Tapyrus.hmac_sha256(k, v)
32
+ t = (t + v)
33
+ t_num = t.bth.to_i(16)
34
+ return t_num if 1 <= t_num && t_num < Tapyrus::Secp256k1::GROUP.order
35
+ k = Tapyrus.hmac_sha256(k, v + '00'.htb)
36
+ v = Tapyrus.hmac_sha256(k, v)
37
+ end
38
+ raise 'A valid nonce was not found.'
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -35,7 +35,7 @@ module Tapyrus
35
35
  privkey = privkey.htb
36
36
  private_key = ECDSA::Format::IntegerOctetString.decode(privkey)
37
37
  extra_entropy ||= ''
38
- nonce = generate_rfc6979_nonce(data, privkey, extra_entropy)
38
+ nonce = RFC6979.generate_rfc6979_nonce(privkey + data, extra_entropy)
39
39
 
40
40
  # port form ecdsa gem.
41
41
  r_point = GROUP.new_point(nonce)
@@ -74,6 +74,10 @@ module Tapyrus
74
74
  end
75
75
  end
76
76
 
77
+ alias :valid_sig? :verify_sig
78
+
79
+ module_function :valid_sig?
80
+
77
81
  # if +pubkey+ is hybrid public key format, it convert uncompressed format.
78
82
  # https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html
79
83
  def repack_pubkey(pubkey)
@@ -87,36 +91,6 @@ module Tapyrus
87
91
  end
88
92
  end
89
93
 
90
- INITIAL_V = '0101010101010101010101010101010101010101010101010101010101010101'.htb
91
- INITIAL_K = '0000000000000000000000000000000000000000000000000000000000000000'.htb
92
- ZERO_B = '00'.htb
93
- ONE_B = '01'.htb
94
-
95
- # generate temporary key k to be used when ECDSA sign.
96
- # https://tools.ietf.org/html/rfc6979#section-3.2
97
- def generate_rfc6979_nonce(data, privkey, extra_entropy)
98
- v = INITIAL_V # 3.2.b
99
- k = INITIAL_K # 3.2.c
100
- # 3.2.d
101
- k = Tapyrus.hmac_sha256(k, v + ZERO_B + privkey + data + extra_entropy)
102
- # 3.2.e
103
- v = Tapyrus.hmac_sha256(k, v)
104
- # 3.2.f
105
- k = Tapyrus.hmac_sha256(k, v + ONE_B + privkey + data + extra_entropy)
106
- # 3.2.g
107
- v = Tapyrus.hmac_sha256(k, v)
108
- # 3.2.h
109
- t = ''
110
- 10000.times do
111
- v = Tapyrus.hmac_sha256(k, v)
112
- t = (t + v)
113
- t_num = t.bth.to_i(16)
114
- return t_num if 1 <= t_num && t_num < GROUP.order
115
- k = Tapyrus.hmac_sha256(k, v + '00'.htb)
116
- v = Tapyrus.hmac_sha256(k, v)
117
- end
118
- raise 'A valid nonce was not found.'
119
- end
120
94
  end
121
95
 
122
96
  end