bech32 1.5.0 → 1.5.1

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: 368eb6deb6248ddb8f5cbcba18ec90a3ed11b84f60a3de80bb59301eb5c7f1a2
4
- data.tar.gz: a0d8654790ab71f8460eecdbf17248e8acd3748bf2011b94afe32dd079b2248b
3
+ metadata.gz: 22cba51d19b0989743f7f679f187311e735ce018dec53880ddfefebee89f688f
4
+ data.tar.gz: 1cd7be33ab83fd724054202a812f818ed02adb5eb7545baa27e27f6b3358da2e
5
5
  SHA512:
6
- metadata.gz: f3aad0caf6fce5ce425bd0c4e59e934ecfe96bc6fec30cd5c5c7a6ee73f266824c7f90193f4e008ea24f8a65239d13c3763d35c8211d5fa2485cb8317e56d527
7
- data.tar.gz: 4891f6c6f80b6b11cd136637c9fd204070a2fab2b170919b34c976219d9885eb8ed43ba688b2002fcc1db4df4b2755d1b169744cfaea578e64336afa327b4b65
6
+ metadata.gz: dc71997f097a817224b687dc53baf048ba2954cd030f7db50523d7e45121632b7f2edf758ed78298102214c3e3407cf7c7da6b3469a3cde089ade10e8346088d
7
+ data.tar.gz: 6c246c4107a40193d317738bfa4637ccf6452efb48f1d36532570cec1e09681cc17fd374f47361467017e6546f36c4513f2585ed2d4b767939dcef05047ede46
@@ -19,7 +19,7 @@ jobs:
19
19
  runs-on: ubuntu-latest
20
20
  strategy:
21
21
  matrix:
22
- ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4']
22
+ ruby-version: ['3.2', '3.3', '3.4', '4.0']
23
23
 
24
24
  steps:
25
25
  - uses: actions/checkout@v4
@@ -32,3 +32,16 @@ jobs:
32
32
  bundler-cache: true # runs 'bundle install' and caches installed gems automatically
33
33
  - name: Run tests
34
34
  run: bundle exec rake
35
+
36
+ typecheck:
37
+ runs-on: ubuntu-latest
38
+
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+ - name: Set up Ruby
42
+ uses: ruby/setup-ruby@v1
43
+ with:
44
+ ruby-version: '3.4'
45
+ bundler-cache: true
46
+ - name: Run type check
47
+ run: bundle exec steep check
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.4.1
1
+ ruby-4.0.0
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in bech32.gemspec
4
4
  gemspec
5
+
6
+ group :development do
7
+ gem 'steep'
8
+ gem 'rbs'
9
+ end
data/Steepfile ADDED
@@ -0,0 +1,19 @@
1
+ # Steepfile
2
+ target :lib do
3
+ signature "sig"
4
+
5
+ check "lib"
6
+
7
+ library "stringio"
8
+
9
+ # Configure diagnostic severity
10
+ # These errors are from Ruby code patterns that are runtime-safe but hard to express in RBS
11
+ configure_code_diagnostics do |hash|
12
+ # Suppress errors for method calls on potentially nil values
13
+ # The actual code handles nil cases properly at runtime
14
+ hash[Steep::Diagnostic::Ruby::NoMethod] = :hint
15
+ hash[Steep::Diagnostic::Ruby::ArgumentTypeMismatch] = :hint
16
+ hash[Steep::Diagnostic::Ruby::MethodBodyTypeMismatch] = :hint
17
+ hash[Steep::Diagnostic::Ruby::UnannotatedEmptyCollection] = :hint
18
+ end
19
+ end
data/bech32.gemspec CHANGED
@@ -13,8 +13,10 @@ Gem::Specification.new do |spec|
13
13
  spec.description = %q(The implementation of Bech32 encoder and decoder.)
14
14
  spec.homepage = 'https://github.com/azuchi/bech32rb'
15
15
  spec.license = 'MIT'
16
+ spec.metadata = { 'rubygems_mfa_required' => 'true' }
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.files += Dir['sig/**/*.rbs']
18
20
  spec.bindir = 'exe'
19
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
22
  spec.require_paths = ['lib']
