tapyrus 0.2.4 → 0.2.9

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 (118) 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 +14 -9
  12. data/lib/schnorr/sign_to_contract.rb +51 -0
  13. data/lib/schnorr/signature.rb +3 -6
  14. data/lib/tapyrus.rb +8 -30
  15. data/lib/tapyrus/base58.rb +7 -6
  16. data/lib/tapyrus/bip175.rb +67 -0
  17. data/lib/tapyrus/block.rb +1 -2
  18. data/lib/tapyrus/block_header.rb +15 -9
  19. data/lib/tapyrus/bloom_filter.rb +5 -3
  20. data/lib/tapyrus/chain_params.rb +1 -4
  21. data/lib/tapyrus/chainparams/dev.yml +3 -2
  22. data/lib/tapyrus/chainparams/prod.yml +3 -2
  23. data/lib/tapyrus/constants.rb +29 -23
  24. data/lib/tapyrus/errors.rb +1 -3
  25. data/lib/tapyrus/ext.rb +1 -1
  26. data/lib/tapyrus/ext/ecdsa.rb +4 -4
  27. data/lib/tapyrus/ext/json_parser.rb +1 -4
  28. data/lib/tapyrus/ext_key.rb +44 -32
  29. data/lib/tapyrus/key.rb +31 -35
  30. data/lib/tapyrus/key_path.rb +15 -12
  31. data/lib/tapyrus/logger.rb +20 -16
  32. data/lib/tapyrus/merkle_tree.rb +19 -20
  33. data/lib/tapyrus/message.rb +14 -16
  34. data/lib/tapyrus/message/addr.rb +1 -7
  35. data/lib/tapyrus/message/base.rb +0 -3
  36. data/lib/tapyrus/message/block.rb +2 -9
  37. data/lib/tapyrus/message/block_transaction_request.rb +3 -6
  38. data/lib/tapyrus/message/block_transactions.rb +2 -6
  39. data/lib/tapyrus/message/block_txn.rb +0 -4
  40. data/lib/tapyrus/message/cmpct_block.rb +1 -7
  41. data/lib/tapyrus/message/error.rb +1 -4
  42. data/lib/tapyrus/message/fee_filter.rb +1 -4
  43. data/lib/tapyrus/message/filter_add.rb +0 -4
  44. data/lib/tapyrus/message/filter_clear.rb +0 -4
  45. data/lib/tapyrus/message/filter_load.rb +2 -5
  46. data/lib/tapyrus/message/get_addr.rb +0 -4
  47. data/lib/tapyrus/message/get_block_txn.rb +0 -4
  48. data/lib/tapyrus/message/get_blocks.rb +0 -3
  49. data/lib/tapyrus/message/get_data.rb +1 -4
  50. data/lib/tapyrus/message/get_headers.rb +1 -3
  51. data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
  52. data/lib/tapyrus/message/headers.rb +0 -4
  53. data/lib/tapyrus/message/headers_parser.rb +3 -8
  54. data/lib/tapyrus/message/inv.rb +1 -4
  55. data/lib/tapyrus/message/inventories_parser.rb +2 -7
  56. data/lib/tapyrus/message/inventory.rb +12 -5
  57. data/lib/tapyrus/message/mem_pool.rb +0 -4
  58. data/lib/tapyrus/message/merkle_block.rb +4 -9
  59. data/lib/tapyrus/message/network_addr.rb +7 -6
  60. data/lib/tapyrus/message/not_found.rb +0 -3
  61. data/lib/tapyrus/message/ping.rb +0 -3
  62. data/lib/tapyrus/message/pong.rb +0 -3
  63. data/lib/tapyrus/message/prefilled_tx.rb +0 -4
  64. data/lib/tapyrus/message/reject.rb +0 -3
  65. data/lib/tapyrus/message/send_cmpct.rb +1 -3
  66. data/lib/tapyrus/message/send_headers.rb +0 -3
  67. data/lib/tapyrus/message/tx.rb +0 -4
  68. data/lib/tapyrus/message/ver_ack.rb +1 -5
  69. data/lib/tapyrus/message/version.rb +2 -5
  70. data/lib/tapyrus/mnemonic.rb +17 -15
  71. data/lib/tapyrus/network.rb +0 -2
  72. data/lib/tapyrus/network/connection.rb +0 -3
  73. data/lib/tapyrus/network/message_handler.rb +61 -60
  74. data/lib/tapyrus/network/peer.rb +13 -12
  75. data/lib/tapyrus/network/peer_discovery.rb +3 -5
  76. data/lib/tapyrus/network/pool.rb +12 -12
  77. data/lib/tapyrus/node.rb +1 -1
  78. data/lib/tapyrus/node/cli.rb +12 -14
  79. data/lib/tapyrus/node/configuration.rb +1 -3
  80. data/lib/tapyrus/node/spv.rb +2 -3
  81. data/lib/tapyrus/opcodes.rb +9 -7
  82. data/lib/tapyrus/out_point.rb +5 -5
  83. data/lib/tapyrus/rpc.rb +1 -0
  84. data/lib/tapyrus/rpc/http_server.rb +21 -22
  85. data/lib/tapyrus/rpc/request_handler.rb +42 -44
  86. data/lib/tapyrus/rpc/tapyrus_core_client.rb +67 -25
  87. data/lib/tapyrus/script/color.rb +20 -2
  88. data/lib/tapyrus/script/multisig.rb +13 -12
  89. data/lib/tapyrus/script/script.rb +104 -67
  90. data/lib/tapyrus/script/script_error.rb +1 -4
  91. data/lib/tapyrus/script/script_interpreter.rb +439 -399
  92. data/lib/tapyrus/script/tx_checker.rb +20 -10
  93. data/lib/tapyrus/secp256k1.rb +0 -4
  94. data/lib/tapyrus/secp256k1/native.rb +14 -15
  95. data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
  96. data/lib/tapyrus/secp256k1/ruby.rb +10 -12
  97. data/lib/tapyrus/slip39.rb +20 -5
  98. data/lib/tapyrus/slip39/share.rb +41 -29
  99. data/lib/tapyrus/slip39/sss.rb +101 -57
  100. data/lib/tapyrus/store.rb +1 -3
  101. data/lib/tapyrus/store/chain_entry.rb +0 -4
  102. data/lib/tapyrus/store/db.rb +0 -2
  103. data/lib/tapyrus/store/db/level_db.rb +5 -9
  104. data/lib/tapyrus/store/spv_chain.rb +11 -17
  105. data/lib/tapyrus/tx.rb +45 -37
  106. data/lib/tapyrus/tx_builder.rb +158 -0
  107. data/lib/tapyrus/tx_in.rb +1 -6
  108. data/lib/tapyrus/tx_out.rb +2 -7
  109. data/lib/tapyrus/util.rb +20 -7
  110. data/lib/tapyrus/validation.rb +12 -11
  111. data/lib/tapyrus/version.rb +1 -1
  112. data/lib/tapyrus/wallet/account.rb +22 -18
  113. data/lib/tapyrus/wallet/base.rb +12 -9
  114. data/lib/tapyrus/wallet/db.rb +6 -9
  115. data/lib/tapyrus/wallet/master_key.rb +2 -4
  116. data/tapyrusrb.gemspec +13 -16
  117. metadata +22 -31
  118. data/.travis.yml +0 -12
