tapyrus 0.2.7 → 0.2.8

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.prettierignore +3 -0
  4. data/.prettierrc.yaml +3 -0
  5. data/CODE_OF_CONDUCT.md +7 -7
  6. data/README.md +14 -17
  7. data/Rakefile +3 -3
  8. data/lib/openassets.rb +0 -2
  9. data/lib/openassets/marker_output.rb +0 -4
  10. data/lib/openassets/payload.rb +4 -10
  11. data/lib/schnorr.rb +2 -3
  12. data/lib/schnorr/signature.rb +3 -6
  13. data/lib/tapyrus.rb +6 -22
  14. data/lib/tapyrus/base58.rb +7 -6
  15. data/lib/tapyrus/block.rb +1 -2
  16. data/lib/tapyrus/block_header.rb +15 -9
  17. data/lib/tapyrus/bloom_filter.rb +5 -3
  18. data/lib/tapyrus/chain_params.rb +1 -4
  19. data/lib/tapyrus/chainparams/dev.yml +3 -2
  20. data/lib/tapyrus/chainparams/prod.yml +3 -2
  21. data/lib/tapyrus/constants.rb +29 -23
  22. data/lib/tapyrus/errors.rb +1 -3
  23. data/lib/tapyrus/ext.rb +1 -1
  24. data/lib/tapyrus/ext/ecdsa.rb +4 -4
  25. data/lib/tapyrus/ext/json_parser.rb +1 -4
  26. data/lib/tapyrus/ext_key.rb +38 -34
  27. data/lib/tapyrus/key.rb +31 -35
  28. data/lib/tapyrus/key_path.rb +15 -12
  29. data/lib/tapyrus/logger.rb +20 -16
  30. data/lib/tapyrus/merkle_tree.rb +19 -20
  31. data/lib/tapyrus/message.rb +14 -16
  32. data/lib/tapyrus/message/addr.rb +1 -7
  33. data/lib/tapyrus/message/base.rb +0 -3
  34. data/lib/tapyrus/message/block.rb +2 -9
  35. data/lib/tapyrus/message/block_transaction_request.rb +3 -6
  36. data/lib/tapyrus/message/block_transactions.rb +2 -6
  37. data/lib/tapyrus/message/block_txn.rb +0 -4
  38. data/lib/tapyrus/message/cmpct_block.rb +1 -7
  39. data/lib/tapyrus/message/error.rb +1 -4
  40. data/lib/tapyrus/message/fee_filter.rb +1 -4
  41. data/lib/tapyrus/message/filter_add.rb +0 -4
  42. data/lib/tapyrus/message/filter_clear.rb +0 -4
  43. data/lib/tapyrus/message/filter_load.rb +2 -5
  44. data/lib/tapyrus/message/get_addr.rb +0 -4
  45. data/lib/tapyrus/message/get_block_txn.rb +0 -4
  46. data/lib/tapyrus/message/get_blocks.rb +0 -3
  47. data/lib/tapyrus/message/get_data.rb +1 -4
  48. data/lib/tapyrus/message/get_headers.rb +1 -3
  49. data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
  50. data/lib/tapyrus/message/headers.rb +0 -4
  51. data/lib/tapyrus/message/headers_parser.rb +3 -8
  52. data/lib/tapyrus/message/inv.rb +1 -4
  53. data/lib/tapyrus/message/inventories_parser.rb +2 -7
  54. data/lib/tapyrus/message/inventory.rb +12 -5
  55. data/lib/tapyrus/message/mem_pool.rb +0 -4
  56. data/lib/tapyrus/message/merkle_block.rb +4 -9
  57. data/lib/tapyrus/message/network_addr.rb +7 -6
  58. data/lib/tapyrus/message/not_found.rb +0 -3
  59. data/lib/tapyrus/message/ping.rb +0 -3
  60. data/lib/tapyrus/message/pong.rb +0 -3
  61. data/lib/tapyrus/message/prefilled_tx.rb +0 -4
  62. data/lib/tapyrus/message/reject.rb +0 -3
  63. data/lib/tapyrus/message/send_cmpct.rb +1 -3
  64. data/lib/tapyrus/message/send_headers.rb +0 -3
  65. data/lib/tapyrus/message/tx.rb +0 -4
  66. data/lib/tapyrus/message/ver_ack.rb +1 -5
  67. data/lib/tapyrus/message/version.rb +2 -5
  68. data/lib/tapyrus/mnemonic.rb +17 -15
  69. data/lib/tapyrus/network.rb +0 -2
  70. data/lib/tapyrus/network/connection.rb +0 -3
  71. data/lib/tapyrus/network/message_handler.rb +61 -60
  72. data/lib/tapyrus/network/peer.rb +13 -12
  73. data/lib/tapyrus/network/peer_discovery.rb +3 -5
  74. data/lib/tapyrus/network/pool.rb +12 -12
  75. data/lib/tapyrus/node.rb +1 -1
  76. data/lib/tapyrus/node/cli.rb +12 -14
  77. data/lib/tapyrus/node/configuration.rb +1 -3
  78. data/lib/tapyrus/node/spv.rb +2 -3
  79. data/lib/tapyrus/opcodes.rb +9 -7
  80. data/lib/tapyrus/out_point.rb +5 -5
  81. data/lib/tapyrus/rpc/http_server.rb +21 -22
  82. data/lib/tapyrus/rpc/request_handler.rb +42 -44
  83. data/lib/tapyrus/rpc/tapyrus_core_client.rb +53 -25
  84. data/lib/tapyrus/script/color.rb +10 -0
  85. data/lib/tapyrus/script/multisig.rb +13 -12
  86. data/lib/tapyrus/script/script.rb +72 -71
  87. data/lib/tapyrus/script/script_error.rb +1 -4
  88. data/lib/tapyrus/script/script_interpreter.rb +439 -399
  89. data/lib/tapyrus/script/tx_checker.rb +20 -10
  90. data/lib/tapyrus/secp256k1.rb +0 -4
  91. data/lib/tapyrus/secp256k1/native.rb +14 -15
  92. data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
  93. data/lib/tapyrus/secp256k1/ruby.rb +10 -12
  94. data/lib/tapyrus/slip39.rb +20 -5
  95. data/lib/tapyrus/slip39/share.rb +41 -29
  96. data/lib/tapyrus/slip39/sss.rb +101 -57
  97. data/lib/tapyrus/store.rb +1 -3
  98. data/lib/tapyrus/store/chain_entry.rb +0 -4
  99. data/lib/tapyrus/store/db.rb +0 -2
  100. data/lib/tapyrus/store/db/level_db.rb +5 -9
  101. data/lib/tapyrus/store/spv_chain.rb +11 -17
  102. data/lib/tapyrus/tx.rb +45 -37
  103. data/lib/tapyrus/tx_builder.rb +158 -0
  104. data/lib/tapyrus/tx_in.rb +1 -6
  105. data/lib/tapyrus/tx_out.rb +2 -7
  106. data/lib/tapyrus/util.rb +7 -9
  107. data/lib/tapyrus/validation.rb +12 -11
  108. data/lib/tapyrus/version.rb +1 -1
  109. data/lib/tapyrus/wallet/account.rb +22 -18
  110. data/lib/tapyrus/wallet/base.rb +12 -9
  111. data/lib/tapyrus/wallet/db.rb +6 -9
  112. data/lib/tapyrus/wallet/master_key.rb +2 -4
  113. data/tapyrusrb.gemspec +13 -14
  114. metadata +21 -4
  115. data/.travis.yml +0 -14
