bitcoinrb 1.9.1 → 1.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9782b433e66eedcc496ac7f8eeeb7000e800065e43ee8f17dd410f639cc2f60
4
- data.tar.gz: c9cdbb34ab9d1a49c46dc7b5e6deb05a007c05f980a2e43c5166e7bee1c732e9
3
+ metadata.gz: a3ee4bbf4cb431d20baab206242d389e127fb9c5a7111d45a4a78acbbbd49c22
4
+ data.tar.gz: faba8ddf3069a8554b31d71c2e7e884df1799fab543ff0696e6c47e87cdc62ab
5
5
  SHA512:
6
- metadata.gz: '0629c12f169b5f513f66df7a5861297e78d173fe64ba8af4ee0b6944e961706078dd999f4d162e6e476c0be570c3229586b13056b321ce66cb7f5007ea4bbf0d'
7
- data.tar.gz: ef78ccff084babb49747ff0f7a3bf32536a3a8cdb180cf85cca4c166ead597e9aa774790df506043970f152c7797baacfb40dc413a0358f77e9aac72404968d4
6
+ metadata.gz: 807dc4bb3bb2eb45a46096bf7e5798eb6a3bb28a9be2c957424baa1adf6cc6f7e19318a9df73dbbc1d4411d0dc0119650e03fc1d56e6b65ea55b97cf4a907781
7
+ data.tar.gz: 4851f4763427b8c76236b7ef9c1f6c99f4a3d54d91b16de5aca4116bb95c65119bc3c7225940be1ae7bc25f9a502c8eaf35f5c585c3e8565c100d8bceb86cd25
data/README.md CHANGED
@@ -19,7 +19,7 @@ Bitcoinrb supports following feature:
19
19
  * [BIP-85](https://github.com/bitcoin/bips/blob/master/bip-0085.mediawiki) Deterministic Entropy From BIP32 Keychains support by `Bitcoin::BIP85Entropy` class.
20
20
  * Schnorr signature([BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki))
21
21
  * Taproot consensus([BIP-341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) and [BIP-342](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki))
22
- * [Output script descriptor](https://github.com/chaintope/bitcoinrb/wiki/Output-Script-Descriptor) ([BIP-380](https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki), [BIP-381](https://github.com/bitcoin/bips/blob/master/bip-0381.mediawiki), [BIP-382](https://github.com/bitcoin/bips/blob/master/bip-0382.mediawiki), [BIP-383](https://github.com/bitcoin/bips/blob/master/bip-0383.mediawiki), [BIP-384](https://github.com/bitcoin/bips/blob/master/bip-0384.mediawiki), [BIP-385](https://github.com/bitcoin/bips/blob/master/bip-0385.mediawiki), [BIP-386](https://github.com/bitcoin/bips/blob/master/bip-0386.mediawiki), [BIP-387](https://github.com/bitcoin/bips/blob/master/bip-0387.mediawiki))
22
+ * [Output script descriptor](https://github.com/chaintope/bitcoinrb/wiki/Output-Script-Descriptor) ([BIP-380](https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki), [BIP-381](https://github.com/bitcoin/bips/blob/master/bip-0381.mediawiki), [BIP-382](https://github.com/bitcoin/bips/blob/master/bip-0382.mediawiki), [BIP-383](https://github.com/bitcoin/bips/blob/master/bip-0383.mediawiki), [BIP-384](https://github.com/bitcoin/bips/blob/master/bip-0384.mediawiki), [BIP-385](https://github.com/bitcoin/bips/blob/master/bip-0385.mediawiki), [BIP-386](https://github.com/bitcoin/bips/blob/master/bip-0386.mediawiki), [BIP-387](https://github.com/bitcoin/bips/blob/master/bip-0387.mediawiki), [BIP-390](https://github.com/bitcoin/bips/blob/master/bip-0390.mediawiki))
23
23
 
24
24
  ## Requirements
25
25
 
data/bitcoinrb.gemspec CHANGED
@@ -26,7 +26,6 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency 'bech32', '>= 1.5.0'
27
27
  spec.add_runtime_dependency 'daemon-spawn'
28
28
  spec.add_runtime_dependency 'thor'
29
- spec.add_runtime_dependency 'leb128', '~> 1.0.0'
30
29
  spec.add_runtime_dependency 'eventmachine_httpserver'
31
30
  spec.add_runtime_dependency 'iniparse'
32
31
  spec.add_runtime_dependency 'siphash'
@@ -0,0 +1,172 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+
4
+ module Bitcoin
5
+ # BIP-321 URI
6
+ # @see https://github.com/bitcoin/bips/blob/master/bip-0321.mediawiki
7
+ class BIP321URI
8
+
9
+ attr_reader :addr
10
+ attr_reader :amount
11
+ attr_reader :label
12
+ attr_reader :message
13
+ attr_reader :pop # proof of payment
14
+ attr_reader :lightning # BOLT11 invoice
15
+ attr_reader :lno # BOLT12 offer
16
+ attr_reader :pay # BIP-351 private address
17
+ attr_reader :sp # BIP-352 silent payment address
18
+ attr_reader :req_pop
19
+ attr_reader :query_addrs
20
+
21
+ attr_reader :other_params
22
+
23
+ # Constructor
24
+ # @param [String] address
25
+ # @param [BigDecimal, Integer] amount
26
+ # @param [String] label
27
+ # @param [String] message
28
+ # @param [Hash] other_params
29
+ # @param [String] pop
30
+ # @param [String] lightning BOLT11 invoice.
31
+ # @param [String] lno BOLT12 offer.
32
+ # @param [String] pay BIP-351 private address.
33
+ # @param [String] sp BIP-352 silent payment address.
34
+ # @param [Boolean] req_pop whether pop is required or not.
35
+ # @param [Array] query_addrs A list of addresses to be placed as query parameters.
36
+ def initialize(address: nil, amount: nil, label: nil, message: nil, other_params: {},
37
+ pop:nil, lightning: nil, lno: nil, pay:nil, sp: nil, req_pop: false, query_addrs: [])
38
+ if address
39
+ Bitcoin::Script.parse_from_addr(address)
40
+ @addr = address
41
+ end
42
+ if amount
43
+ amount = BigDecimal(amount) if amount.is_a?(Integer)
44
+ raise ArgumentError, "amount must be BigDecimal or integer." unless amount.is_a?(BigDecimal)
45
+ @amount = amount
46
+ end
47
+ raise ArgumentError, "label must be string." if label && !label.is_a?(String)
48
+ @label = label
49
+
50
+ raise ArgumentError, "message must be string." if message && !message.is_a?(String)
51
+ @message = message
52
+
53
+ raise ArgumentError, "pop must be string." if pop && !pop.is_a?(String)
54
+ @pop = pop
55
+
56
+ raise ArgumentError, "lightning must be string." if lightning && !lightning.is_a?(String)
57
+ @lightning = lightning
58
+
59
+ raise ArgumentError, "lno must be string." if lno && !lno.is_a?(String)
60
+ @lno = lno
61
+
62
+ raise ArgumentError, "pay must be string." if pay && !pay.is_a?(String)
63
+ @pay = pay
64
+
65
+ if sp
66
+ raise ArgumentError, "sp must be string." unless sp.is_a?(String)
67
+ begin
68
+ Bech32::SilentPaymentAddr.parse(sp)
69
+ @sp = sp
70
+ rescue ArgumentError
71
+ raise ArgumentError, "Invalid sp address specified."
72
+ end
73
+ end
74
+
75
+ raise ArgumentError, 'pop is required, if req_pop is true.' if req_pop && pop.nil?
76
+ @req_pop = req_pop
77
+
78
+ @query_addrs = query_addrs.map do |addr|
79
+ Bitcoin::Script.parse_from_addr(addr)
80
+ addr
81
+ end
82
+
83
+ raise ArgumentError, "other_params must be Hash." unless other_params.is_a?(Hash)
84
+ other_params.keys.each do |key|
85
+ raise ArgumentError, 'An unsupported reqparam is included.' if key.start_with?('req-')
86
+ end
87
+ @other_params = other_params
88
+ end
89
+
90
+ # Parse BIP-321 URI string.
91
+ # @param [String] BIP-321 URI.
92
+ # @return [Bitcoin::BIP321URI]
93
+ # @raise [ArgumentError]
94
+ def self.parse(uri)
95
+ raise ArgumentError, "uri must be string." unless uri.is_a?(String)
96
+ raise ArgumentError, "Invalid uri scheme." unless uri.downcase.start_with?('bitcoin:')
97
+ uri = uri[8..-1]
98
+ addr, params = uri.split('?', 2)
99
+ req_pop = false
100
+ query_addrs = []
101
+ params = if params
102
+ decoded = URI.decode_www_form(params)
103
+ decoded = decoded.map do |k, v|
104
+ if k == 'req-pop'
105
+ req_pop = true
106
+ k = 'pop'
107
+ end
108
+ if %w[bc tb].include?(k.downcase)
109
+ raise ArgumentError, "#{k} not allowed in current network." unless Bitcoin.chain_params.bech32_hrp == k.downcase
110
+ query_addrs << v
111
+ nil
112
+ else
113
+ [k, v]
114
+ end
115
+ end.compact
116
+ keys = decoded.map(&:first)
117
+ duplicate_key = keys.detect { |key| keys.count(key) > 1 }
118
+ raise ArgumentError, "#{duplicate_key} must not appear twice." if duplicate_key
119
+ decoded.to_h.except('')
120
+ else
121
+ {}
122
+ end
123
+ addr = nil if addr.empty?
124
+ amount = params['amount'] ? BigDecimal(params['amount']) : nil
125
+ excluded_keys = %w[amount label message pop lightning lno pay sp]
126
+ others = params.except(*excluded_keys)
127
+ BIP321URI.new(address: addr, amount: amount, label: params['label'], message: params['message'],
128
+ pop: params['pop'], lightning: params['lightning'], lno: params['lno'],
129
+ pay: params['pay'], sp: params['sp'], other_params: others, req_pop: req_pop, query_addrs: query_addrs)
130
+ end
131
+
132
+ # Get all addresses contained in the URI body and query parameters
133
+ # @return [Array] An array of address.
134
+ def addresses
135
+ addrs = []
136
+ addrs << @addr if @addr
137
+ addrs + @query_addrs
138
+ end
139
+
140
+ # Payment amount (satoshi unit)
141
+ # @return [Integer, nil]
142
+ def satoshi
143
+ amount.nil? ? nil : (amount * 100_000_000).to_i
144
+ end
145
+
146
+ def to_s
147
+ uri = 'bitcoin:'
148
+ uri << addr if addr
149
+ base_params = {}
150
+ base_params['amount'] = amount.to_s('f').sub(/\.0+$/, '') if amount
151
+ base_params['label'] = label if label
152
+ base_params['message'] = message if message
153
+ pop_label = req_pop ? 'req-pop' : 'pop'
154
+ base_params[pop_label] = pop if pop
155
+ base_params['lightning'] = lightning if lightning
156
+ base_params['lno'] = lno if lno
157
+ base_params['sp'] = sp if sp
158
+ base_params['pay'] = pay if pay
159
+
160
+ all_params = base_params.merge other_params
161
+ params = all_params.map do |k, v|
162
+ "#{k}=#{CGI.escape(v).gsub('+', '%20')}"
163
+ end.join('&')
164
+ uri << "?#{params}" unless params.empty?
165
+ unless query_addrs.empty?
166
+ uri << '?' unless uri.include?('?')
167
+ uri << query_addrs.map {|addr| "#{Bitcoin.chain_params.bech32_hrp}=#{addr}"}.join('&')
168
+ end
169
+ uri
170
+ end
171
+ end
172
+ end
@@ -565,7 +565,6 @@ module Bitcoin
565
565
  return set_error(SCRIPT_ERR_STACK_SIZE) if stack.size + alt_stack.size > MAX_STACK_SIZE
566
566
  end
567
567
  rescue Exception => e
568
- puts e
569
568
  return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
570
569
  end
571
570
 
@@ -6,8 +6,6 @@ module Bitcoin
6
6
  # transaction output
7
7
  class TxOut
8
8
 
9
- include OpenAssets::MarkerOutput
10
-
11
9
  attr_accessor :value
12
10
  attr_accessor :script_pubkey
13
11
 
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "1.9.1"
2
+ VERSION = "1.10.0"
3
3
  end
data/lib/bitcoin.rb CHANGED
@@ -11,7 +11,6 @@ require 'base64'
11
11
  require 'observer'
12
12
  require 'tmpdir'
13
13
  require 'merkle'
14
- require_relative 'openassets'
15
14
 
16
15
  module Bitcoin
17
16
 
@@ -64,6 +63,8 @@ module Bitcoin
64
63
  autoload :Taproot, 'bitcoin/taproot'
65
64
  autoload :SilentPayment, 'bitcoin/silent_payment'
66
65
  autoload :BIP324, 'bitcoin/bip324'
66
+ autoload :BIP321URI, 'bitcoin/bip321_uri'
67
+ autoload :BIP353, 'bitcoin/bip353'
67
68
 
68
69
  require_relative 'bitcoin/constants'
69
70
  require_relative 'bitcoin/ext/ecdsa'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitcoinrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.1
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-11-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ecdsa_ext
@@ -93,20 +93,6 @@ dependencies:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: leb128
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: 1.0.0
103
- type: :runtime
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: 1.0.0
110
96
  - !ruby/object:Gem::Dependency
111
97
  name: eventmachine_httpserver
112
98
  requirement: !ruby/object:Gem::Requirement
@@ -275,6 +261,7 @@ files:
275
261
  - exe/bitcoinrbd
276
262
  - lib/bitcoin.rb
277
263
  - lib/bitcoin/base58.rb
264
+ - lib/bitcoin/bip321_uri.rb
278
265
  - lib/bitcoin/bip324.rb
279
266
  - lib/bitcoin/bip324/cipher.rb
280
267
  - lib/bitcoin/bip324/ell_swift_pubkey.rb
@@ -442,10 +429,6 @@ files:
442
429
  - lib/bitcoin/wallet/db.rb
443
430
  - lib/bitcoin/wallet/master_key.rb
444
431
  - lib/bitcoin/wallet/utxo.rb
445
- - lib/openassets.rb
446
- - lib/openassets/marker_output.rb
447
- - lib/openassets/payload.rb
448
- - lib/openassets/util.rb
449
432
  homepage: https://github.com/chaintope/bitcoinrb
450
433
  licenses:
451
434
  - MIT
@@ -464,7 +447,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
464
447
  - !ruby/object:Gem::Version
465
448
  version: '0'
466
449
  requirements: []
467
- rubygems_version: 3.6.9
450
+ rubygems_version: 3.6.2
468
451
  specification_version: 4
469
452
  summary: The implementation of Bitcoin Protocol for Ruby.
470
453
  test_files: []
@@ -1,20 +0,0 @@
1
- module OpenAssets
2
-
3
- module MarkerOutput
4
-
5
- # whether this output is marker output for open assets.
6
- def open_assets_marker?
7
- return false unless script_pubkey.op_return?
8
- !oa_payload.nil?
9
- end
10
-
11
- # get open asset payload.
12
- # @return [OpenAssets::Payload] open asset payload.
13
- def oa_payload
14
- return nil unless script_pubkey.op_return?
15
- Payload.parse_from_payload(script_pubkey.op_return_data)
16
- end
17
-
18
- end
19
-
20
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenAssets
4
-
5
- MARKER = "\x4f\x41"
6
- VERSION = "\x01\x00"
7
-
8
- # the open assets payload
9
- class Payload
10
-
11
- attr_accessor :quantities
12
- attr_accessor :metadata
13
-
14
- def initialize(quantities = [], metadata = '')
15
- @quantities = quantities
16
- @metadata = metadata
17
- end
18
-
19
- # parse open assets payload
20
- # @return [Payload] a open assets payload object, if payload is invalid, return nil.
21
- def self.parse_from_payload(payload)
22
- buf = StringIO.new(payload)
23
- marker = buf.read(2)
24
- version = buf.read(2)
25
- return nil if marker != MARKER || version != VERSION
26
- count = Bitcoin.unpack_var_int_from_io(buf)
27
- return nil unless count
28
- quantities = []
29
- count.times do
30
- quantities << LEB128.decode_unsigned(buf, buf.pos)
31
- end
32
- metadata_length = Bitcoin.unpack_var_int_from_io(buf)
33
- return nil if metadata_length.nil? || buf.length < metadata_length + buf.pos
34
- metadata = buf.read(metadata_length).each_byte.map(&:chr).join
35
- new(quantities, metadata)
36
- rescue
37
- # LEB128#decode_unsigned raise 'undefined method `unpack' for nil:NilClass'
38
- # for invalid format such as "018f8f" (the most significant bit of the last byte should be 0)
39
- nil
40
- end
41
-
42
- # generate binary payload
43
- def to_payload
44
- payload = String.new
45
- payload << MARKER
46
- payload << VERSION
47
- payload << Bitcoin.pack_var_int(quantities.size) << quantities.map{|q| LEB128.encode_unsigned(q).read }.join
48
- payload << Bitcoin.pack_var_int(metadata.length) << metadata.bytes.map{|b| sprintf("%02x", b)}.join.htb
49
- payload
50
- end
51
-
52
- end
53
-
54
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenAssets
4
- module Util
5
- class << self
6
- OA_VERSION_BYTE = '17' # 0x23
7
- OA_VERSION_BYTE_TESTNET = '73' # 0x115
8
-
9
- def script_to_asset_id(script)
10
- hash_to_asset_id(Bitcoin.hash160(script))
11
- end
12
-
13
- private
14
-
15
- def hash_to_asset_id(hash)
16
- hash = oa_version_byte + hash
17
- Bitcoin::Base58.encode(hash + Bitcoin.calc_checksum(hash))
18
- end
19
-
20
- def oa_version_byte
21
- case Bitcoin.chain_params.network
22
- when 'mainnet' then OA_VERSION_BYTE
23
- when 'testnet', 'regtest' then OA_VERSION_BYTE_TESTNET
24
- end
25
- end
26
- end
27
- end
28
- end
data/lib/openassets.rb DELETED
@@ -1,9 +0,0 @@
1
- require 'leb128'
2
-
3
- module OpenAssets
4
-
5
- autoload :MarkerOutput, 'openassets/marker_output'
6
- autoload :Payload, 'openassets/payload'
7
- autoload :Util, 'openassets/util'
8
-
9
- end