tapyrus 0.2.2 → 0.2.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1abedf80b636e2bfd80db4617ca9f92e703148f07e59c08b14860c13ac57689
4
- data.tar.gz: 21b478051eb01354e410475e15761f24773fe164fcd9abf3307acb231b5c8ae3
3
+ metadata.gz: 15ad1708c6361b20c98632d45f81d2ad445114b45123fbc5acc2c8da2fc01c1b
4
+ data.tar.gz: 74a754e7045b6a2475eeb913b79acee31fe882ac8bda39918c774017e1d0cb4e
5
5
  SHA512:
6
- metadata.gz: 61c8cc2439074666abffc6ff85ffaa40811e8e0992edb19846876dabf9a300f4822af522a6f621271f310a9b1ea3f9429f30e86452d29b0f2216052568a72a6a
7
- data.tar.gz: f3845015c030c7ccf915700eb45ac2f743c3f0c19dbe077c72c4afe19327252d1f3a64ffb29c1f5790997c8f6f2317930ab5ae99a894687a86f6381154c5429d
6
+ metadata.gz: e71234f42f008a4e81ab87652ffe1e386303b0e0a731fce90a84e7e77fb40ef6549f777762970d6dbbb380d8f6d6fa5f1d4af2a7e42038d8a210221317eb6d33
7
+ data.tar.gz: 21c7fbefd23b4fb42d4dc9400917c2d42650db8b7dfaa09bb5d96ed14f2d04a707fa749e8964c69b6c297261875f30f2e0a0a6e2b7c1a702e607e9bce537fd49
data/.travis.yml CHANGED
@@ -1,8 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.4.6
4
- - 2.5.5
5
- - 2.6.3
3
+ - 2.4.10
4
+ - 2.5.8
5
+ - 2.6.6
6
+ - 2.7.2
7
+ - 3.0.0
6
8
  addons:
7
9
  apt:
8
10
  packages:
data/README.md CHANGED
@@ -12,7 +12,7 @@ Tapyrusrb supports following feature:
12
12
  * Tapyrus script interpreter
13
13
  * De/serialization of Tapyrus protocol network messages
14
14
  * De/serialization of blocks and transactions
15
- * Key generation and verification for ECDSA, including [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) supports.
15
+ * Key generation and verification for Schnorr and ECDSA (including [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) supports).
16
16
  * ECDSA signature(RFC6979 -Deterministic ECDSA, LOW-S, LOW-R support)
17
17
  * [WIP] SPV node
18
18
  * [WIP] 0ff-chain protocol
data/lib/tapyrus.rb CHANGED
@@ -118,14 +118,7 @@ module Tapyrus
118
118
 
119
119
  # get opcode
120
120
  def opcode
121
- case encoding
122
- when Encoding::ASCII_8BIT
123
- each_byte.next
124
- when Encoding::US_ASCII
125
- ord
126
- else
127
- to_i
128
- end
121
+ force_encoding(Encoding::ASCII_8BIT).ord
129
122
  end
130
123
 
131
124
  def opcode?
@@ -29,7 +29,7 @@ module ::ECDSA::Format::PointOctetString
29
29
  when 4
30
30
  decode_uncompressed string, group
31
31
  when 6..7
32
- raise DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord unless allow_hybrid
32
+ raise ECDSA::Format::DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord unless allow_hybrid
33
33
  decode_uncompressed string, group if allow_hybrid
34
34
  else
35
35
  raise ECDSA::Format::DecodeError, 'Unrecognized start byte for point octet string: 0x%x' % string[0].ord
data/lib/tapyrus/key.rb CHANGED
@@ -96,10 +96,13 @@ module Tapyrus
96
96
  # @return [String] signature data with binary format
97
97
  def sign(data, low_r = true, extra_entropy = nil, algo: :ecdsa)
98
98
  raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
99
- if algo == :ecdsa
99
+ case algo
100
+ when :ecdsa
100
101
  sign_ecdsa(data, low_r, extra_entropy)
102
+ when :schnorr
103
+ secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: algo)
101
104
  else
102
- sign_schnorr(data)
105
+ false
103
106
  end
104
107
  end
105
108
 
@@ -112,11 +115,8 @@ module Tapyrus
112
115
  return false unless valid_pubkey?
113
116
  begin
114
117
  raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
