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,6 +1,5 @@
1
1
  module Tapyrus
2
2
  class TxChecker
3
-
4
3
  attr_reader :tx
5
4
  attr_reader :input_index
6
5
  attr_reader :amount
@@ -22,8 +21,8 @@ module Tapyrus
22
21
  script_sig = script_sig.htb
23
22
  hash_type = script_sig[-1].unpack('C').first
24
23
  sig = script_sig[0..-2]
25
- sighash = tx.sighash_for_input(input_index, script_code, hash_type: hash_type,
26
- amount: amount, sig_version: sig_version)
24
+ sighash =
25
+ tx.sighash_for_input(input_index, script_code, hash_type: hash_type, amount: amount, sig_version: sig_version)
27
26
  verify_sig(sig.bth, pubkey, sighash)
28
27
  end
29
28
 
@@ -33,7 +32,8 @@ module Tapyrus
33
32
  # @param [String] digest a message digest with binary format to be verified.
34
33
  # @return [Boolean] if check is passed return true, otherwise false.
35
34
  def verify_sig(sig, pubkey, digest, allow_hybrid: false)
36
- key_type = pubkey.start_with?('02') || pubkey.start_with?('03') ? Key::TYPES[:compressed] : Key::TYPES[:uncompressed]
35
+ key_type =
36
+ pubkey.start_with?('02') || pubkey.start_with?('03') ? Key::TYPES[:compressed] : Key::TYPES[:uncompressed]
37
37
  sig = sig.htb
38
38
  algo = sig.bytesize == 64 ? :schnorr : :ecdsa
39
39
  begin
@@ -49,8 +49,10 @@ module Tapyrus
49
49
  # distinguished by whether nLockTime < LOCKTIME_THRESHOLD.
50
50
 
51
51
  # We want to compare apples to apples, so fail the script unless the type of nLockTime being tested is the same as the nLockTime in the transaction.
52
- unless ((tx.lock_time < LOCKTIME_THRESHOLD && locktime < LOCKTIME_THRESHOLD) ||
53
- (tx.lock_time >= LOCKTIME_THRESHOLD && locktime >= LOCKTIME_THRESHOLD))
52
+ unless (
53
+ (tx.lock_time < LOCKTIME_THRESHOLD && locktime < LOCKTIME_THRESHOLD) ||
54
+ (tx.lock_time >= LOCKTIME_THRESHOLD && locktime >= LOCKTIME_THRESHOLD)
55
+ )
54
56
  return false
55
57
  end
56
58
 
@@ -68,6 +70,7 @@ module Tapyrus
68
70
 
69
71
  def check_sequence(sequence)
70
72
  tx_sequence = tx.inputs[input_index].sequence
73
+
71
74
  # Fail if the transaction's version number is not set high enough to trigger BIP 68 rules.
72
75
  return false if tx.features < 2
73
76
 
@@ -84,14 +87,21 @@ module Tapyrus
84
87
  # distinguished by whether sequence_masked < TxIn#SEQUENCE_LOCKTIME_TYPE_FLAG.
85
88
  # We want to compare apples to apples, so fail the script
86
89
  # unless the type of nSequenceMasked being tested is the same as the nSequenceMasked in the transaction.
87
- unless ((tx_sequence_masked < TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && sequence_masked < TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
88
- (tx_sequence_masked >= TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && sequence_masked >= TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG))
90
+ unless (
91
+ (
92
+ tx_sequence_masked < TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG &&
93
+ sequence_masked < TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG
94
+ ) ||
95
+ (
96
+ tx_sequence_masked >= TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG &&
97
+ sequence_masked >= TxIn::SEQUENCE_LOCKTIME_TYPE_FLAG
98
+ )
99
+ )
89
100
  return false
90
101
  end
91
102
 
92
103
  # Now that we know we're comparing apples-to-apples, the comparison is a simple numeric one.
93
104
  sequence_masked <= tx_sequence_masked
94
105
  end
95
-
96
106
  end
97
- end
107
+ end
@@ -1,13 +1,9 @@
1
1
  module Tapyrus
2
-
3
2
  module Secp256k1
4
-
5
3
  GROUP = ECDSA::Group::Secp256k1
6
4
 
7
5
  autoload :Ruby, 'tapyrus/secp256k1/ruby'
8
6
  autoload :Native, 'tapyrus/secp256k1/native'
9
7
  autoload :RFC6979, 'tapyrus/secp256k1/rfc6979'
10
-
11
8
  end
12
-
13
9
  end
@@ -3,7 +3,6 @@
3
3
 
4
4
  module Tapyrus
5
5
  module Secp256k1
6
-
7
6
  # binding for secp256k1 (https://github.com/chaintope/tapyrus-core/tree/v0.4.0/src/secp256k1)
8
7
  # tag: v0.4.0
9
8
  # this is not included by default, to enable set shared object path to ENV['SECP256K1_LIB_PATH']
@@ -80,8 +79,8 @@ module Tapyrus
80
79
  priv_key = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, SecureRandom.random_bytes(32))
