tapyrus 0.1.0 → 0.2.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -14
  3. data/exe/tapyrusrbd +2 -2
  4. data/lib/openassets/util.rb +2 -4
  5. data/lib/schnorr.rb +83 -0
  6. data/lib/schnorr/signature.rb +38 -0
  7. data/lib/tapyrus.rb +9 -11
  8. data/lib/tapyrus/block.rb +1 -32
  9. data/lib/tapyrus/block_header.rb +7 -6
  10. data/lib/tapyrus/chain_params.rb +13 -26
  11. data/lib/tapyrus/chainparams/{testnet.yml → dev.yml} +7 -9
  12. data/lib/tapyrus/chainparams/{mainnet.yml → prod.yml} +7 -10
  13. data/lib/tapyrus/constants.rb +12 -34
  14. data/lib/tapyrus/ext.rb +5 -0
  15. data/lib/tapyrus/ext/json_parser.rb +47 -0
  16. data/lib/tapyrus/ext_key.rb +5 -10
  17. data/lib/tapyrus/key.rb +57 -29
  18. data/lib/tapyrus/message.rb +2 -2
  19. data/lib/tapyrus/message/base.rb +1 -0
  20. data/lib/tapyrus/message/block.rb +3 -3
  21. data/lib/tapyrus/message/cmpct_block.rb +3 -5
  22. data/lib/tapyrus/message/tx.rb +2 -2
  23. data/lib/tapyrus/network/peer.rb +1 -15
  24. data/lib/tapyrus/node/cli.rb +15 -11
  25. data/lib/tapyrus/node/configuration.rb +1 -1
  26. data/lib/tapyrus/node/spv.rb +1 -1
  27. data/lib/tapyrus/opcodes.rb +5 -0
  28. data/lib/tapyrus/out_point.rb +1 -1
  29. data/lib/tapyrus/rpc/request_handler.rb +3 -3
  30. data/lib/tapyrus/rpc/tapyrus_core_client.rb +17 -15
  31. data/lib/tapyrus/script/color.rb +79 -0
  32. data/lib/tapyrus/script/multisig.rb +0 -27
  33. data/lib/tapyrus/script/script.rb +74 -89
  34. data/lib/tapyrus/script/script_error.rb +8 -14
  35. data/lib/tapyrus/script/script_interpreter.rb +65 -86
  36. data/lib/tapyrus/script/tx_checker.rb +16 -4
  37. data/lib/tapyrus/secp256k1.rb +1 -0
  38. data/lib/tapyrus/secp256k1/rfc6979.rb +43 -0
  39. data/lib/tapyrus/secp256k1/ruby.rb +5 -31
  40. data/lib/tapyrus/store/chain_entry.rb +1 -0
  41. data/lib/tapyrus/tx.rb +18 -160
  42. data/lib/tapyrus/tx_in.rb +4 -11
  43. data/lib/tapyrus/tx_out.rb +2 -1
  44. data/lib/tapyrus/util.rb +8 -0
  45. data/lib/tapyrus/validation.rb +1 -6
  46. data/lib/tapyrus/version.rb +1 -1
  47. data/lib/tapyrus/wallet/account.rb +1 -0
  48. data/lib/tapyrus/wallet/master_key.rb +1 -0
  49. data/tapyrusrb.gemspec +3 -3
  50. metadata +42 -39
  51. data/lib/tapyrus/chainparams/regtest.yml +0 -38
  52. data/lib/tapyrus/descriptor.rb +0 -147
  53. data/lib/tapyrus/script_witness.rb +0 -38
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.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-05 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bech32
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 1.0.3
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 1.0.3
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: daemon-spawn
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -136,20 +122,6 @@ dependencies:
136
122
  - - ">="
137
123
  - !ruby/object:Gem::Version
138
124
  version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rest-client
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
125
  - !ruby/object:Gem::Dependency
154
126
  name: iniparse
155
127
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +192,20 @@ dependencies:
220
192
  - - ">="
221
193
  - !ruby/object:Gem::Version
222
194
  version: 5.2.3
195
+ - !ruby/object:Gem::Dependency
196
+ name: json_pure
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: 2.3.1
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: 2.3.1
223
209
  - !ruby/object:Gem::Dependency
224
210
  name: leveldb-native
225
211
  requirement: !ruby/object:Gem::Requirement
@@ -252,16 +238,16 @@ dependencies:
252
238
  name: rake
253
239
  requirement: !ruby/object:Gem::Requirement
254
240
  requirements:
255
- - - "~>"
241
+ - - ">="
256
242
  - !ruby/object:Gem::Version
