tapyrus 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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