115
- if algo == :ecdsa
116
- verify_ecdsa_sig(sig, origin)
117
- else
118
- verify_schnorr_sig(sig, origin)
119
- end
118
+ sig = ecdsa_signature_parse_der_lax(sig) if algo == :ecdsa
119
+ secp256k1_module.verify_sig(origin, sig, pubkey, algo: algo)
120
120
  rescue Exception
121
121
  false
122
122
  end
@@ -225,13 +225,7 @@ module Tapyrus
225
225
 
226
226
  # fully validate whether this is a valid public key (more expensive than IsValid())
227
227
  def fully_valid_pubkey?(allow_hybrid = false)
228
- return false unless valid_pubkey?
229
- begin
230
- point = ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1, allow_hybrid: allow_hybrid)
231
- ECDSA::Group::Secp256k1.valid_public_key?(point)
232
- rescue ECDSA::Format::DecodeError
233
- false
234
- end
228
+ valid_pubkey? && secp256k1_module.parse_ec_pubkey?(pubkey, allow_hybrid)
235
229
  end
236
230
 
237
231
  private
@@ -292,34 +286,18 @@ module Tapyrus
292
286
 
293
287
  # generate ecdsa signature
294
288
  def sign_ecdsa(data, low_r, extra_entropy)
295
- sig = secp256k1_module.sign_data(data, priv_key, extra_entropy)
289
+ sig = secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: :ecdsa)
296
290
  if low_r && !sig_has_low_r?(sig)
297
291
  counter = 1
298
292
  until sig_has_low_r?(sig)
299
293
  extra_entropy = [counter].pack('I*').bth.ljust(64, '0').htb
300
- sig = secp256k1_module.sign_data(data, priv_key, extra_entropy)
294
+ sig = secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: :ecdsa)
301
295
  counter += 1
302
296
  end
303
297
  end
304
298
  sig
305
299
  end
306
300
 
307
- # generate schnorr signature
308
- def sign_schnorr(msg)
309
- Schnorr.sign(msg, priv_key.to_i(16)).encode
310
- end
311
-
312
- # verify ecdsa signature
313
- def verify_ecdsa_sig(sig, message)
314
- sig = ecdsa_signature_parse_der_lax(sig)
315
- secp256k1_module.verify_sig(message, sig, pubkey)
316
- end
317
-
318
- # verify schnorr signature
319
- def verify_schnorr_sig(sig, message)
320
- Schnorr.valid_sig?(message, sig, pubkey.htb)
321
- end
322
-
323
301
  end
324
302
 
325
303
  end
@@ -43,6 +43,14 @@ module Tapyrus
43
43
  true
44
44
  end
45
45
 
46
+ def hash
47
+ to_payload.hash
48
+ end
49
+
50
+ def eql?(other)
51
+ to_payload.eql?(other.to_payload)
52
+ end
53
+
46
54
  private
47
55
 
48
56
  def initialize(type, payload)
@@ -53,11 +61,11 @@ module Tapyrus
53
61
 
54
62
  module ColoredOutput
55
63
  def colored?
56
- script_pubkey.cp2pkh? || script_pubkey.cp2sh?
64
+ script_pubkey.colored?
57
65
  end
58
66
 
59
67
  def color_id
60
- @color_id ||= ColorIdentifier.parse_from_payload(script_pubkey.chunks[0].pushed_data)
68
+ @color_id ||= script_pubkey.color_id
61
69
  end
62
70
 
63
71
  def reissuable?
@@ -75,6 +75,18 @@ module Tapyrus
75
75
  end
76
76
  end
77
77
 
78
+ # Remove color identifier from cp2pkh or cp2sh
79
+ # @param [ColorIdentifier] color identifier
80
+ # @return [Script] P2PKH or P2SH script
81
+ # @raise [RuntimeError] if script is neither cp2pkh nor cp2sh
82
+ def remove_color
83
+ raise RuntimeError, 'Only cp2pkh and cp2sh can remove color' unless cp2pkh? or cp2sh?
84
+
85
+ Tapyrus::Script.new.tap do |s|
86
+ s.chunks = self.chunks[2..-1]
87
+ end
88
+ end
89
+
78
90
  def get_multisig_pubkeys
79
91
  num = Tapyrus::Opcodes.opcode_to_small_int(chunks[-2].bth.to_i(16))
80
92
  (1..num).map{ |i| chunks[i].pushed_data }
@@ -118,6 +130,12 @@ module Tapyrus
118
130
  Tapyrus::Script.to_p2pkh(hex)
