tapyrus 0.1.0 → 0.2.0

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