@@ -1,4 +1,4 @@
1
- require "murmurhash3"
1
+ require 'murmurhash3'
2
2
  module Tapyrus
3
3
  class BloomFilter
4
4
  LN2_SQUARED = 0.4804530139182014246671025263266649717305529515945455 # log(2) ** 2
@@ -23,6 +23,7 @@ module Tapyrus
23
23
  # The size S of the filter in bytes is given by (-1 / pow(log(2), 2) * N * log(P)) / 8
24
24
  len = [[(-elements_length * Math.log(fp_rate) / (LN2_SQUARED * 8)).to_i, MAX_BLOOM_FILTER_SIZE].min, 1].max
25
25
  filter = Array.new(len, 0)
26
+
26
27
  # The number of hash functions required is given by S * 8 / N * log(2)
27
28
  hash_funcs = [[(filter.size * 8 * LN2 / elements_length).to_i, MAX_HASH_FUNCS].min, 1].max
28
29
  BloomFilter.new(filter, hash_funcs, tweak)
@@ -59,8 +60,9 @@ module Tapyrus
59
60
  end
60
61
 
61
62
  private
63
+
62
64
  def to_hash(data, i)
63
- MurmurHash3::V32.str_hash(data, (i * 0xfba4c795 + tweak) & 0xffffffff) % (filter.length * 8)
65
+ MurmurHash3::V32.str_hash(data, (i * 0xfba4c795 + tweak) & 0xffffffff) % (filter.length * 8)
64
66
  end
