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 +4 -4
- data/.github/workflows/main.yml +14 -1
- data/.ruby-version +1 -1
- data/Gemfile +5 -0
- data/Steepfile +19 -0
- data/bech32.gemspec +2 -0
- data/lib/bech32/nostr/entity.rb +13 -8
- data/lib/bech32/nostr/nip19.rb +3 -1
- data/lib/bech32/silent_payment_addr.rb +3 -1
- data/lib/bech32/version.rb +1 -1
- data/lib/bech32.rb +1 -1
- data/sig/bech32/bech32.rbs +45 -0
- data/sig/bech32/nostr/entity.rbs +54 -0
- data/sig/bech32/nostr/nip19.rbs +23 -0
- data/sig/bech32/segwit_addr.rbs +28 -0
- data/sig/bech32/silent_payment_addr.rbs +21 -0
- metadata +11 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22cba51d19b0989743f7f679f187311e735ce018dec53880ddfefebee89f688f
|
|
4
|
+
data.tar.gz: 1cd7be33ab83fd724054202a812f818ed02adb5eb7545baa27e27f6b3358da2e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc71997f097a817224b687dc53baf048ba2954cd030f7db50523d7e45121632b7f2edf758ed78298102214c3e3407cf7c7da6b3469a3cde089ade10e8346088d
|
|
7
|
+
data.tar.gz: 6c246c4107a40193d317738bfa4637ccf6452efb48f1d36532570cec1e09681cc17fd374f47361467017e6546f36c4513f2585ed2d4b767939dcef05047ede46
|
data/.github/workflows/main.yml
CHANGED
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
runs-on: ubuntu-latest
|
|
20
20
|
strategy:
|
|
21
21
|
matrix:
|
|
22
|
-
ruby-version: ['3.
|
|
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-
|
|
1
|
+
ruby-4.0.0
|
data/Gemfile
CHANGED
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']
|
data/lib/bech32/nostr/entity.rb
CHANGED
|
@@ -110,37 +110,42 @@ module Bech32
|
|
|
110
110
|
buf = ::StringIO.new(data)
|
|
111
111
|
entries = []
|
|
112
112
|
until buf.eof?
|
|
113
|
-
|
|
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,
|
|
123
|
+
entries << TLVEntry.new(type, value.unpack1('H*'), 'pubkey')
|
|
119
124
|
when NIP19::HRP_RELAY
|
|
120
|
-
entries << TLVEntry.new(type,
|
|
125
|
+
entries << TLVEntry.new(type, value, 'relay')
|
|
121
126
|
when NIP19::HRP_EVENT
|
|
122
|
-
entries << TLVEntry.new(type,
|
|
127
|
+
entries << TLVEntry.new(type, value.unpack1('H*'), 'id')
|
|
123
128
|
when NIP19::HRP_EVENT_COORDINATE
|
|
124
|
-
entries << TLVEntry.new(type,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
data/lib/bech32/nostr/nip19.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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]
|
data/lib/bech32/version.rb
CHANGED
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.
|
|
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:
|
|
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:
|
|
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: []
|