257
- version: '10.0'
243
+ version: 12.3.3
258
244
  type: :development
259
245
  prerelease: false
260
246
  version_requirements: !ruby/object:Gem::Requirement
261
247
  requirements:
262
- - - "~>"
248
+ - - ">="
263
249
  - !ruby/object:Gem::Version
264
- version: '10.0'
250
+ version: 12.3.3
265
251
  - !ruby/object:Gem::Dependency
266
252
  name: rspec
267
253
  requirement: !ruby/object:Gem::Requirement
@@ -290,6 +276,20 @@ dependencies:
290
276
  - - ">="
291
277
  - !ruby/object:Gem::Version
292
278
  version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: webmock
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - "~>"
284
+ - !ruby/object:Gem::Version
285
+ version: '3.0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - "~>"
291
+ - !ruby/object:Gem::Version
292
+ version: '3.0'
293
293
  description: "[WIP]The implementation of Tapyrus Protocol for Ruby."
294
294
  email:
295
295
  - azuchi@chaintope.com
@@ -317,17 +317,19 @@ files:
317
317
  - lib/openassets/marker_output.rb
318
318
  - lib/openassets/payload.rb
319
319
  - lib/openassets/util.rb
320
+ - lib/schnorr.rb
321
+ - lib/schnorr/signature.rb
320
322
  - lib/tapyrus.rb
321
323
  - lib/tapyrus/base58.rb
322
324
  - lib/tapyrus/block.rb
323
325
  - lib/tapyrus/block_header.rb
324
326
  - lib/tapyrus/bloom_filter.rb
325
327
  - lib/tapyrus/chain_params.rb
326
- - lib/tapyrus/chainparams/mainnet.yml
327
- - lib/tapyrus/chainparams/regtest.yml
328
- - lib/tapyrus/chainparams/testnet.yml
328
+ - lib/tapyrus/chainparams/dev.yml
329
+ - lib/tapyrus/chainparams/prod.yml
329
330
  - lib/tapyrus/constants.rb
330
- - lib/tapyrus/descriptor.rb
331
+ - lib/tapyrus/ext.rb
332
+ - lib/tapyrus/ext/json_parser.rb
331
333
  - lib/tapyrus/ext_key.rb
332
334
  - lib/tapyrus/key.rb
333
335
  - lib/tapyrus/key_path.rb
@@ -394,14 +396,15 @@ files:
394
396
  - lib/tapyrus/rpc/http_server.rb
395
397
  - lib/tapyrus/rpc/request_handler.rb
396
398
  - lib/tapyrus/rpc/tapyrus_core_client.rb
399
+ - lib/tapyrus/script/color.rb
397
400
  - lib/tapyrus/script/multisig.rb
398
401
  - lib/tapyrus/script/script.rb
399
402
  - lib/tapyrus/script/script_error.rb
400
403
  - lib/tapyrus/script/script_interpreter.rb
401
404
  - lib/tapyrus/script/tx_checker.rb
402
- - lib/tapyrus/script_witness.rb
403
405
  - lib/tapyrus/secp256k1.rb
404
406
  - lib/tapyrus/secp256k1/native.rb
407
+ - lib/tapyrus/secp256k1/rfc6979.rb
405
408
  - lib/tapyrus/secp256k1/ruby.rb
406
409
  - lib/tapyrus/slip39.rb
407
410
  - lib/tapyrus/slip39/share.rb