65
67
 
66
68
  def set_bit(data)
@@ -72,7 +74,7 @@ module Tapyrus
72
74
  end
73
75
 
74
76
  def full?
75
- @full |= filter.all? {|byte| byte == 0xff}
77
+ @full |= filter.all? { |byte| byte == 0xff }
76
78
  end
77
79
  end
78
80
  end
@@ -1,10 +1,8 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Tapyrus
4
-
5
4
  # Network parameter class
6
5
  class ChainParams
7
-
8
6
  attr_reader :network
9
7
  attr_reader :magic_head
10
8
  attr_reader :message_magic
@@ -63,5 +61,4 @@ module Tapyrus
63
61
 
64
62
  private_class_method :init
65
63
  end
66
-
67
- end
64
+ end
@@ -1,4 +1,5 @@
1
- --- !ruby/object:Tapyrus::ChainParams
1
+ ---
2
+ !ruby/object:Tapyrus::ChainParams
2
3
  network: "dev"
3
4
  magic_head: "0b110907"
4
5
  message_magic: "Tapyrus Signed Message:\n"
@@ -26,4 +27,4 @@ target_spacing: 600 # block interval
26
27
  max_money: 21000000
27
28
  bip34_height: 227931
28
29
  dns_seeds:
29
- bip44_coin_type: 1
30
+ bip44_coin_type: 1
@@ -1,4 +1,5 @@
1
- --- !ruby/object:Tapyrus::ChainParams
1
+ ---
2
+ !ruby/object:Tapyrus::ChainParams
2
3
  network: "prod"
3
4
  magic_head: "f9beb4d9"
4
5
  message_magic: "Tapyrus Signed Message:\n"
@@ -26,4 +27,4 @@ target_spacing: 600 # block interval
26
27
  max_money: 21000000
27
28
  bip34_height: 227931
28
29
  dns_seeds:
29
- bip44_coin_type: 0
30
+ bip44_coin_type: 0
@@ -1,20 +1,23 @@
1
1
  module Tapyrus
2
-
3
2
  COIN = 100_000_000
4
3
  MAX_MONEY = 21_000_000 * COIN
5
4
 
6
5
  # The maximum allowed size for a serialized block, in bytes (only for buffer size limits)
7
6
  MAX_BLOCK_SERIALIZED_SIZE = 4_000_000
7
+
8
8
  # The maximum allowed weight for a block, see BIP 141 (network rule)
9
9
  MAX_BLOCK_WEIGHT = 4_000_000
10
+
10
11
  # The maximum allowed number of signature check operations in a block (network rule)
11
12
  MAX_BLOCK_SIGOPS_COST = 80_000
13
+
12
14
  # Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
13
15
  COINBASE_MATURITY = 100
14
16
  WITNESS_SCALE_FACTOR = 4
15
17
 
16
18
  # 60 is the lower bound for the size of a valid serialized Tx
17
19
  MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60
20
+
18
21
  # 10 is the lower bound for the size of a serialized Tx
19
22
  MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10
20
23
 
@@ -26,11 +29,11 @@ module Tapyrus
26
29
  DUST_RELAY_TX_FEE = 3000
27
30
 
28
31
  # script verify flags
29
- SCRIPT_VERIFY_NONE = 0
30
- SCRIPT_VERIFY_P2SH = (1 << 0)
32
+ SCRIPT_VERIFY_NONE = 0
33
+ SCRIPT_VERIFY_P2SH = (1 << 0)
31
34
  SCRIPT_VERIFY_STRICTENC = (1 << 1)
32
- SCRIPT_VERIFY_DERSIG = (1 << 2)
33
- SCRIPT_VERIFY_LOW_S = (1 << 3)
35
+ SCRIPT_VERIFY_DERSIG = (1 << 2)
36
+ SCRIPT_VERIFY_LOW_S = (1 << 3)
34
37
  SCRIPT_VERIFY_NULLDUMMY = (1 << 4)
35
38
  SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5)
36
39
  SCRIPT_VERIFY_MINIMALDATA = (1 << 6)
@@ -45,24 +48,27 @@ module Tapyrus
45
48
  MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH
46
49
 
47
50
  # Standard script verification flags that standard transactions will comply with.