@@ -110,37 +110,42 @@ module Bech32
110
110
  buf = ::StringIO.new(data)
111
111
  entries = []
112
112
  until buf.eof?
113
- type, len = buf.read(2).unpack('CC')
113
+ header = buf.read(2)
114
+ raise ArgumentError, "Invalid TLV: truncated header." if header.nil? || header.bytesize < 2
115
+ type, len = header.unpack('CC')
116
+ value = buf.read(len)
117
+ raise ArgumentError, "Invalid TLV: truncated value." if value.nil? ? len > 0 : value.bytesize < len
118
+ value ||= ''
114
119
  case type
115
120
  when TYPE_SPECIAL # special
116
121
  case hrp
117
122
  when NIP19::HRP_PROFILE
118
- entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'pubkey')
123
+ entries << TLVEntry.new(type, value.unpack1('H*'), 'pubkey')
119
124
  when NIP19::HRP_RELAY
120
- entries << TLVEntry.new(type, buf.read(len), 'relay')
125
+ entries << TLVEntry.new(type, value, 'relay')
121
126
  when NIP19::HRP_EVENT
122
- entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'id')
127
+ entries << TLVEntry.new(type, value.unpack1('H*'), 'id')
123
128
  when NIP19::HRP_EVENT_COORDINATE
124
- entries << TLVEntry.new(type, buf.read(len), 'identifier')
129
+ entries << TLVEntry.new(type, value, 'identifier')
125
130
  end
126
131
  when TYPE_RELAY # relay
127
132
  case hrp
128
133
  when NIP19::HRP_PROFILE, NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
129
- entries << TLVEntry.new(type, buf.read(len), 'relay')
134
+ entries << TLVEntry.new(type, value, 'relay')
130
135
  else
131
136
  raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
132
137
  end
133
138
  when TYPE_AUTHOR # author
134
139
  case hrp
135
140
  when NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
136
- entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'author')
141
+ entries << TLVEntry.new(type, value.unpack1('H*'), 'author')
137
142
  else
138
143
  raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
139
144
  end
140
145
  when TYPE_KIND # kind
141
146
  case hrp
142
147
  when NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
143
- entries << TLVEntry.new(type, buf.read(len).unpack1('H*').to_i(16), 'kind')
148
+ entries << TLVEntry.new(type, value.unpack1('H*').to_s.to_i(16), 'kind')
144
149
  else
145
150
  raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
146
151
  end
@@ -28,7 +28,9 @@ module Bech32
28
28
  raise ArgumentError, 'Invalid nip19 string.' if hrp.nil?
29
29
  raise ArgumentError, 'Invalid bech32 spec.' unless spec == Bech32::Encoding::BECH32
30
30
 
31
- entity = Bech32.convert_bits(data, 5, 8, false).pack('C*')
31
+ converted = Bech32.convert_bits(data, 5, 8, false)
32
+ raise ArgumentError, 'Invalid data.' if converted.nil?
33
+ entity = converted.pack('C*')
32
34
  raise ArgumentError, "Data whose HRP is #{hrp} must be 32 bytes." if BARE_PREFIXES.include?(hrp) && entity.bytesize != 32
33
35
  if BARE_PREFIXES.include?(hrp)
34
36
  BareEntity.new(hrp, entity.unpack1('H*'))
@@ -38,7 +38,9 @@ module Bech32
38
38
  raise ArgumentError, "addr must be encoded with bech32m." unless spec == Bech32::Encoding::BECH32M
39
39
  raise ArgumentError, 'Invalid hrp.' if hrp.nil? || data[0].nil? || ![HRP_MAINNET, HRP_TESTNET].include?(hrp)
40
40
  version = data[0]
41
- keys = Bech32.convert_bits(data[1..-1], 5, 8, false).pack('C*').unpack1('H*')
41
+ converted = Bech32.convert_bits(data[1..-1], 5, 8, false)
42
+ raise ArgumentError, "Invalid data." if converted.nil?
43
+ keys = converted.pack('C*').unpack1('H*')
42
44
  raise ArgumentError, "Invalid key size." unless keys.length == 132
43
45
  scan = keys[0...66]
44
46
  spend = keys[66..-1]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bech32