81
80
  ret = secp256k1_ec_seckey_verify(context, priv_key)
82
81
  end
83
- private_key = priv_key.read_string(32).bth
84
- [private_key , generate_pubkey_in_context(context, private_key, compressed: compressed) ]
82
+ private_key = priv_key.read_string(32).bth
83
+ [private_key, generate_pubkey_in_context(context, private_key, compressed: compressed)]
85
84
  end
86
85
  end
87
86
 
@@ -92,9 +91,7 @@ module Tapyrus
92
91
  end
93
92
 
94
93
  def generate_pubkey(priv_key, compressed: true)
95
- with_context do |context|
96
- generate_pubkey_in_context(context, priv_key, compressed: compressed)
97
- end
94
+ with_context { |context| generate_pubkey_in_context(context, priv_key, compressed: compressed) }
98
95
  end
99
96
 
100
97
  # sign data.
@@ -152,13 +149,14 @@ module Tapyrus
152
149
 
153
150
  pubkey = FFI::MemoryPointer.new(:uchar, 65)
154
151
  pubkey_len = FFI::MemoryPointer.new(:uint64)
155
- result = if compressed
156
- pubkey_len.put_uint64(0, 33)
157
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
158
- else
159
- pubkey_len.put_uint64(0, 65)
160
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
161
- end
152
+ result =
153
+ if compressed
154
+ pubkey_len.put_uint64(0, 33)
155
+ secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
156
+ else
157
+ pubkey_len.put_uint64(0, 65)
158
+ secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
159
+ end
162
160
  raise 'error serialize pubkey' unless result || pubkey_len.read_uint64 > 0
163
161
  pubkey.read_string(pubkey_len.read_uint64).bth
164
162
  end
@@ -196,7 +194,9 @@ module Tapyrus
196
194
 
197
195
  signature = FFI::MemoryPointer.new(:uchar, 64)
198
196
  msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
199
- raise 'Failed to generate schnorr signature.' unless secp256k1_schnorr_sign(context, signature, msg32, secret, nil, nil) == 1
197
+ unless secp256k1_schnorr_sign(context, signature, msg32, secret, nil, nil) == 1
198
+ raise 'Failed to generate schnorr signature.'
199
+ end
200
200
  signature.read_string(64)
201
201
  end
202
202
  end
@@ -241,7 +241,6 @@ module Tapyrus
241
241
  result == 1
242
242
  end
243
243
  end
244
-
245
244
  end
246
245
  end
247
246
  end
@@ -1,7 +1,6 @@
1
1
  module Tapyrus
2
2
  module Secp256k1
3
3
  module RFC6979
4
-
5
4
  INITIAL_V = '0101010101010101010101010101010101010101010101010101010101010101'.htb
6
5
  INITIAL_K = '0000000000000000000000000000000000000000000000000000000000000000'.htb
7
6
  ZERO_B = '00'.htb
@@ -17,17 +16,22 @@ module Tapyrus
17
16
  def generate_rfc6979_nonce(key_data, extra_entropy)
18
17
  v = INITIAL_V # 3.2.b
19
18
  k = INITIAL_K # 3.2.c
19
+
20
20
  # 3.2.d
21
21
  k = Tapyrus.hmac_sha256(k, v + ZERO_B + key_data + extra_entropy)
22
+
22
23
  # 3.2.e
23
24
  v = Tapyrus.hmac_sha256(k, v)
25
+
24
26
  # 3.2.f
25
27
  k = Tapyrus.hmac_sha256(k, v + ONE_B + key_data + extra_entropy)
28
+
26
29
  # 3.2.g
27
30
  v = Tapyrus.hmac_sha256(k, v)
31
+
28
32
  # 3.2.h
29
33
  t = ''
30
- 10000.times do
34
+ 10_000.times do
31
35
  v = Tapyrus.hmac_sha256(k, v)
32
36
  t = (t + v)
33
37
  t_num = t.bth.to_i(16)
@@ -37,7 +41,6 @@ module Tapyrus
37
41
  end
38
42
  raise 'A valid nonce was not found.'
39
43
  end
40
-
41
44
  end
42
45
  end
43
- end
46
+ end
@@ -1,10 +1,8 @@
1
1
  module Tapyrus