48
- STANDARD_SCRIPT_VERIFY_FLAGS = [MANDATORY_SCRIPT_VERIFY_FLAGS,
49
- SCRIPT_VERIFY_DERSIG,
50
- SCRIPT_VERIFY_STRICTENC,
51
- SCRIPT_VERIFY_MINIMALDATA,
52
- SCRIPT_VERIFY_NULLDUMMY,
53
- SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
54
- SCRIPT_VERIFY_CLEANSTACK,
55
- SCRIPT_VERIFY_MINIMALIF,
56
- SCRIPT_VERIFY_NULLFAIL,
57
- SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
58
- SCRIPT_VERIFY_CHECKSEQUENCEVERIFY,
59
- SCRIPT_VERIFY_LOW_S,
60
- SCRIPT_VERIFY_CONST_SCRIPTCODE].inject(SCRIPT_VERIFY_NONE){|flags, f| flags |= f}
51
+ STANDARD_SCRIPT_VERIFY_FLAGS =
52
+ [
53
+ MANDATORY_SCRIPT_VERIFY_FLAGS,
54
+ SCRIPT_VERIFY_DERSIG,
55
+ SCRIPT_VERIFY_STRICTENC,
56
+ SCRIPT_VERIFY_MINIMALDATA,
57
+ SCRIPT_VERIFY_NULLDUMMY,
58
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
59
+ SCRIPT_VERIFY_CLEANSTACK,
60
+ SCRIPT_VERIFY_MINIMALIF,
61
+ SCRIPT_VERIFY_NULLFAIL,
62
+ SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
63
+ SCRIPT_VERIFY_CHECKSEQUENCEVERIFY,
64
+ SCRIPT_VERIFY_LOW_S,
65
+ SCRIPT_VERIFY_CONST_SCRIPTCODE
66
+ ].inject(SCRIPT_VERIFY_NONE) { |flags, f| flags |= f }
61
67
 
62
68
  # for script
63
69
 
64
70
  # Maximum script length in bytes
65
- MAX_SCRIPT_SIZE = 10000
71
+ MAX_SCRIPT_SIZE = 10_000
66
72
 
67
73
  # Maximum number of public keys per multisig
68
74
  MAX_PUBKEYS_PER_MULTISIG = 20
@@ -77,7 +83,7 @@ module Tapyrus
77
83
  MAX_STACK_SIZE = 1000
78
84
 
79
85
  # Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
80
- LOCKTIME_THRESHOLD = 500000000
86
+ LOCKTIME_THRESHOLD = 500_000_000
81
87
 
82
88
  # Signature hash types/flags
83
89
  SIGHASH_TYPE = { all: 1, none: 2, single: 3, anyonecanpay: 128 }
@@ -153,7 +159,7 @@ module Tapyrus
153
159
  ERRCODES_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [const_get(c), c.to_s] }.flatten]
154
160
  NAME_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [c.to_s, const_get(c)] }.flatten]
155
161
 
156
- COINBASE_WTXID = '00'* 32
162
+ COINBASE_WTXID = '00' * 32
157
163
 
158
164
  # for message
159
165
  MESSAGE_HEADER_SIZE = 24
@@ -169,5 +175,5 @@ module Tapyrus
169
175
 
170
176
  BIP32_EXTKEY_WITH_VERSION_SIZE = 78
171
177
 
172
- HARDENED_THRESHOLD = 2147483648 # 2**31
173
- end
178
+ HARDENED_THRESHOLD = 2_147_483_648 # 2**31
179
+ end
@@ -1,7 +1,6 @@
1
1
  module Tapyrus
2
2
  module Errors
3
3
  module Messages
4
-
5
4
  INVALID_PUBLIC_KEY = 'Invalid public key.'
6
5
  INVALID_BIP32_PRIV_PREFIX = 'Invalid BIP32 private key prefix. prefix must be 0x00.'
7
6
  INVALID_BIP32_FINGERPRINT = 'Invalid parent fingerprint.'
@@ -11,7 +10,6 @@ module Tapyrus
11
10
 
12
11
  INVALID_PRIV_KEY = 'Private key is not in range [1..n-1].'
13
12
  INVALID_CHECKSUM = 'Invalid checksum.'
14
-
15
13
  end
16
14
  end
17
- end
15
+ end
data/lib/tapyrus/ext.rb CHANGED
@@ -2,4 +2,4 @@ module Tapyrus
2
2
  module Ext
3
3
  autoload :JsonParser, 'tapyrus/ext/json_parser'
4
4
  end
5
- end
5
+ end
@@ -12,7 +12,6 @@ class ::ECDSA::Point
12
12
  end
13
13
 
14
14
  module ::ECDSA::Format::PointOctetString
15
-
16
15
  def self.decode(string, group, allow_hybrid: false)
17
16
  string = string.dup.force_encoding('BINARY')
