tapyrus 0.2.7 → 0.2.8

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