2
2
  module Secp256k1
3
-
4
3
  # secp256 module using ecdsa gem
5
4
  # https://github.com/DavidEGrayson/ruby_ecdsa
6
5
  module Ruby
7
-
8
6
  module_function
9
7
 
10
8
  # generate ec private key and public key
@@ -58,7 +56,7 @@ module Tapyrus
58
56
  end
59
57
  end
60
58
 
61
- alias :valid_sig? :verify_sig
59
+ alias valid_sig? verify_sig
62
60
 
63
61
  module_function :valid_sig?
64
62
 
@@ -68,7 +66,8 @@ module Tapyrus
68
66
  # @return [Boolean] If valid public key return true, otherwise false.
69
67
  def parse_ec_pubkey?(pubkey, allow_hybrid = false)
70
68
  begin
71
- point = ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1, allow_hybrid: allow_hybrid)
69
+ point =
70
+ ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1, allow_hybrid: allow_hybrid)
72
71
  ECDSA::Group::Secp256k1.valid_public_key?(point)
73
72
  rescue ECDSA::Format::DecodeError
74
73
  false
@@ -80,11 +79,11 @@ module Tapyrus
80
79
  def repack_pubkey(pubkey)
81
80
  p = pubkey.htb
82
81
  case p[0]
83
- when "\x06", "\x07"
84
- p[0] = "\x04"
85
- p
86
- else
87
- pubkey.htb
82
+ when "\x06", "\x07"
83
+ p[0] = "\x04"
84
+ p
85
+ else
86
+ pubkey.htb
88
87
  end
89
88
  end
90
89
 
@@ -104,7 +103,8 @@ module Tapyrus
104
103
  e = ECDSA.normalize_digest(data, GROUP.bit_length)
105
104
  s = point_field.mod(point_field.inverse(nonce) * (e + r * private_key))
106
105
 
107
- if s > (GROUP.order / 2) # convert low-s
106
+ if s > (GROUP.order / 2)
107
+ # convert low-s
108
108
  s = GROUP.order - s
109
109
  end
110
110
 
@@ -125,8 +125,6 @@ module Tapyrus
125
125
  false
126
126
  end
127
127
  end
128
-
129
128
  end
130
-
131
129
  end
132
130
  end
@@ -1,6 +1,5 @@
1
1
  module Tapyrus
2
2
  module SLIP39
3
-
4
3
  WORDS = File.readlines("#{__dir__}/slip39/wordlist/english.txt").map(&:strip)
5
4
 
6
5
  module_function
@@ -15,37 +14,53 @@ module Tapyrus
15
14
 
16
15
  # The length of the radix in bits.
17
16
  RADIX_BITS = 10
17
+
18
18
  # The number of words in the wordlist.
19
- RADIX = 2 ** RADIX_BITS
19
+ RADIX = 2**RADIX_BITS
20
+
20
21
  # The length of the random identifier in bits.
21
22
  ID_LENGTH_BITS = 15
23
+
22
24
  # The length of the iteration exponent in bits.
23
25
  ITERATION_EXP_LENGTH_BITS = 5
26
+
24
27
  # The length of the random identifier and iteration exponent in words.
25
28
  ID_EXP_LENGTH_WORDS = bits_to_words(ID_LENGTH_BITS + ITERATION_EXP_LENGTH_BITS)
29
+
26
30
  # The maximum number of shares that can be created.
27
31
  MAX_SHARE_COUNT = 16
32
+
28
33
  # The length of the RS1024 checksum in words.
29
34
  CHECKSUM_LENGTH_WORDS = 3
35
+
30
36
  # The length of the digest of the shared secret in bytes.
31
37
  DIGEST_LENGTH_BYTES = 4
38
+
32
39
  # The customization string used in the RS1024 checksum and in the PBKDF2 salt.
33
40
  CUSTOMIZATION_STRING = 'shamir'.bytes
41
+
34
42
  # The length of the mnemonic in words without the share value.
35
43
  METADATA_LENGTH_WORDS = ID_EXP_LENGTH_WORDS + 2 + CHECKSUM_LENGTH_WORDS
44
+
36
45
  # The minimum allowed entropy of the master secret.
37
46
  MIN_STRENGTH_BITS = 128
47
+
38
48
  # The minimum allowed length of the mnemonic in words.
39
49
  MIN_MNEMONIC_LENGTH_WORDS = METADATA_LENGTH_WORDS + bits_to_words(MIN_STRENGTH_BITS)
50
+
40
51
  # The minimum number of iterations to use in PBKDF2.