18
17
 
@@ -29,11 +28,12 @@ module ::ECDSA::Format::PointOctetString
29
28
  when 4
30
29
  decode_uncompressed string, group
31
30
  when 6..7
32
- raise ECDSA::Format::DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord unless allow_hybrid
31
+ unless allow_hybrid
32
+ raise ECDSA::Format::DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord
33
+ end
33
34
  decode_uncompressed string, group if allow_hybrid
34
35
  else
35
36
  raise ECDSA::Format::DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord
36
37
  end
37
38
  end
38
-
39
- end
39
+ end
@@ -2,11 +2,9 @@ require 'json/pure'
2
2
 
3
3
  module Tapyrus
4
4
  module Ext
5
-
6
5
  # Extension of JSON::Pure::Parser.
7
6
  # This class convert Float value to String value.
8
7
  class JsonParser < JSON::Pure::Parser
9
-
10
8
  def parse_value
11
9
  case
12
10
  when scan(FLOAT)
@@ -41,7 +39,6 @@ module Tapyrus
41
39
  UNPARSED
42
40
  end
43
41
  end
44
-
45
42
  end
46
43
  end
47
- end
44
+ end
@@ -1,5 +1,4 @@
1
1
  module Tapyrus
2
-
3
2
  # Integers modulo the order of the curve(secp256k1)
4
3
  CURVE_ORDER = ECDSA::Group::Secp256k1.order
5
4
 
@@ -45,8 +44,8 @@ module Tapyrus
45
44
 
46
45
  # serialize extended private key
47
46
  def to_payload
48
- version.htb << [depth].pack('C') << parent_fingerprint.htb <<
49
- [number].pack('N') << chain_code << [0x00].pack('C') << key.priv_key.htb
47
+ version.htb << [depth].pack('C') << parent_fingerprint.htb << [number].pack('N') << chain_code <<
48
+ [0x00].pack('C') << key.priv_key.htb
50
49
  end
51
50
 
52
51
  # Base58 encoded extended private key
@@ -108,8 +107,7 @@ module Tapyrus
108
107
  raise 'invalid key' if left >= CURVE_ORDER
109
108
  child_priv = (left + key.priv_key.to_i(16)) % CURVE_ORDER
110
109
  raise 'invalid key ' if child_priv >= CURVE_ORDER
111
- new_key.key = Tapyrus::Key.new(
112
- priv_key: child_priv.to_even_length_hex.rjust(64, '0'), key_type: key_type)
110
+ new_key.key = Tapyrus::Key.new(priv_key: child_priv.to_even_length_hex.rjust(64, '0'), key_type: key_type)
113
111
  new_key.chain_code = l[32..-1]
114
112
  new_key.ver = version
115
113
  new_key
@@ -147,10 +145,14 @@ module Tapyrus
147
145
  ext_key.parent_fingerprint = buf.read(4).bth
148
146
  ext_key.number = buf.read(4).unpack('N').first
149
147
  if ext_key.depth == 0
150
- raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT unless ext_key.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
148
+ unless ext_key.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
149
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT
150
+ end
151
151
  raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_INDEX if ext_key.number > 0
152
152
  end
153
- raise ArgumentError, Errors::Messages:: INVALID_BIP32_ZERO_DEPTH if ext_key.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_key.depth > 0
153
+ if ext_key.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_key.depth > 0
154
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_DEPTH
155
+ end
154
156
  ext_key.chain_code = buf.read(32)
155
157
  raise ArgumentError, Errors::Messages::INVALID_BIP32_PRIV_PREFIX unless buf.read(1).bth == '00' # 0x00
156
158
  ext_key.key = Tapyrus::Key.new(priv_key: buf.read(32).bth, key_type: Tapyrus::Key::TYPES[:compressed])
@@ -166,33 +168,34 @@ module Tapyrus
166
168
  def self.version_from_purpose(purpose)
167
169
  v = purpose - Tapyrus::HARDENED_THRESHOLD
168
170
  case v
169
- when 49
170
- Tapyrus.chain_params.bip49_privkey_p2wpkh_p2sh_version
171
- when 84
172
- Tapyrus.chain_params.bip84_privkey_p2wpkh_version
173
- else
174
- Tapyrus.chain_params.extended_privkey_version
171
+ when 49
172
+ Tapyrus.chain_params.bip49_privkey_p2wpkh_p2sh_version
173
+ when 84
174
+ Tapyrus.chain_params.bip84_privkey_p2wpkh_version
175
+ else
176
+ Tapyrus.chain_params.extended_privkey_version
175
177
  end