4
- VERSION = '1.5.0'
4
+ VERSION = '1.5.1'
5
5
  end
data/lib/bech32.rb CHANGED
@@ -50,7 +50,7 @@ module Bech32
50
50
  bech = bech.downcase
51
51
  # check data length
52
52
  pos = bech.rindex(SEPARATOR)
53
- return nil if pos.nil? || pos + 7 > bech.length || bech.length > max_length
53
+ return nil if pos.nil? || pos < 1 || pos + 7 > bech.length || bech.length > max_length
54
54
  # check valid charset
55
55
  bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)}
56
56
  # split hrp and data
@@ -0,0 +1,45 @@
1
+ module Bech32
2
+ VERSION: String
3
+
4
+ module Encoding
5
+ BECH32: Integer
6
+ BECH32M: Integer
7
+ end
8
+
9
+ SEPARATOR: String
10
+ CHARSET: Array[String]
11
+ BECH32M_CONST: Integer
12
+
13
+ # Encode hrp and data to bech32/bech32m string.
14
+ def self.encode: (String hrp, Array[Integer] data, Integer spec) -> String
15
+
16
+ # Decode bech32/bech32m string. Returns nil if invalid.
17
+ def self.decode: (String bech, ?Integer max_length) -> [String, Array[Integer], Integer]?
18
+
19
+ # Convert bits from one base to another.
20
+ def self.convert_bits: (Array[Integer] data, Integer from, Integer to, ?bool padding) -> Array[Integer]?
21
+
22
+ # Create checksum for hrp and data.
23
+ def self.create_checksum: (String hrp, Array[Integer] data, Integer spec) -> Array[Integer]
24
+
25
+ # Verify checksum. Returns encoding spec if valid, nil otherwise.
26
+ def self.verify_checksum: (String hrp, Array[Integer] data) -> Integer?
27
+
28
+ # module_function methods are also available as instance methods
29
+ def encode: (String hrp, Array[Integer] data, Integer spec) -> String
30
+ def decode: (String bech, ?Integer max_length) -> [String, Array[Integer], Integer]?
31
+ def convert_bits: (Array[Integer] data, Integer from, Integer to, ?bool padding) -> Array[Integer]?
32
+ def create_checksum: (String hrp, Array[Integer] data, Integer spec) -> Array[Integer]
33
+ def verify_checksum: (String hrp, Array[Integer] data) -> Integer?
34
+
35
+ private
36
+
37
+ # Expand HRP for checksum computation.
38
+ def self.expand_hrp: (String hrp) -> Array[Integer]
39
+
40
+ # Compute polymod checksum.
41
+ def self.polymod: (Array[Integer] values) -> Integer
42
+
43
+ def expand_hrp: (String hrp) -> Array[Integer]
44
+ def polymod: (Array[Integer] values) -> Integer
45
+ end
@@ -0,0 +1,54 @@
1
+ module Bech32
2
+ module Nostr
3
+ class BareEntity
4
+ attr_reader hrp: String
5
+ attr_reader data: String
6
+
7
+ # Initialize bare entity.
8
+ def initialize: (String hrp, String data) -> void
9
+
10
+ # Encode to bech32 string.
11
+ def encode: () -> String
12
+ end
13
+
14
+ class TLVEntry
15
+ attr_reader type: Integer
16
+ attr_reader label: String?
17
+ attr_reader value: String | Integer
18
+
19
+ # Initialize TLV entry.
20
+ def initialize: (Integer type, String | Integer value, ?String? label) -> void
21
+
22
+ # Convert to binary payload.
23
+ def to_payload: () -> String
24
+
25
+ # String representation.
26
+ def to_s: () -> String
27
+
28
+ private
29
+
30
+ # Check if string is hex encoded.
31
+ def hex_string?: (String str) -> bool
32
+ end
33
+
34
+ class TLVEntity
35
+ TYPE_SPECIAL: Integer
36
+ TYPE_RELAY: Integer
37
+ TYPE_AUTHOR: Integer
38
+ TYPE_KIND: Integer
39
+ TYPES: Array[Integer]
40
+
41
+ attr_reader hrp: String
42
+ attr_reader entries: Array[TLVEntry]
43
+
44
+ # Initialize TLV entity.
45
+ def initialize: (String hrp, Array[TLVEntry] entries) -> void
46
+
47
+ # Parse TLV entity from binary data.
48
+ def self.parse: (String hrp, String data) -> TLVEntity
49
+
50
+ # Encode to bech32 string.
51
+ def encode: () -> String
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ module Bech32
2
+ module Nostr
3
+ module NIP19
4
+ HRP_PUBKEY: String
5
+ HRP_PRIVATE_KEY: String
6
+ HRP_NOTE_ID: String
7
+ HRP_PROFILE: String
8
+ HRP_EVENT: String
9
+ HRP_RELAY: String
10
+ HRP_EVENT_COORDINATE: String
11
+
12
+ BARE_PREFIXES: Array[String]
13
+ TLV_PREFIXES: Array[String]
14
+ ALL_PREFIXES: Array[String]
15
+
16
+ # Decode NIP-19 bech32 string.
17
+ def self.decode: (String string) -> (BareEntity | TLVEntity)
18
+
19
+ # module_function methods are also available as instance methods
20
+ def decode: (String string) -> (BareEntity | TLVEntity)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Bech32
2
+ class SegwitAddr
3
+ HRP_MAINNET: String
4
+ HRP_TESTNET: String
5
+ HRP_REGTEST: String
6
+
7
+ attr_accessor hrp: String
8
+ attr_accessor ver: Integer?
9
+ attr_accessor prog: Array[Integer]?
10
+
11
+ # Initialize SegwitAddr. Optionally parse from address string.
12
+ def initialize: (?String? addr) -> void
13
+
14
+ # Generate script pubkey from witness version and program.
15
+ def to_script_pubkey: () -> String
16
+
17
+ # Parse script pubkey into witness version and program.
18
+ def script_pubkey=: (String script_pubkey) -> void
19
+
20
+ # Generate bech32/bech32m address string.
21
+ def addr: () -> String
22
+
23
+ private
24
+
25
+ # Parse address string into hrp, version and program.
26
+ def parse_addr: (String addr) -> void
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ module Bech32
2
+ # BIP-352 silent payment address.
3
+ class SilentPaymentAddr
4
+ HRP_MAINNET: String
5
+ HRP_TESTNET: String
6
+
7
+ attr_reader hrp: String
8
+ attr_reader version: Integer
9
+ attr_reader scan_key: String
10
+ attr_reader spend_key: String
11
+
12
+ # Initialize SilentPaymentAddr.
13
+ def initialize: (String hrp, Integer version, String scan_key, String spend_key) -> void
14
+
15
+ # Parse silent payment address string.
16
+ def self.parse: (String addr) -> SilentPaymentAddr
17
+
18
+ # Generate silent payment address string.
19
+ def to_s: () -> String
20
+ end
21
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bech32
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shigeyuki Azuchi
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: thor
@@ -69,6 +69,7 @@ files:
69
69
  - LICENSE.txt