119
131
  when Tapyrus.chain_params.p2sh_version
120
132
  Tapyrus::Script.to_p2sh(hex)
133
+ when Tapyrus.chain_params.cp2pkh_version
134
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
135
+ Tapyrus::Script.to_cp2pkh(color, hex[66..-1])
136
+ when Tapyrus.chain_params.cp2sh_version
137
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
138
+ Tapyrus::Script.to_cp2sh(color, hex[66..-1])
121
139
  else
122
140
  throw e
123
141
  end
@@ -214,6 +232,8 @@ module Tapyrus
214
232
  (chunks.size == 1 || chunks[1].opcode <= OP_16)
215
233
  end
216
234
 
235
+ # Return whether this script is a CP2PKH format script or not.
236
+ # @return [Boolean] true if this script is cp2pkh, otherwise false.
217
237
  def cp2pkh?
218
238
  return false unless chunks.size == 7
219
239
  return false unless chunks[0].bytesize == 34
@@ -223,6 +243,8 @@ module Tapyrus
223
243
  (chunks[2..3]+ chunks[5..6]).map(&:ord) && chunks[4].bytesize == 21
224
244
  end
225
245
 
246
+ # Return whether this script is a CP2SH format script or not.
247
+ # @return [Boolean] true if this script is cp2pkh, otherwise false.
226
248
  def cp2sh?
227
249
  return false unless chunks.size == 5
228
250
  return false unless chunks[0].bytesize == 34
@@ -230,6 +252,20 @@ module Tapyrus
230
252
  return false unless chunks[1].ord == OP_COLOR
231
253
  OP_HASH160 == chunks[2].ord && OP_EQUAL == chunks[4].ord && chunks[3].bytesize == 21
232
254
  end
255
+
256
+ # Return whether this script represents colored coin.
257
+ # @return [Boolean] true if this script is colored, otherwise false.
258
+ def colored?
259
+ cp2pkh? || cp2sh?
260
+ end
261
+
262
+ # Return color identifier for this script.
263
+ # @return [ColorIdentifer] color identifier for this script if this script is colored. return nil if this script is not colored.
264
+ def color_id
265
+ return nil unless colored?
266
+
267
+ Tapyrus::Color::ColorIdentifier.parse_from_payload(chunks[0].pushed_data)
268
+ end
233
269
 
234
270
  def op_return_data
235
271
  return nil unless op_return?
@@ -4,8 +4,8 @@
4
4
  module Tapyrus
5
5
  module Secp256k1
6
6
 
7
- # binding for secp256k1 (https://github.com/bitcoin/bitcoin/tree/v0.14.2/src/secp256k1)
8
- # tag: v0.14.2
7
+ # binding for secp256k1 (https://github.com/chaintope/tapyrus-core/tree/v0.4.0/src/secp256k1)
8
+ # tag: v0.4.0
9
9
  # this is not included by default, to enable set shared object path to ENV['SECP256K1_LIB_PATH']
10
10
  # for linux, ENV['SECP256K1_LIB_PATH'] = '/usr/local/lib/libsecp256k1.so'
11
11
  # for mac,
@@ -50,6 +50,8 @@ module Tapyrus
50
50
  attach_function(:secp256k1_ecdsa_signature_parse_der, [:pointer, :pointer, :pointer, :size_t], :int)
51
51
  attach_function(:secp256k1_ecdsa_signature_normalize, [:pointer, :pointer, :pointer], :int)
52
52
  attach_function(:secp256k1_ecdsa_verify, [:pointer, :pointer, :pointer, :pointer], :int)
53
+ attach_function(:secp256k1_schnorr_sign, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int)
54
+ attach_function(:secp256k1_schnorr_verify, [:pointer, :pointer, :pointer, :pointer], :int)
53
55
  end
54
56
 
55
57
  def with_context(flags: (SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN))
@@ -100,7 +102,68 @@ module Tapyrus
100
102
  # @param [String] privkey a private key using sign
101
103
  # @param [String] extra_entropy a extra entropy for rfc6979
102
104
  # @return [String] signature data with binary format