176
178
  end
177
179
 
178
180
  # check whether +version+ is supported version bytes.
179
181
  def self.support_version?(version)
180
182
  p = Tapyrus.chain_params
181
- [p.bip49_privkey_p2wpkh_p2sh_version, p.bip84_privkey_p2wpkh_version, p.extended_privkey_version].include?(version)
183
+ [p.bip49_privkey_p2wpkh_p2sh_version, p.bip84_privkey_p2wpkh_version, p.extended_privkey_version].include?(
184
+ version
185
+ )
182
186
  end
183
187
 
184
188
  # convert privkey version to pubkey version
185
189
  def priv_ver_to_pub_ver
186
190
  case version
187
- when Tapyrus.chain_params.bip49_privkey_p2wpkh_p2sh_version
188
- Tapyrus.chain_params.bip49_pubkey_p2wpkh_p2sh_version
189
- when Tapyrus.chain_params.bip84_privkey_p2wpkh_version
190
- Tapyrus.chain_params.bip84_pubkey_p2wpkh_version
191
- else
192
- Tapyrus.chain_params.extended_pubkey_version
191
+ when Tapyrus.chain_params.bip49_privkey_p2wpkh_p2sh_version
192
+ Tapyrus.chain_params.bip49_pubkey_p2wpkh_p2sh_version
193
+ when Tapyrus.chain_params.bip84_privkey_p2wpkh_version
194
+ Tapyrus.chain_params.bip84_pubkey_p2wpkh_version
195
+ else
196
+ Tapyrus.chain_params.extended_pubkey_version
193
197
  end
194
198
  end
195
-
196
199
  end
197
200
 
198
201
  # BIP-32 Extended public key
@@ -208,8 +211,7 @@ module Tapyrus
208
211
 
209
212
  # serialize extended pubkey
210
213
  def to_payload
211
- version.htb << [depth].pack('C') <<
212
- parent_fingerprint.htb << [number].pack('N') << chain_code << pub.htb
214
+ version.htb << [depth].pack('C') << parent_fingerprint.htb << [number].pack('N') << chain_code << pub.htb
213
215
  end
214
216
 
215
217
  def pub
@@ -269,7 +271,7 @@ module Tapyrus
269
271
  l = Tapyrus.hmac_sha512(chain_code, data)
270
272
  left = l[0..31].bth.to_i(16)
271
273
  raise 'invalid key' if left >= CURVE_ORDER
272
- p1 = Tapyrus::Secp256k1::GROUP.generator.multiply_by_scalar(left)
274
+ p1 = Tapyrus::Key.new(priv_key: left.to_s(16), key_type: Tapyrus::Key::TYPES[:uncompressed]).to_point
273
275
  p2 = Tapyrus::Key.new(pubkey: pubkey, key_type: key_type).to_point
274
276
  new_key.pubkey = (p1 + p2).to_hex
275
277
  new_key.chain_code = l[32..-1]
@@ -309,10 +311,14 @@ module Tapyrus
309
311
  ext_pubkey.parent_fingerprint = buf.read(4).bth
310
312
  ext_pubkey.number = buf.read(4).unpack('N').first
311
313
  if ext_pubkey.depth == 0
312
- raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT unless ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
314
+ unless ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
315
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT
316
+ end
313
317
  raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_INDEX if ext_pubkey.number > 0
314
318
  end
315
- raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_DEPTH if ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_pubkey.depth > 0
319
+ if ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_pubkey.depth > 0
320
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_DEPTH
321
+ end
316
322
  ext_pubkey.chain_code = buf.read(32)
317
323
  ext_pubkey.pubkey = Tapyrus::Key.new(pubkey: buf.read(33).bth).pubkey
318
324
  ext_pubkey
@@ -336,12 +342,12 @@ module Tapyrus
336
342
  def self.version_from_purpose(purpose)
337
343
  v = purpose - Tapyrus::HARDENED_THRESHOLD
338
344
  case v
339
- when 49
340
- Tapyrus.chain_params.bip49_pubkey_p2wpkh_p2sh_version
341
- when 84
342
- Tapyrus.chain_params.bip84_pubkey_p2wpkh_version
343
- else
344
- Tapyrus.chain_params.extended_pubkey_version
345
+ when 49
346
+ Tapyrus.chain_params.bip49_pubkey_p2wpkh_p2sh_version
347
+ when 84
348
+ Tapyrus.chain_params.bip84_pubkey_p2wpkh_version
349
+ else
350
+ Tapyrus.chain_params.extended_pubkey_version
345
351
  end