70
70
  - README.md
71
71
  - Rakefile
72
+ - Steepfile
72
73
  - bech32.gemspec
73
74
  - bin/console
74
75
  - bin/setup
@@ -80,10 +81,16 @@ files:
80
81
  - lib/bech32/segwit_addr.rb
81
82
  - lib/bech32/silent_payment_addr.rb
82
83
  - lib/bech32/version.rb
84
+ - sig/bech32/bech32.rbs
85
+ - sig/bech32/nostr/entity.rbs
86
+ - sig/bech32/nostr/nip19.rbs
87
+ - sig/bech32/segwit_addr.rbs
88
+ - sig/bech32/silent_payment_addr.rbs
83
89
  homepage: https://github.com/azuchi/bech32rb
84
90
  licenses:
85
91
  - MIT
86
- metadata: {}
92
+ metadata:
93
+ rubygems_mfa_required: 'true'
87
94
  rdoc_options: []
88
95
  require_paths:
89
96
  - lib
@@ -98,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
105
  - !ruby/object:Gem::Version
99
106
  version: '0'
100
107
  requirements: []
101
- rubygems_version: 3.6.3
108
+ rubygems_version: 4.0.3
102
109
  specification_version: 4
103
110
  summary: The implementation of Bech32 encoder and decoder.
104
111
  test_files: []