103
- def sign_data(data, privkey, extra_entropy)
105
+ def sign_data(data, privkey, extra_entropy, algo: :ecdsa)
106
+ case algo
107
+ when :ecdsa
108
+ sign_ecdsa(data, privkey, extra_entropy)
109
+ when :schnorr
110
+ sign_schnorr(data, privkey)
111
+ else
112
+ nil
113
+ end
114
+ end
115
+
116
+ # verify signature.
117
+ # @param[String] data a data.
118
+ # @param [String] sig signature data with binary format
119
+ # @param [String] pub_key a public key using verify.
120
+ def verify_sig(data, sig, pub_key, algo: :ecdsa)
121
+ case algo
122
+ when :ecdsa
123
+ verify_ecdsa(data, sig, pub_key)
124
+ when :schnorr
125
+ verify_schnorr(data, sig, pub_key)
126
+ else
127
+ false
128
+ end
129
+ end
130
+
131
+ # # validate whether this is a valid public key (more expensive than IsValid())
132
+ # @param [String] pub_key public key with hex format.
133
+ # @param [Boolean] allow_hybrid whether support hybrid public key.
134
+ # @return [Boolean] If valid public key return true, otherwise false.
135
+ def parse_ec_pubkey?(pub_key, allow_hybrid = false)
136
+ pub_key = pub_key.htb
137
+ return false if !allow_hybrid && ![0x02, 0x03, 0x04].include?(pub_key[0].ord)
138
+ with_context do |context|
139
+ pubkey = FFI::MemoryPointer.new(:uchar, pub_key.bytesize).put_bytes(0, pub_key)
140
+ internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
141
+ result = secp256k1_ec_pubkey_parse(context, internal_pubkey, pubkey, pub_key.bytesize)
142
+ result == 1
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ def generate_pubkey_in_context(context, privkey, compressed: true)
149
+ internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
150
+ result = secp256k1_ec_pubkey_create(context, internal_pubkey, privkey.htb)
151
+ raise 'error creating pubkey' unless result
152
+
153
+ pubkey = FFI::MemoryPointer.new(:uchar, 65)
154
+ 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
162
+ raise 'error serialize pubkey' unless result || pubkey_len.read_uint64 > 0
163
+ pubkey.read_string(pubkey_len.read_uint64).bth
164
+ end
165
+
166
+ def sign_ecdsa(data, privkey, extra_entropy)
104
167
  with_context do |context|
105
168
  secret = FFI::MemoryPointer.new(:uchar, privkey.htb.bytesize).put_bytes(0, privkey.htb)
106
169
  raise 'priv_key invalid' unless secp256k1_ec_seckey_verify(context, secret)
@@ -126,7 +189,19 @@ module Tapyrus
126
189
  end
127
190
  end
128
191
 
129
- def verify_sig(data, sig, pub_key)
192
+ def sign_schnorr(data, privkey)
193
+ with_context do |context|
194
+ secret = FFI::MemoryPointer.new(:uchar, privkey.htb.bytesize).put_bytes(0, privkey.htb)
195
+ raise 'priv_key invalid' unless secp256k1_ec_seckey_verify(context, secret)
196
+
197
+ signature = FFI::MemoryPointer.new(:uchar, 64)
198
+ 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
200
+ signature.read_string(64)
201
+ end
202
+ end
203
+
204
+ def verify_ecdsa(data, sig, pub_key)
130
205
  with_context do |context|
131
206
  return false if data.bytesize == 0
132
207
 
@@ -150,25 +225,23 @@ module Tapyrus
150
225
  end
151
226
  end
152
227
 
153
- private
228
+ def verify_schnorr(data, sig, pub_key)
229
+ with_context do |context|
230
+ return false if data.bytesize == 0
231
+ pubkey = FFI::MemoryPointer.new(:uchar, pub_key.htb.bytesize).put_bytes(0, pub_key.htb)
232
+ internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
233
+ result = secp256k1_ec_pubkey_parse(context, internal_pubkey, pubkey, pubkey.size)
234
+ return false unless result
154
235
 
155
- def generate_pubkey_in_context(context, privkey, compressed: true)
156
- internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
157
- result = secp256k1_ec_pubkey_create(context, internal_pubkey, privkey.htb)
158
- raise 'error creating pubkey' unless result
236
+ signature = FFI::MemoryPointer.new(:uchar, sig.bytesize).put_bytes(0, sig)
159
237
 