346
352
  end
347
353
 
@@ -350,7 +356,5 @@ module Tapyrus
350
356
  p = Tapyrus.chain_params
351
357
  [p.bip49_pubkey_p2wpkh_p2sh_version, p.bip84_pubkey_p2wpkh_version, p.extended_pubkey_version].include?(version)
352
358
  end
353
-
354
359
  end
355
-
356
360
  end
data/lib/tapyrus/key.rb CHANGED
@@ -2,10 +2,8 @@
2
2
  # https://github.com/lian/bitcoin-ruby/blob/master/COPYING
3
3
 
4
4
  module Tapyrus
5
-
6
5
  # tapyrus key class
7
6
  class Key
8
-
9
7
  PUBLIC_KEY_SIZE = 65
10
8
  COMPRESSED_PUBLIC_KEY_SIZE = 33
11
9
  SIGNATURE_SIZE = 72
@@ -18,9 +16,10 @@ module Tapyrus
18
16
  attr_accessor :key_type
19
17
  attr_reader :secp256k1_module
20
18
 
21
- TYPES = {uncompressed: 0x00, compressed: 0x01, p2pkh: 0x10, p2wpkh: 0x11, p2wpkh_p2sh: 0x12}
19
+ TYPES = { uncompressed: 0x00, compressed: 0x01, p2pkh: 0x10, p2wpkh: 0x11, p2wpkh_p2sh: 0x12 }
22
20
 
23
21
  MIN_PRIV_KEY_MOD_ORDER = 0x01
22
+
24
23
  # Order of secp256k1's generator minus 1.
25
24
  MAX_PRIV_KEY_MOD_ORDER = ECDSA::Group::Secp256k1.order - 1
26
25
 
@@ -31,18 +30,18 @@ module Tapyrus
31
30
  # @param [Boolean] compressed [Deprecated] whether public key is compressed.
32
31
  # @return [Tapyrus::Key] a key object.
33
32
  def initialize(priv_key: nil, pubkey: nil, key_type: nil, compressed: true, allow_hybrid: false)
34
- puts "[Warning] Use key_type parameter instead of compressed. compressed parameter removed in the future." if key_type.nil? && !compressed.nil? && pubkey.nil?
33
+ if key_type.nil? && !compressed.nil? && pubkey.nil?
34
+ puts '[Warning] Use key_type parameter instead of compressed. compressed parameter removed in the future.'
35
+ end
35
36
  if key_type
36
37
  @key_type = key_type
37
38
  compressed = @key_type != TYPES[:uncompressed]
38
39
  else
39
40
  @key_type = compressed ? TYPES[:compressed] : TYPES[:uncompressed]
40
41
  end
41
- @secp256k1_module = Tapyrus.secp_impl
42
+ @secp256k1_module = Tapyrus.secp_impl
42
43
  @priv_key = priv_key
43
- if @priv_key
44
- raise ArgumentError, Errors::Messages::INVALID_PRIV_KEY unless validate_private_key_range(@priv_key)
45
- end
44
+ raise ArgumentError, Errors::Messages::INVALID_PRIV_KEY unless validate_private_key_range(@priv_key) if @priv_key
46
45
  if pubkey
47
46
  @pubkey = pubkey
48
47
  else
@@ -66,7 +65,9 @@ module Tapyrus
66
65
  data = hex[2...-8].htb
67
66
  checksum = hex[-8..-1]
68
67
  raise ArgumentError, 'invalid version' unless version == Tapyrus.chain_params.privkey_version
69
- raise ArgumentError, Errors::Messages::INVALID_CHECKSUM unless Tapyrus.calc_checksum(version + data.bth) == checksum
68
+ unless Tapyrus.calc_checksum(version + data.bth) == checksum
69
+ raise ArgumentError, Errors::Messages::INVALID_CHECKSUM
70
+ end
70
71
  key_len = data.bytesize
71
72
  if key_len == COMPRESSED_PUBLIC_KEY_SIZE && data[-1].unpack('C').first == 1
72
73
  key_type = TYPES[:compressed]
@@ -95,7 +96,7 @@ module Tapyrus
95
96
  # @param [Symbol] algo Algorithms used for verification. Either :ecdsa or :schnorr is supported. default value is :ecdsa.
96
97
  # @return [String] signature data with binary format
97
98
  def sign(data, low_r = true, extra_entropy = nil, algo: :ecdsa)
98
- raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
99
+ raise ArgumentError, 'Unsupported algorithm has been specified.' unless SIG_ALGO.include?(algo)
99
100
  case algo