@@ -1,38 +0,0 @@
1
- --- !ruby/object:Tapyrus::ChainParams
2
- network: "regtest"
3
- magic_head: "fabfb5da"
4
- message_magic: "Bitcoin Signed Message:\n"
5
- address_version: "6f"
6
- p2sh_version: "c4"
7
- bech32_hrp: 'bcrt'
8
- privkey_version: "ef"
9
- extended_privkey_version: "04358394"
10
- extended_pubkey_version: "043587cf"
11
- bip49_pubkey_p2wpkh_p2sh_version: "044a5262"
12
- bip49_pubkey_p2wsh_p2sh_version: "024285ef"
13
- bip49_privkey_p2wpkh_p2sh_version: "044a4e28"
14
- bip49_privkey_p2wsh_p2sh_version: "024285b5"
15
- bip84_pubkey_p2wpkh_version: "045f1cf6"
16
- bip84_pubkey_p2wsh_version: "02575483"
17
- bip84_privkey_p2wpkh_version: "045f18bc"
18
- bip84_privkey_p2wsh_version: "02575048"
19
- default_port: 18444
20
- protocol_version: 70013
21
- retarget_interval: 2016
22
- retarget_time: 1209600 # 2 weeks
23
- target_spacing: 600 # block interval
24
- max_money: 21000000
25
- bip34_height: 0
26
- genesis_hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
27
- proof_of_work_limit: 0x207fffff
28
- dns_seeds:
29
- genesis:
30
- hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
31
- merkle_root: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
32
- time: 1296688602
33
- nonce: 2
34
- bits: 0x207fffff
35
- version: 1
36
- prev_hash: "0000000000000000000000000000000000000000000000000000000000000000"
37
- bip44_coin_type: 1
38
- dust_relay_fee: 3600
@@ -1,147 +0,0 @@
1
- module Tapyrus
2
-
3
- module Descriptor
4
-
5
- include Tapyrus::Opcodes
6
-
7
- # generate P2PK output for the given public key.
8
- # @param [String] key private key or public key with hex format
9
- # @return [Tapyrus::Script] P2PK script.
10
- def pk(key)
11
- Tapyrus::Script.new << extract_pubkey(key) << OP_CHECKSIG
12
- end
13
-
14
- # generate P2PKH output for the given public key.
15
- # @param [String] key private key or public key with hex format.
16
- # @return [Tapyrus::Script] P2PKH script.
17
- def pkh(key)
18
- Tapyrus::Script.to_p2pkh(Tapyrus.hash160(extract_pubkey(key)))
19
- end
20
-
21
- # generate P2PKH output for the given public key.
22
- # @param [String] key private key or public key with hex format.
23
- # @return [Tapyrus::Script] P2WPKH script.
24
- def wpkh(key)
25
- pubkey = extract_pubkey(key)
26
- raise ArgumentError, "Uncompressed key are not allowed." unless compressed_key?(pubkey)
27
- Tapyrus::Script.to_p2wpkh(Tapyrus.hash160(pubkey))
28
- end
29
-
30
- # generate P2SH embed the argument.
31
- # @param [String or Script] script script to be embed.
32
- # @return [Tapyrus::Script] P2SH script.
33
- def sh(script)
34
- script = script.to_hex if script.is_a?(Tapyrus::Script)
35
- raise ArgumentError, "P2SH script is too large, 547 bytes is larger than #{Tapyrus::MAX_SCRIPT_ELEMENT_SIZE} bytes." if script.htb.bytesize > Tapyrus::MAX_SCRIPT_ELEMENT_SIZE
36
- Tapyrus::Script.to_p2sh(Tapyrus.hash160(script))
37
- end
38
-
39
- # generate P2WSH embed the argument.
40
- # @param [String or Script] script script to be embed.
41
- # @return [Tapyrus::Script] P2WSH script.
42
- def wsh(script)
43
- script = Tapyrus::Script(script.htb) if script.is_a?(String)
44
- raise ArgumentError, "P2SH script is too large, 547 bytes is larger than #{Tapyrus::MAX_SCRIPT_ELEMENT_SIZE} bytes." if script.to_payload.bytesize > Tapyrus::MAX_SCRIPT_ELEMENT_SIZE
45
- raise ArgumentError, "Uncompressed key are not allowed." if script.get_pubkeys.any?{|p|!compressed_key?(p)}
46
- Tapyrus::Script.to_p2wsh(script)
47
- end
48
-
49
- # an alias for the collection of `pk(KEY)` and `pkh(KEY)`.
50
- # If the key is compressed, it also includes `wpkh(KEY)` and `sh(wpkh(KEY))`.
51
- # @param [String] key private key or public key with hex format.
52
- # @return [Array[Tapyrus::Script]]
53
- def combo(key)
54
- result = [pk(key), pkh(key)]
55
- pubkey = extract_pubkey(key)
56
- if compressed_key?(pubkey)
57
- result << wpkh(key)
58
- result << sh(result.last)
59
- end
60
- result
61
- end
62
-
63
- # generate multisig output for given keys.
64
- # @param [Integer] threshold the threshold of multisig.
65
- # @param [Array[String]] keys an array of keys.
66
- # @return [Tapyrus::Script] multisig script.
67
- def multi(threshold, *keys, sort: false)
68
- raise ArgumentError, 'Multisig threshold is not valid.' unless threshold.is_a?(Integer)
69
- raise ArgumentError, 'Multisig threshold cannot be 0, must be at least 1.' unless threshold > 0
70
- raise ArgumentError, 'Multisig threshold cannot be larger than the number of keys.' if threshold > keys.size
71
- raise ArgumentError, 'Multisig must have between 1 and 16 keys, inclusive.' if keys.size > 16
72
- pubkeys = keys.map{|key| extract_pubkey(key) }
73
- Tapyrus::Script.to_multisig_script(threshold, pubkeys, sort: sort)
74
- end
75
-
76
- # generate sorted multisig output for given keys.
77
- # @param [Integer] threshold the threshold of multisig.
78
- # @param [Array[String]] keys an array of keys.
79
- # @return [Tapyrus::Script] multisig script.
80
- def sortedmulti(threshold, *keys)
81
- multi(threshold, *keys, sort: true)
82
- end
83
-
84
- private
85
-
86
- # extract public key from KEY format.
87
- # @param [String] key KEY string.
88
- # @return [String] public key.
89
- def extract_pubkey(key)
90
- if key.start_with?('[') # BIP32 fingerprint
91
- raise ArgumentError, 'Invalid key origin.' if key.count('[') > 1 || key.count(']') > 1
92
- info = key[1...key.index(']')] # TODO
93
- fingerprint, *paths = info.split('/')
94
- raise ArgumentError, 'Fingerprint is not hex.' unless fingerprint.valid_hex?
95
- raise ArgumentError, 'Fingerprint is not 4 bytes.' unless fingerprint.size == 8
96
- key = key[(key.index(']') + 1)..-1]
97
- else
98
- raise ArgumentError, 'Invalid key origin.' if key.include?(']')
99
- end
100
-
101
- # check BIP32 derivation path
102
- key, *paths = key.split('/')
103
-
104
- if key.start_with?('xprv')
105
- key = Tapyrus::ExtKey.from_base58(key)
106
- key = derive_path(key, paths, true) if paths
107
- elsif key.start_with?('xpub')
108
- key = Tapyrus::ExtPubkey.from_base58(key)
109
- key = derive_path(key, paths, false) if paths
110
- else
111
- begin
112
- key = Tapyrus::Key.from_wif(key)
113
- rescue ArgumentError
114
- key_type = compressed_key?(key) ? Tapyrus::Key::TYPES[:compressed] : Tapyrus::Key::TYPES[:uncompressed]
115
- key = Tapyrus::Key.new(pubkey: key, key_type: key_type)
116
- end
117
- end
118
- key = key.is_a?(Tapyrus::Key) ? key : key.key
119
- raise ArgumentError, 'Invalid pubkey.' unless key.fully_valid_pubkey?
120
- key.pubkey
121
- end
122
-
123
- def compressed_key?(key)
124
- %w(02 03).include?(key[0..1]) && [key].pack("H*").bytesize == 33
125
- end
126
-
127
- def derive_path(key, paths, is_private)
128
- paths.each do |path|
129
- raise ArgumentError, 'xpub can not derive hardened key.' if !is_private && path.end_with?("'")
130
- if is_private
131
- hardened = path.end_with?("'")
132
- path = hardened ? path[0..-2] : path
133
- raise ArgumentError, 'Key path value is not a valid value.' unless path =~ /^[0-9]+$/
134
- raise ArgumentError, 'Key path value is out of range.' if !hardened && path.to_i >= Tapyrus::HARDENED_THRESHOLD
135
- key = key.derive(path.to_i, hardened)
136
- else
137
- raise ArgumentError, 'Key path value is not a valid value.' unless path =~ /^[0-9]+$/
138
- raise ArgumentError, 'Key path value is out of range.' if path.to_i >= Tapyrus::HARDENED_THRESHOLD
139
- key = key.derive(path.to_i)
140
- end
141
- end
142
- key
143
- end
144
-
145
- end
146
-
147
- end
@@ -1,38 +0,0 @@
1
- module Tapyrus
2
-
3
- # witness
4
- class ScriptWitness
5
-
6
- attr_reader :stack
7
-
8
- def initialize(stack = [])
9
- @stack = stack
10
- end
11
-
12
- def self.parse_from_payload(payload)
13
- buf = payload.is_a?(StringIO) ? payload : StringIO.new(payload)
14
- size = Tapyrus.unpack_var_int_from_io(buf)
15
- stack = size.times.map do
16
- buf.read(Tapyrus.unpack_var_int_from_io(buf))
17
- end
18
- self.new(stack)
19
- end
20
-
21
- def empty?
22
- stack.empty?
23
- end
24
-
25
- def to_payload
26
- p = Tapyrus.pack_var_int(stack.size)
27
- p << stack.map { |s|
28
- Tapyrus.pack_var_int(s.bytesize) << s
29
- }.join
30
- end
31
-
32
- def to_s
33
- stack.map{|s|s.bth}.join(' ')
34
- end
35
-
36
- end
37
-
38
- end