@@ -1,5 +1,4 @@
1
1
  module Tapyrus
2
-
3
2
  # Base58Check encoding
4
3
  # https://en.bitcoin.it/wiki/Base58Check_encoding
5
4
  module Base58
@@ -23,16 +22,18 @@ module Tapyrus
23
22
  # decode base58 string to hex value.
24
23
  def decode(base58_val)
25
24
  int_val = 0
26
- base58_val.reverse.split(//).each_with_index do |char,index|
27
- raise ArgumentError, 'Value passed not a valid Base58 String.' if (char_index = ALPHABET.index(char)).nil?
28
- int_val += char_index * (SIZE ** index)
29
- end
25
+ base58_val
26
+ .reverse
27
+ .split(//)
28
+ .each_with_index do |char, index|
29
+ raise ArgumentError, 'Value passed not a valid Base58 String.' if (char_index = ALPHABET.index(char)).nil?
30
+ int_val += char_index * (SIZE**index)
31
+ end
30
32
  s = int_val.to_even_length_hex
31
33
  s = '' if s == '00'
32
34
  leading_zero_bytes = (base58_val.match(/^([1]+)/) ? $1 : '').size
33
35
  s = ('00' * leading_zero_bytes) + s if leading_zero_bytes > 0
34
36
  s
35
37
  end
36
-
37
38
  end
38
39
  end
@@ -0,0 +1,67 @@
1
+ module Tapyrus
2
+ # Key generation based on BIP-175
3
+ #
4
+ # @example
5
+ #
6
+ # master = Tapyrus::ExtKey.from_base58('xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73')
7
+ # bip175 = Tapyrus::BIP175.from_private_key(master)
8
+ # bip175 << "foo"
9
+ # bip175 << "bar"
10
+ # bip175.addr
11
+ # > 1C7f322izqMqLzZzfzkPAjxBzprxDi47Yf
12
+ #
13
+ # @see https://github.com/bitcoin/bips/blob/master/bip-0175.mediawiki
14
+ class BIP175
15
+ PURPOSE_TYPE = 175
16
+
17
+ attr_accessor :payment_base
18
+
19
+ def initialize
20
+ @contracts = []
21
+ end
22
+
23
+ # @param key [Tapyrus::ExtKey] master private extended key
24
+ def self.from_ext_key(key)
25
+ raise ArgumentError, 'key should be Tapyrus::ExtKey' unless key.is_a?(Tapyrus::ExtKey)
26
+ raise ArgumentError, 'key should be master private extended key' unless key.master?
27
+ new.tap do |bip175|
28
+ bip175.payment_base =
29
+ key.derive(PURPOSE_TYPE, true).derive(Tapyrus.chain_params.bip44_coin_type, true).ext_pubkey
30
+ end
31
+ end
32
+
33
+ # @param key [Tapyrus::ExtPubkey] contract base public key
34
+ def self.from_ext_pubkey(key)
35
+ raise ArgumentError, 'key should be Tapyrus::ExtPubkey' unless key.is_a?(Tapyrus::ExtPubkey)
36
+ new.tap { |bip175| bip175.payment_base = key }
37
+ end
38
+
39
+ # Add value of hashed contract
40
+ # @param contract [String] contract information
41
+ def add(contract)
42
+ @contracts << Tapyrus.sha256(contract)
43
+ self
44
+ end
45
+ alias << add
46
+
47
+ # Return combined hash consist of payment_base and contract hashes
48
+ # @return [String] contract_hash
49
+ def combined_hash
50
+ hashes = @contracts.map { |c| c.bth }.sort
51
+ concatenated_hash = [payment_base.to_base58].concat(hashes).join
52
+ Tapyrus.sha256(concatenated_hash)
53
+ end
54
+
55
+ # Return pay-to-contract extended public key
56
+ # @return [Tapyrus::ExtPubkey] extended public key
57
+ def pubkey
58
+ # Split every 2 bytes
59
+ paths = combined_hash.unpack('S>*')
60
+ paths.inject(payment_base) { |key, p| key.derive(p) }
61
+ end
62
+
63
+ def addr
64
+ pubkey.addr
65
+ end
66
+ end
67
+ end
data/lib/tapyrus/block.rb CHANGED
@@ -37,6 +37,5 @@ module Tapyrus
37
37
  def height
38
38
  transactions.first.in.first.out_point.index
39
39
  end
40
-
41
40
  end
42
- end
41
+ end
@@ -1,18 +1,17 @@
1
1
  module Tapyrus
2
-
3
2
  # Block Header
4
3
  class BlockHeader
5
4
  include Tapyrus::HexConverter
6
5
  extend Tapyrus::Util
7
6
  include Tapyrus::Util
8
7
 
9
- X_FILED_TYPES = {none: 0, aggregate_pubkey: 1}
8
+ X_FILED_TYPES = { none: 0, aggregate_pubkey: 1 }
10
9
 
11
10
  attr_accessor :features
12
11
  attr_accessor :prev_hash
13
12
  attr_accessor :merkle_root
14
13
  attr_accessor :im_merkle_root # merkel root of immulable merkle tree which consist of immutable txid.
15
- attr_accessor :time # unix timestamp
14
+ attr_accessor :time # unix timestamp
16
15
  attr_accessor :x_field_type
17
16
  attr_accessor :x_field
18
17
  attr_accessor :proof
@@ -33,7 +32,16 @@ module Tapyrus
33
32
  features, prev_hash, merkle_root, im_merkle_root, time, x_filed_type = buf.read(105).unpack('Va32a32a32Vc')
34
33
  x_field = buf.read(unpack_var_int_from_io(buf)) unless x_filed_type == X_FILED_TYPES[:none]
35
34
  proof = buf.read(unpack_var_int_from_io(buf))
36
- new(features, prev_hash.bth, merkle_root.bth, im_merkle_root.bth, time, x_filed_type, x_field ? x_field.bth : x_field, proof.bth)
35
+ new(
36
+ features,
37
+ prev_hash.bth,
38
+ merkle_root.bth,
39
+ im_merkle_root.bth,
40
+ time,
41
+ x_filed_type,
42
+ x_field ? x_field.bth : x_field,
43
+ proof.bth
44
+ )
37
45
  end
38
46
 
39
47
  def to_payload(skip_proof = false)
@@ -87,9 +95,9 @@ module Tapyrus
87
95
  # @return [Boolean] if valid return true, otherwise false
88
96
  def valid_x_field?
89
97
  case x_field_type
90
- when X_FILED_TYPES[:none] then
98
+ when X_FILED_TYPES[:none]
91
99
  x_field.nil?
92
- when X_FILED_TYPES[:aggregate_pubkey] then
100
+ when X_FILED_TYPES[:aggregate_pubkey]
93
101
  Tapyrus::Key.new(pubkey: x_field).fully_valid_pubkey?
94
102
  else
95
103
  false
@@ -111,7 +119,5 @@ module Tapyrus
111
119
  def size
112
120
  to_payload.bytesize
113
121
  end
114
-
115
122
  end
116
-
117
- end
123
+ end
@@ -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 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,38 @@ 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
199
 
200
+ def master?
201
+ depth == 0 && number == 0 && parent_fingerprint == '00000000'
202
+ end
196
203
  end
197
204
 
198
205
  # BIP-32 Extended public key
@@ -208,8 +215,7 @@ module Tapyrus
208
215
 
209
216
  # serialize extended pubkey
210
217
  def to_payload
211
- version.htb << [depth].pack('C') <<
212
- parent_fingerprint.htb << [number].pack('N') << chain_code << pub.htb
218
+ version.htb << [depth].pack('C') << parent_fingerprint.htb << [number].pack('N') << chain_code << pub.htb
213
219
  end
214
220
 
215
221
  def pub
@@ -269,7 +275,7 @@ module Tapyrus
269
275
  l = Tapyrus.hmac_sha512(chain_code, data)
270
276
  left = l[0..31].bth.to_i(16)
271
277
  raise 'invalid key' if left >= CURVE_ORDER
272
- p1 = Tapyrus::Secp256k1::GROUP.generator.multiply_by_scalar(left)
278
+ p1 = Tapyrus::Key.new(priv_key: left.to_s(16), key_type: Tapyrus::Key::TYPES[:uncompressed]).to_point
273
279
  p2 = Tapyrus::Key.new(pubkey: pubkey, key_type: key_type).to_point
274
280
  new_key.pubkey = (p1 + p2).to_hex
275
281
  new_key.chain_code = l[32..-1]
@@ -309,10 +315,14 @@ module Tapyrus
309
315
  ext_pubkey.parent_fingerprint = buf.read(4).bth
310
316
  ext_pubkey.number = buf.read(4).unpack('N').first
311
317
  if ext_pubkey.depth == 0
312
- raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT unless ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
318
+ unless ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT
319
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_FINGERPRINT
320
+ end
313
321
  raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_INDEX if ext_pubkey.number > 0
314
322
  end
315
- raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_DEPTH if ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_pubkey.depth > 0
323
+ if ext_pubkey.parent_fingerprint == ExtKey::MASTER_FINGERPRINT && ext_pubkey.depth > 0
324
+ raise ArgumentError, Errors::Messages::INVALID_BIP32_ZERO_DEPTH
325
+ end
316
326
  ext_pubkey.chain_code = buf.read(32)
317
327
  ext_pubkey.pubkey = Tapyrus::Key.new(pubkey: buf.read(33).bth).pubkey
318
328
  ext_pubkey
@@ -336,12 +346,12 @@ module Tapyrus
336
346
  def self.version_from_purpose(purpose)
337
347
  v = purpose - Tapyrus::HARDENED_THRESHOLD
338
348
  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
349
+ when 49
350
+ Tapyrus.chain_params.bip49_pubkey_p2wpkh_p2sh_version
351
+ when 84
352
+ Tapyrus.chain_params.bip84_pubkey_p2wpkh_version
353
+ else
354
+ Tapyrus.chain_params.extended_pubkey_version
345
355
  end
346
356
  end
347
357
 
@@ -351,6 +361,8 @@ module Tapyrus
351
361
  [p.bip49_pubkey_p2wpkh_p2sh_version, p.bip84_pubkey_p2wpkh_version, p.extended_pubkey_version].include?(version)
352
362
  end
353
363
 
364
+ def master?
365
+ depth == 0 && number == 0 && parent_fingerprint == '00000000'
366
+ end
354
367
  end
355
-
356
368
  end