100
101
  when :ecdsa
101
102
  sign_ecdsa(data, low_r, extra_entropy)
@@ -114,7 +115,7 @@ module Tapyrus
114
115
  def verify(sig, origin, algo: :ecdsa)
115
116
  return false unless valid_pubkey?
116
117
  begin
117
- raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
118
+ raise ArgumentError, 'Unsupported algorithm has been specified.' unless SIG_ALGO.include?(algo)
118
119
  sig = ecdsa_signature_parse_der_lax(sig) if algo == :ecdsa
119
120
  secp256k1_module.verify_sig(origin, sig, pubkey, algo: algo)
120
121
  rescue Exception
@@ -150,12 +151,12 @@ module Tapyrus
150
151
  p = pubkey.htb
151
152
  return false if p.bytesize < COMPRESSED_PUBLIC_KEY_SIZE
152
153
  case p[0]
153
- when "\x04"
154
- return false unless p.bytesize == PUBLIC_KEY_SIZE
155
- when "\x02", "\x03"
156
- return false unless p.bytesize == COMPRESSED_PUBLIC_KEY_SIZE
157
- else
158
- return false
154
+ when "\x04"
155
+ return false unless p.bytesize == PUBLIC_KEY_SIZE
156
+ when "\x02", "\x03"
157
+ return false unless p.bytesize == COMPRESSED_PUBLIC_KEY_SIZE
158
+ else
159
+ return false
159
160
  end
160
161
  true
161
162
  end
@@ -172,16 +173,17 @@ module Tapyrus
172
173
  len_r = s[3]
173
174
  len_s = s[5 + len_r]
174
175
  val_s = s.slice(6 + len_r, len_s)
176
+
177
+ # prettier-ignore
175
178
  max_mod_half_order = [
176
- 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
177
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
178
- 0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,
179
- 0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0]
180
- compare_big_endian(val_s, [0]) > 0 &&
181
- compare_big_endian(val_s, max_mod_half_order) <= 0
179
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
180
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
181
+ 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, 0x50, 0x1d,
182
+ 0xdf, 0xe9, 0x2f, 0x46, 0x68, 0x1b, 0x20, 0xa0
183
+ ]
184
+ compare_big_endian(val_s, [0]) > 0 && compare_big_endian(val_s, max_mod_half_order) <= 0
182
185
  end
183
186
 
184
-
185
187
  # check +sig+ is correct der encoding.
186
188
  # This function is consensus-critical since BIP66.
187
189
  # @param [String] sig a signature data with binary format.
@@ -233,15 +235,11 @@ module Tapyrus
233
235
  def self.compare_big_endian(c1, c2)
234
236
  c1, c2 = c1.dup, c2.dup # Clone the arrays
235
237
 
236
- while c1.size > c2.size
237
- return 1 if c1.shift > 0
238
- end
238
+ return 1 if c1.shift > 0 while c1.size > c2.size
239
239
 
240
- while c2.size > c1.size
241
- return -1 if c2.shift > 0
242
- end
240
+ return -1 if c2.shift > 0 while c2.size > c1.size
243
241
 
244
- c1.size.times{|idx| return c1[idx] - c2[idx] if c1[idx] != c2[idx] }
242
+ c1.size.times { |idx| return c1[idx] - c2[idx] if c1[idx] != c2[idx] }
245
243
  0
246
244
  end
247
245
 
@@ -267,7 +265,7 @@ module Tapyrus
267
265
  def ecdsa_signature_parse_der_lax(sig)
268
266
  sig_array = sig.unpack('C*')
269
267
  len_r = sig_array[3]
270
- r = sig_array[4...(len_r+4)].pack('C*').bth
268
+ r = sig_array[4...(len_r + 4)].pack('C*').bth
271
269
  len_s = sig_array[len_r + 5]
272
270
  s = sig_array[(len_r + 6)...(len_r + 6 + len_s)].pack('C*').bth
273
271
  ECDSA::Signature.new(r.to_i(16), s.to_i(16)).to_der
@@ -291,13 +289,11 @@ module Tapyrus
291
289
  counter = 1
292
290
  until sig_has_low_r?(sig)
293
291
  extra_entropy = [counter].pack('I*').bth.ljust(64, '0').htb
294
- sig = secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: :ecdsa)
292
+ sig = secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: :ecdsa)
295
293
  counter += 1
296
294
  end
297
295
  end
298
296
  sig
299
297
  end
300
-
301
298
  end
302
-
303
299
  end