160
- pubkey = FFI::MemoryPointer.new(:uchar, 65)
161
- pubkey_len = FFI::MemoryPointer.new(:uint64)
162
- result = if compressed
163
- pubkey_len.put_uint64(0, 33)
164
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
165
- else
166
- pubkey_len.put_uint64(0, 65)
167
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
168
- end
169
- raise 'error serialize pubkey' unless result || pubkey_len.read_uint64 > 0
170
- pubkey.read_string(pubkey_len.read_uint64).bth
238
+ msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
239
+ result = secp256k1_schnorr_verify(context, signature, msg32, internal_pubkey)
240
+
241
+ result == 1
242
+ end
171
243
  end
244
+
172
245
  end
173
246
  end
174
247
  end
@@ -31,7 +31,64 @@ module Tapyrus
31
31
  # @param [String] data a data to be signed with binary format
32
32
  # @param [String] privkey a private key using sign
33
33
  # @return [String] signature data with binary format
34
- def sign_data(data, privkey, extra_entropy)
34
+ def sign_data(data, privkey, extra_entropy, algo: :ecdsa)
35
+ case algo
36
+ when :ecdsa
37
+ sign_ecdsa(data, privkey, extra_entropy)
38
+ when :schnorr
39
+ Schnorr.sign(data, privkey.to_i(16)).encode
40
+ else
41
+ nil
42
+ end
43
+ end
44
+
45
+ # verify signature using public key
46
+ # @param [String] digest a SHA-256 message digest with binary format
47
+ # @param [String] sig a signature for +data+ with binary format
48
+ # @param [String] pubkey a public key corresponding to the private key used for sign
49
+ # @return [Boolean] verify result
50
+ def verify_sig(digest, sig, pubkey, algo: :ecdsa)
51
+ case algo
52
+ when :ecdsa
53
+ verify_ecdsa(digest, sig, pubkey)
54
+ when :schnorr
55
+ Schnorr.valid_sig?(digest, sig, pubkey.htb)
56
+ else
57
+ false
58
+ end
59
+ end
60
+
61
+ alias :valid_sig? :verify_sig
62
+
63
+ module_function :valid_sig?
64
+
65
+ # validate whether this is a valid public key (more expensive than IsValid())
66
+ # @param [String] pubkey public key with hex format.
67
+ # @param [Boolean] allow_hybrid whether support hybrid public key.
68
+ # @return [Boolean] If valid public key return true, otherwise false.
69
+ def parse_ec_pubkey?(pubkey, allow_hybrid = false)
70
+ begin
71
+ point = ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1, allow_hybrid: allow_hybrid)
72
+ ECDSA::Group::Secp256k1.valid_public_key?(point)
73
+ rescue ECDSA::Format::DecodeError
74
+ false
75
+ end
76
+ end
77
+
78
+ # if +pubkey+ is hybrid public key format, it convert uncompressed format.
79
+ # https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html
80
+ def repack_pubkey(pubkey)
81
+ p = pubkey.htb
82
+ case p[0]
83
+ when "\x06", "\x07"
84
+ p[0] = "\x04"
85
+ p
86
+ else
87
+ pubkey.htb
88
+ end
89
+ end
90
+
91
+ def sign_ecdsa(data, privkey, extra_entropy)
35
92
  privkey = privkey.htb
36
93
  private_key = ECDSA::Format::IntegerOctetString.decode(privkey)
37
94
  extra_entropy ||= ''
@@ -59,12 +116,7 @@ module Tapyrus
59
116
  signature
60
117
  end
61
118
 
62
- # verify signature using public key
63
- # @param [String] digest a SHA-256 message digest with binary format
64
- # @param [String] sig a signature for +data+ with binary format
65
- # @param [String] pubkey a public key corresponding to the private key used for sign
66
- # @return [Boolean] verify result
67
- def verify_sig(digest, sig, pubkey)
119
+ def verify_ecdsa(digest, sig, pubkey)
68
120
  begin
69
121
  k = ECDSA::Format::PointOctetString.decode(repack_pubkey(pubkey), GROUP)
70
122
  signature = ECDSA::Format::SignatureDerString.decode(sig)
@@ -74,23 +126,6 @@ module Tapyrus
74
126
  end
75
127
  end
76
128
 
77
- alias :valid_sig? :verify_sig
78
-
79
- module_function :valid_sig?
80
-
81
- # if +pubkey+ is hybrid public key format, it convert uncompressed format.
82
- # https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html
83
- def repack_pubkey(pubkey)
84
- p = pubkey.htb
85
- case p[0]
86
- when "\x06", "\x07"
87
- p[0] = "\x04"
88
- p
89
- else
90
- pubkey.htb
91
- end
92
- end
93
-
94
129
  end