41
- BASE_ITERATION_COUNT = 10000
52
+ BASE_ITERATION_COUNT = 10_000
53
+
42
54
  # The number of rounds to use in the Feistel cipher.
43
55
  ROUND_COUNT = 4
56
+
44
57
  # The index of the share containing the shared secret.
45
58
  SECRET_INDEX = 255
59
+
46
60
  # The index of the share containing the digest of the shared secret.
47
61
  DIGEST_INDEX = 254
48
62
 
63
+ # prettier-ignore
49
64
  EXP_TABLE = [
50
65
  1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19,
51
66
  53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34,
@@ -66,6 +81,7 @@ module Tapyrus
66
81
  57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246
67
82
  ]
68
83
 
84
+ # prettier-ignore
69
85
  LOG_TABLE = [
70
86
  0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
71
87
  100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28,
@@ -88,6 +104,5 @@ module Tapyrus
88
104
 
89
105
  autoload :SSS, 'tapyrus/slip39/sss'
90
106
  autoload :Share, 'tapyrus/slip39/share'
91
-
92
107
  end
93
- end
108
+ end
@@ -1,36 +1,35 @@
1
1
  module Tapyrus
2
2
  module SLIP39
3
-
4
3
  # Share of Shamir's Secret Sharing Scheme
5
4
  class Share
6
-
7
- attr_accessor :id # 15 bits, Integer
8
- attr_accessor :iteration_exp # 5 bits, Integer
9
- attr_accessor :group_index # 4 bits, Integer
10
- attr_accessor :group_threshold # 4 bits, Integer
11
- attr_accessor :group_count # 4 bits, Integer
12
- attr_accessor :member_index # 4 bits, Integer
5
+ attr_accessor :id # 15 bits, Integer
6
+ attr_accessor :iteration_exp # 5 bits, Integer
7
+ attr_accessor :group_index # 4 bits, Integer
8
+ attr_accessor :group_threshold # 4 bits, Integer
9
+ attr_accessor :group_count # 4 bits, Integer
10
+ attr_accessor :member_index # 4 bits, Integer
13
11
  attr_accessor :member_threshold # 4 bits, Integer
14
- attr_accessor :value # 8n bits, hex string.
15
- attr_accessor :checksum # 30 bits, Integer
12
+ attr_accessor :value # 8n bits, hex string.
13
+ attr_accessor :checksum # 30 bits, Integer
16
14
 
17
15
  # Recover Share from the mnemonic words
18
16
  # @param [Array{String}] words the mnemonic words
19
17
  # @return [Tapyrus::SLIP39::Share] a share
20
18
  def self.from_words(words)
21
19
  raise ArgumentError, 'Mnemonics should be an array of strings' unless words.is_a?(Array)
22
- indices = words.map do |word|
23
- index = Tapyrus::SLIP39::WORDS.index(word.downcase)
24
- raise IndexError, 'word not found in words list.' unless index
25
- index
26
- end
20
+ indices =
21
+ words.map do |word|
22
+ index = Tapyrus::SLIP39::WORDS.index(word.downcase)
23
+ raise IndexError, 'word not found in words list.' unless index
24
+ index
25
+ end
27
26
 
28
27
  raise ArgumentError, 'Invalid mnemonic length.' if indices.size < MIN_MNEMONIC_LENGTH_WORDS
29
28
  raise ArgumentError, 'Invalid mnemonic checksum.' unless verify_rs1024_checksum(indices)
30
29
 
31
30
  padding_length = (RADIX_BITS * (indices.size - METADATA_LENGTH_WORDS)) % 16
32
31
  raise ArgumentError, 'Invalid mnemonic length.' if padding_length > 8
33
- data = indices.map{|i|i.to_s(2).rjust(10, '0')}.join
32
+ data = indices.map { |i| i.to_s(2).rjust(10, '0') }.join
34
33
 
35
34
  s = self.new
36
35
  s.id = data[0...ID_LENGTH_BITS].to_i(2)
@@ -38,14 +37,17 @@ module Tapyrus
38
37
  s.group_index = data[20...24].to_i(2)
39
38
  s.group_threshold = data[24...28].to_i(2) + 1
40
39
  s.group_count = data[28...32].to_i(2) + 1
41
- raise ArgumentError, "Invalid mnemonic. Group threshold(#{s.group_threshold}) cannot be greater than group count(#{s.group_count})." if s.group_threshold > s.group_count
40
+ if s.group_threshold > s.group_count
41
+ raise ArgumentError,
42
+ "Invalid mnemonic. Group threshold(#{s.group_threshold}) cannot be greater than group count(#{s.group_count})."
43
+ end
42
44
  s.member_index = data[32...36].to_i(2)
43
45
  s.member_threshold = data[36...40].to_i(2) + 1
44
46
  value_length = data.length - 70
45
47
  start_index = 40 + padding_length
46
48
  end_index = start_index + value_length - padding_length
47
49
  padding_value = data[40...(40 + padding_length)]
48
- raise ArgumentError, "Invalid mnemonic. padding must only zero." unless padding_value.to_i(2) == 0
50
+ raise ArgumentError, 'Invalid mnemonic. padding must only zero.' unless padding_value.to_i(2) == 0
49
51
  s.value = data[start_index...end_index].to_i(2).to_even_length_hex
50
52
  s.checksum = data[(40 + value_length)..-1].to_i(2)
51
53
  s
@@ -55,25 +57,34 @@ module Tapyrus
55
57
  # @return [Array[String]] array of mnemonic word.
56
58
  def to_words
57
59
  indices = build_word_indices
58
- indices.map{|index| Tapyrus::SLIP39::WORDS[index]}
60
+ indices.map { |index| Tapyrus::SLIP39::WORDS[index] }
59
61
  end
60
62
 
61
63
  # Calculate checksum using current fields
62
64
  # @return [Integer] checksum
63
65
  def calculate_checksum
64
66
  indices = build_word_indices(false)
65
- create_rs1024_checksum(indices).map{|i|i.to_bits(10)}.join.to_i(2)
67
+ create_rs1024_checksum(indices).map { |i| i.to_bits(10) }.join.to_i(2)
66
68
  end
67
69
 
68
70
  def self.rs1024_polymod(values)
69
- gen = [0xe0e040, 0x1c1c080, 0x3838100, 0x7070200, 0xe0e0009, 0x1c0c2412, 0x38086c24, 0x3090fc48, 0x21b1f890, 0x3f3f120]
71
+ gen = [
72
+ 0xe0e040,
73
+ 0x1c1c080,
74
+ 0x3838100,
75
+ 0x7070200,
76
+ 0xe0e0009,
77
+ 0x1c0c2412,
78
+ 0x38086c24,
79
+ 0x3090fc48,
80
+ 0x21b1f890,
81
+ 0x3f3f120
82
+ ]
70
83
  chk = 1
71
84
  values.each do |v|
72
85
  b = (chk >> 20)
73
86
  chk = (chk & 0xfffff) << 10 ^ v
74
- 10.times do |i|
75
- chk ^= (((b >> i) & 1 == 1) ? gen[i] : 0)
76
- end
87
+ 10.times { |i| chk ^= (((b >> i) & 1 == 1) ? gen[i] : 0) }
77
88
  end
78
89
  chk
79
90
  end
@@ -89,14 +100,16 @@ module Tapyrus
89
100
  s << group_index.to_bits(4)
90
101
  s << (group_threshold - 1).to_bits(4)
91
102
  s << (group_count - 1).to_bits(4)
92
- raise StandardError, "Group threshold(#{group_threshold}) cannot be greater than group count(#{group_count})." if group_threshold > group_count
103
+ if group_threshold > group_count
104
+ raise StandardError, "Group threshold(#{group_threshold}) cannot be greater than group count(#{group_count})."
105
+ end
93
106
  s << member_index.to_bits(4)
94
107
  s << (member_threshold - 1).to_bits(4)
95
108
  value_length = value.to_i(16).bit_length
96
109
  padding_length = RADIX_BITS - (value_length % RADIX_BITS)
97
110
  s << value.to_i(16).to_bits(value_length + padding_length)
98
111
  s << checksum.to_bits(30) if include_checksum
99
- s.chars.each_slice(10).map{|index| index.join.to_i(2)}
112
+ s.chars.each_slice(10).map { |index| index.join.to_i(2) }
100
113
  end
101
114
 
102
115
  # Verify RS1024 checksum
@@ -112,11 +125,10 @@ module Tapyrus
112
125
  def create_rs1024_checksum(data)
113
126
  values = CUSTOMIZATION_STRING + data + Array.new(CHECKSUM_LENGTH_WORDS, 0)
114
127
  polymod = Tapyrus::SLIP39::Share.rs1024_polymod(values) ^ 1
115
- CHECKSUM_LENGTH_WORDS.times.to_a.reverse.map {|i|(polymod >> (10 * i)) & 1023 }
128
+ CHECKSUM_LENGTH_WORDS.times.to_a.reverse.map { |i| (polymod >> (10 * i)) & 1023 }
116
129
  end
117
130
 
118
131
  private_class_method :verify_rs1024_checksum
119
-
120
132
  end
121
133
  end
122
- end
134
+ end