95
130
 
96
131
  end
data/lib/tapyrus/util.rb CHANGED
@@ -113,6 +113,9 @@ module Tapyrus
113
113
  if hex.size == 50 && calc_checksum(hex[0...-8]) == hex[-8..-1]
114
114
  raise 'Invalid version bytes.' unless [Tapyrus.chain_params.address_version, Tapyrus.chain_params.p2sh_version].include?(hex[0..1])
115
115
  [hex[2...-8], hex[0..1]]
116
+ elsif hex.size == 116 && calc_checksum(hex[0...-8]) == hex[-8..-1]
117
+ raise 'Invalid version bytes.' unless [Tapyrus.chain_params.cp2pkh_version, Tapyrus.chain_params.cp2sh_version].include?(hex[0..1])
118
+ [hex[2...-8], hex[0..1]]
116
119
  else
117
120
  raise 'Invalid address.'
118
121
  end
@@ -128,6 +131,18 @@ module Tapyrus
128
131
  OpenSSL::HMAC.digest(DIGEST_NAME_SHA256, key, data)
129
132
  end
130
133
 
134
+ # check whether +addr+ is valid address.
135
+ # @param [String] addr an address
136
+ # @return [Boolean] if valid address return true, otherwise false.
137
+ def valid_address?(addr)
138
+ begin
139
+ Tapyrus::Script.parse_from_addr(addr)
140
+ true
141
+ rescue Exception => e
142
+ false
143
+ end
144
+ end
145
+
131
146
  end
132
147
 
133
148
  module HexConverter
@@ -1,3 +1,3 @@
1
1
  module Tapyrus
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.7"
3
3
  end
data/tapyrusrb.gemspec CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["azuchi"]
11
11
  spec.email = ["azuchi@chaintope.com"]
12
12
 
13
- spec.summary = %q{[WIP]The implementation of Tapyrus Protocol for Ruby.}
14
- spec.description = %q{[WIP]The implementation of Tapyrus Protocol for Ruby.}
13
+ spec.summary = %q{The implementation of Tapyrus Protocol for Ruby.}
14
+ spec.description = %q{The implementation of Tapyrus Protocol for Ruby.}
15
15
  spec.homepage = 'https://github.com/chaintope/tapyrusrb'
16
16
  spec.license = "MIT"
17
17
 
@@ -30,8 +30,6 @@ Gem::Specification.new do |spec|
30
30
  spec.add_runtime_dependency 'eventmachine_httpserver'
31
31
  spec.add_runtime_dependency 'iniparse'
32
32
  spec.add_runtime_dependency 'siphash'
33
- spec.add_runtime_dependency 'protobuf', '3.8.5'
34
- spec.add_runtime_dependency 'scrypt'
35
33
  spec.add_runtime_dependency 'activesupport', '>= 5.2.3'
36
34
  spec.add_runtime_dependency 'json_pure', '>= 2.3.1'
37
35
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapyrus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-10 00:00:00.000000000 Z
11
+ date: 2021-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -150,34 +150,6 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: protobuf
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - '='
158
- - !ruby/object:Gem::Version
159
- version: 3.8.5
160
- type: :runtime
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - '='
165
- - !ruby/object:Gem::Version
166
- version: 3.8.5
167
- - !ruby/object:Gem::Dependency
168
- name: scrypt
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :runtime
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
153
  - !ruby/object:Gem::Dependency
182
154
  name: activesupport
183
155
  requirement: !ruby/object:Gem::Requirement
@@ -290,7 +262,7 @@ dependencies:
290
262
  - - "~>"
291
263
  - !ruby/object:Gem::Version
292
264
  version: '3.0'
293
- description: "[WIP]The implementation of Tapyrus Protocol for Ruby."
265
+ description: The implementation of Tapyrus Protocol for Ruby.
294
266
  email:
295
267
  - azuchi@chaintope.com
296
268
  executables:
@@ -449,8 +421,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
449
421
  - !ruby/object:Gem::Version
450
422
  version: '0'
451
423
  requirements: []
452
- rubygems_version: 3.0.3
424
+ rubygems_version: 3.0.6
453
425
  signing_key:
454
426
  specification_version: 4
455
- summary: "[WIP]The implementation of Tapyrus Protocol for Ruby."
427
+ summary: The implementation of Tapyrus Protocol for Ruby.
456
428
  test_files: []