bech32 1.2.1 → 1.4.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 +4 -4
- data/.github/workflows/main.yml +2 -3
- data/README.md +52 -14
- data/lib/bech32/nostr/entity.rb +147 -0
- data/lib/bech32/nostr/nip19.rb +41 -0
- data/lib/bech32/nostr.rb +8 -0
- data/lib/bech32/segwit_addr.rb +3 -26
- data/lib/bech32/version.rb +1 -1
- data/lib/bech32.rb +30 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e52ce0d1cc8ab59a97a220fc50e134c3c70fcc5beebd83b86631f4a3c6fc39d
|
4
|
+
data.tar.gz: cbf75c9c25a349c048ee2ad3503d3db8f6631babccdbfb8a7608dd7de9a60ce0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 399a572833d9f651037a7e49c17917bf1e82521fac556c8cc47e14422ef96b200797124e95d51ac2ac760947fdf6b10c39485cbd1228529b72ad3b46e063f5f0
|
7
|
+
data.tar.gz: 6cd811fad6a9a6da5853230ff4501be650afc3a1efeb8208b098774f9bd83676e79ad7be433911774f3005b61054f43671623176bfec1a37835d5f24557e1755
|
data/.github/workflows/main.yml
CHANGED
@@ -19,15 +19,14 @@ jobs:
|
|
19
19
|
runs-on: ubuntu-latest
|
20
20
|
strategy:
|
21
21
|
matrix:
|
22
|
-
ruby-version: ['
|
22
|
+
ruby-version: ['3.0', '3.1', '3.2']
|
23
23
|
|
24
24
|
steps:
|
25
25
|
- uses: actions/checkout@v2
|
26
26
|
- name: Set up Ruby
|
27
27
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
28
28
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
29
|
-
|
30
|
-
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
29
|
+
uses: ruby/setup-ruby@v1
|
31
30
|
with:
|
32
31
|
ruby-version: ${{ matrix.ruby-version }}
|
33
32
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Bech32 [](https://github.com/azuchi/bech32rb/actions/workflows/main.yml) [](https://badge.fury.io/rb/bech32) [](LICENSE) <img src="http://segwit.co/static/public/images/logo.png" width="100">
|
2
2
|
|
3
3
|
The implementation of the Bech32/Bech32m encoder and decoder for Ruby.
|
4
4
|
|
@@ -50,17 +50,6 @@ hrp, data, spec = Bech32.decode('BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4')
|
|
50
50
|
# spec is whether Bech32::Encoding::BECH32 or Bech32::Encoding::BECH32M
|
51
51
|
```
|
52
52
|
|
53
|
-
Decode Bech32-encoded Segwit address into `Bech32::SegwitAddr` instance.
|
54
|
-
|
55
|
-
```ruby
|
56
|
-
addr = 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4'
|
57
|
-
segwit_addr = Bech32::SegwitAddr.new(addr)
|
58
|
-
|
59
|
-
# generate script pubkey
|
60
|
-
segwit_addr.to_script_pubkey
|
61
|
-
=> 0014751e76e8199196d454941c45d1b3a323f1433bd6
|
62
|
-
```
|
63
|
-
|
64
53
|
#### Advanced
|
65
54
|
|
66
55
|
The maximum number of characters of Bech32 defined in [BIP-173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) is limited to 90 characters.
|
@@ -84,7 +73,20 @@ hrp = 'bc'
|
|
84
73
|
data = [0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, 8, 21, 4, 20, 3, 17, 2, 29, 3, 12, 29, 3, 4, 15, 24, 20, 6, 14, 30, 22]
|
85
74
|
|
86
75
|
bech = Bech32.encode(hrp, data, Bech32::Encoding::BECH32)
|
87
|
-
=> bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
|
76
|
+
=> 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
77
|
+
```
|
78
|
+
|
79
|
+
### Segwit
|
80
|
+
|
81
|
+
Decode Bech32-encoded Segwit address into `Bech32::SegwitAddr` instance.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
addr = 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4'
|
85
|
+
segwit_addr = Bech32::SegwitAddr.new(addr)
|
86
|
+
|
87
|
+
# generate script pubkey
|
88
|
+
segwit_addr.to_script_pubkey
|
89
|
+
=> '0014751e76e8199196d454941c45d1b3a323f1433bd6'
|
88
90
|
```
|
89
91
|
|
90
92
|
Encode Segwit script into Bech32 Segwit address.
|
@@ -95,7 +97,43 @@ segwit_addr.script_pubkey = '0014751e76e8199196d454941c45d1b3a323f1433bd6'
|
|
95
97
|
|
96
98
|
# generate addr
|
97
99
|
segwit_addr.addr
|
98
|
-
=> bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
|
100
|
+
=> 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
|
101
|
+
```
|
102
|
+
|
103
|
+
### Nostr
|
104
|
+
|
105
|
+
Supports encoding/decoding of Nostr's [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) entities.
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
# Decode bare entity
|
109
|
+
bech32 = 'npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg'
|
110
|
+
entity = Bech32::Nostr::NIP19.parse(bech32)
|
111
|
+
entity.hrp
|
112
|
+
=> 'npub'
|
113
|
+
entity.data
|
114
|
+
=> '7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e'
|
115
|
+
|
116
|
+
# Decode tlv entity
|
117
|
+
bech32 = 'nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p'
|
118
|
+
entity = Bech32::Nostr::NIP19.parse(bech32)
|
119
|
+
entity.hrp
|
120
|
+
=> 'nprofile'
|
121
|
+
entity.entries[0].value
|
122
|
+
=> '3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d'
|
123
|
+
entity.entries[1].value
|
124
|
+
=> 'wss://r.x.com'
|
125
|
+
|
126
|
+
# Encode bare entity
|
127
|
+
entity = Bech32::Nostr::BareEntity.new('npub', '7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e')
|
128
|
+
entity.encode
|
129
|
+
=> 'npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg'
|
130
|
+
|
131
|
+
# Encode tlv entity
|
132
|
+
entry_relay = Bech32::Nostr::TLVEntry.new(Bech32::Nostr::TLVEntity::TYPE_RELAY, 'wss://relay.nostr.example')
|
133
|
+
entry_author = Bech32::Nostr::TLVEntry.new(Bech32::Nostr::TLVEntity::TYPE_AUTHOR, '97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322')
|
134
|
+
entity = Bech32::Nostr::TLVEntity.new(Bech32::Nostr::NIP19::HRP_EVENT, [entry_relay, entry_author])
|
135
|
+
entity.encode
|
136
|
+
=> 'nevent1qyvhwumn8ghj7un9d3shjtnwdaehgu3wv4uxzmtsd3jsygyhcu9ygdn2v56uz3dnx0uh865xmlwz675emfsccsxxguz6mx8rygstv78u'
|
99
137
|
```
|
100
138
|
|
101
139
|
### CLI
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Bech32
|
2
|
+
module Nostr
|
3
|
+
class BareEntity
|
4
|
+
attr_reader :hrp
|
5
|
+
attr_reader :data
|
6
|
+
|
7
|
+
# Initialize bare entity.
|
8
|
+
# @param [String] hrp human-readable part.
|
9
|
+
# @param [String] data Entity data(hex string).
|
10
|
+
def initialize(hrp, data)
|
11
|
+
raise ArgumentError, "HRP #{hrp} is unsupported." unless NIP19::BARE_PREFIXES.include?(hrp)
|
12
|
+
raise ArgumentError, "Data whose HRP is #{hrp} must be 32 bytes." unless [data].pack('H*').bytesize == 32
|
13
|
+
@hrp = hrp
|
14
|
+
@data = data
|
15
|
+
end
|
16
|
+
|
17
|
+
# Encode bare entity to bech32 string.
|
18
|
+
# @return [String] bech32 string.
|
19
|
+
def encode
|
20
|
+
Bech32.encode(hrp, Bech32.convert_bits([data].pack('H*').unpack('C*'), 8, 5), Bech32::Encoding::BECH32)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class TLVEntry
|
25
|
+
|
26
|
+
attr_reader :type
|
27
|
+
attr_reader :label
|
28
|
+
attr_reader :value
|
29
|
+
|
30
|
+
def initialize(type, value, label = nil)
|
31
|
+
raise ArgumentError, "Type #{type} unsupported." unless TLVEntity::TYPES.include?(type)
|
32
|
+
|
33
|
+
@type = type
|
34
|
+
@value = value
|
35
|
+
@label = label
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convert to binary data.
|
39
|
+
# @return [String] binary data.
|
40
|
+
def to_payload
|
41
|
+
data = if value.is_a?(Integer)
|
42
|
+
[value].pack('N')
|
43
|
+
else
|
44
|
+
hex_string?(value) ? [value].pack('H*') : value
|
45
|
+
end
|
46
|
+
len = data.bytesize
|
47
|
+
[type, len].pack('CC') + data
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Check whether +str+ is hex string or not.
|
53
|
+
# @param [String] str string.
|
54
|
+
# @return [Boolean]
|
55
|
+
def hex_string?(str)
|
56
|
+
return false if str.bytes.any? { |b| b > 127 }
|
57
|
+
return false if str.length % 2 != 0
|
58
|
+
hex_chars = str.chars.to_a
|
59
|
+
hex_chars.all? { |c| c =~ /[0-9a-fA-F]/ }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class TLVEntity
|
64
|
+
|
65
|
+
TYPE_SPECIAL = 0
|
66
|
+
TYPE_RELAY = 1
|
67
|
+
TYPE_AUTHOR = 2
|
68
|
+
TYPE_KIND = 3
|
69
|
+
|
70
|
+
TYPES = [TYPE_SPECIAL, TYPE_RELAY, TYPE_AUTHOR, TYPE_KIND]
|
71
|
+
|
72
|
+
attr_reader :hrp
|
73
|
+
attr_reader :entries
|
74
|
+
|
75
|
+
# Initialize TLV entity.
|
76
|
+
# @param [String] hrp human-readable part.
|
77
|
+
# @param [Array<TLVEntry>] entries TLV entries.
|
78
|
+
# @return [TLVEntity]
|
79
|
+
def initialize(hrp, entries)
|
80
|
+
raise ArgumentError, "HRP #{hrp} is unsupported." unless NIP19::TLV_PREFIXES.include?(hrp)
|
81
|
+
entries.each do |e|
|
82
|
+
raise ArgumentError, "Entries must be TLVEntry. #{e.class} given." unless e.is_a?(TLVEntry)
|
83
|
+
end
|
84
|
+
|
85
|
+
@hrp = hrp
|
86
|
+
@entries = entries
|
87
|
+
end
|
88
|
+
|
89
|
+
# Parse TLV entity from data.
|
90
|
+
# @param [String] hrp human-readable part.
|
91
|
+
# @param [String] data Entity data(binary format).
|
92
|
+
# @return [TLVEntity]
|
93
|
+
def self.parse(hrp, data)
|
94
|
+
buf = StringIO.new(data)
|
95
|
+
entries = []
|
96
|
+
until buf.eof?
|
97
|
+
type, len = buf.read(2).unpack('CC')
|
98
|
+
case type
|
99
|
+
when TYPE_SPECIAL # special
|
100
|
+
case hrp
|
101
|
+
when NIP19::HRP_PROFILE
|
102
|
+
entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'pubkey')
|
103
|
+
when NIP19::HRP_RELAY
|
104
|
+
entries << TLVEntry.new(type, buf.read(len), 'relay')
|
105
|
+
when NIP19::HRP_EVENT
|
106
|
+
entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'id')
|
107
|
+
when NIP19::HRP_EVENT_COORDINATE
|
108
|
+
entries << TLVEntry.new(type, buf.read(len), 'identifier')
|
109
|
+
end
|
110
|
+
when TYPE_RELAY # relay
|
111
|
+
case hrp
|
112
|
+
when NIP19::HRP_PROFILE, NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
|
113
|
+
entries << TLVEntry.new(type, buf.read(len), 'relay')
|
114
|
+
else
|
115
|
+
raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
|
116
|
+
end
|
117
|
+
when TYPE_AUTHOR # author
|
118
|
+
case hrp
|
119
|
+
when NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
|
120
|
+
entries << TLVEntry.new(type, buf.read(len).unpack1('H*'), 'author')
|
121
|
+
else
|
122
|
+
raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
|
123
|
+
end
|
124
|
+
when TYPE_KIND # kind
|
125
|
+
case hrp
|
126
|
+
when NIP19::HRP_EVENT, NIP19::HRP_EVENT_COORDINATE
|
127
|
+
entries << TLVEntry.new(type, buf.read(len).unpack1('H*').to_i(16), 'kind')
|
128
|
+
else
|
129
|
+
raise ArgumentError, "Type: #{type} does not supported for HRP: #{hrp}"
|
130
|
+
end
|
131
|
+
else
|
132
|
+
raise ArgumentError, "Unknown TLV type: #{type}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
TLVEntity.new(hrp, entries)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Encode tlv entity to bech32 string.
|
140
|
+
# @return [String] bech32 string.
|
141
|
+
def encode
|
142
|
+
data = entries.map(&:to_payload).join
|
143
|
+
Bech32.encode(hrp, Bech32.convert_bits(data.unpack('C*'), 8, 5), Bech32::Encoding::BECH32)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bech32
|
2
|
+
module Nostr
|
3
|
+
module NIP19
|
4
|
+
|
5
|
+
HRP_PUBKEY = 'npub'
|
6
|
+
HRP_PRIVATE_KEY = 'nsec'
|
7
|
+
HRP_NOTE_ID = 'note'
|
8
|
+
HRP_PROFILE = 'nprofile'
|
9
|
+
HRP_EVENT = 'nevent'
|
10
|
+
HRP_RELAY = 'nrelay'
|
11
|
+
HRP_EVENT_COORDINATE = 'naddr'
|
12
|
+
|
13
|
+
BARE_PREFIXES = [HRP_PUBKEY, HRP_PRIVATE_KEY, HRP_NOTE_ID]
|
14
|
+
TLV_PREFIXES = [HRP_PROFILE, HRP_EVENT, HRP_RELAY, HRP_EVENT_COORDINATE]
|
15
|
+
ALL_PREFIXES = BARE_PREFIXES + TLV_PREFIXES
|
16
|
+
|
17
|
+
module_function
|
18
|
+
|
19
|
+
# Decode nip19 string.
|
20
|
+
# @param [String] string Bech32 string.
|
21
|
+
# @return [BareEntity | TLVEntity]
|
22
|
+
def decode(string)
|
23
|
+
hrp, data, spec = Bech32.decode(string, string.length)
|
24
|
+
|
25
|
+
raise ArgumentError, 'Invalid nip19 string.' if hrp.nil?
|
26
|
+
raise ArgumentError, 'Invalid bech32 spec.' unless spec == Bech32::Encoding::BECH32
|
27
|
+
|
28
|
+
entity = Bech32.convert_bits(data, 5, 8, false).pack('C*')
|
29
|
+
raise ArgumentError, "Data whose HRP is #{hrp} must be 32 bytes." if BARE_PREFIXES.include?(hrp) && entity.bytesize != 32
|
30
|
+
if BARE_PREFIXES.include?(hrp)
|
31
|
+
BareEntity.new(hrp, entity.unpack1('H*'))
|
32
|
+
elsif TLV_PREFIXES.include?(hrp)
|
33
|
+
TLVEntity.parse(hrp, entity)
|
34
|
+
else
|
35
|
+
raise ArgumentError, "HRP #{hrp} is unsupported."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/bech32/nostr.rb
ADDED
data/lib/bech32/segwit_addr.rb
CHANGED
@@ -18,7 +18,7 @@ module Bech32
|
|
18
18
|
# Returns segwit script pubkey which generated from witness version and witness program.
|
19
19
|
def to_script_pubkey
|
20
20
|
v = ver == 0 ? ver : ver + 0x50
|
21
|
-
([v, prog.length]
|
21
|
+
([v, prog.length] + prog).pack('C*').unpack("H*").first
|
22
22
|
end
|
23
23
|
|
24
24
|
# parse script pubkey into witness version and witness program
|
@@ -31,7 +31,7 @@ module Bech32
|
|
31
31
|
# Returns segwit address string which generated from hrp, witness version and witness program.
|
32
32
|
def addr
|
33
33
|
spec = (ver == 0 ? Bech32::Encoding::BECH32 : Bech32::Encoding::BECH32M)
|
34
|
-
Bech32.encode(hrp, [ver] + convert_bits(prog, 8, 5), spec)
|
34
|
+
Bech32.encode(hrp, [ver] + Bech32.convert_bits(prog, 8, 5), spec)
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
@@ -41,34 +41,11 @@ module Bech32
|
|
41
41
|
raise 'Invalid address.' if hrp.nil? || data[0].nil? || ![HRP_MAINNET, HRP_TESTNET, HRP_REGTEST].include?(hrp)
|
42
42
|
@ver = data[0]
|
43
43
|
raise 'Invalid witness version' if @ver > 16
|
44
|
-
@prog = convert_bits(data[1..-1], 5, 8, false)
|
44
|
+
@prog = Bech32.convert_bits(data[1..-1], 5, 8, false)
|
45
45
|
raise 'Invalid witness program' if @prog.nil? || @prog.length < 2 || @prog.length > 40
|
46
46
|
raise 'Invalid witness program with version 0' if @ver == 0 && (@prog.length != 20 && @prog.length != 32)
|
47
47
|
raise 'Witness version and encoding spec do not match' if (@ver == 0 && spec != Bech32::Encoding::BECH32) || (@ver != 0 && spec != Bech32::Encoding::BECH32M)
|
48
48
|
end
|
49
49
|
|
50
|
-
def convert_bits(data, from, to, padding=true)
|
51
|
-
acc = 0
|
52
|
-
bits = 0
|
53
|
-
ret = []
|
54
|
-
maxv = (1 << to) - 1
|
55
|
-
max_acc = (1 << (from + to - 1)) - 1
|
56
|
-
data.each do |v|
|
57
|
-
return nil if v < 0 || (v >> from) != 0
|
58
|
-
acc = ((acc << from) | v) & max_acc
|
59
|
-
bits += from
|
60
|
-
while bits >= to
|
61
|
-
bits -= to
|
62
|
-
ret << ((acc >> bits) & maxv)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
if padding
|
66
|
-
ret << ((acc << (to - bits)) & maxv) unless bits == 0
|
67
|
-
elsif bits >= from || ((acc << (to - bits)) & maxv) != 0
|
68
|
-
return nil
|
69
|
-
end
|
70
|
-
ret
|
71
|
-
end
|
72
|
-
|
73
50
|
end
|
74
51
|
end
|
data/lib/bech32/version.rb
CHANGED
data/lib/bech32.rb
CHANGED
@@ -6,6 +6,7 @@ module Bech32
|
|
6
6
|
end
|
7
7
|
|
8
8
|
autoload :SegwitAddr, 'bech32/segwit_addr'
|
9
|
+
autoload :Nostr, 'bech32/nostr'
|
9
10
|
|
10
11
|
SEPARATOR = '1'
|
11
12
|
|
@@ -86,6 +87,35 @@ module Bech32
|
|
86
87
|
hrp.each_char.map{|c|c.ord >> 5} + [0] + hrp.each_char.map{|c|c.ord & 31}
|
87
88
|
end
|
88
89
|
|
90
|
+
# Convert a +data+ where each byte is encoding +from+ bits to a byte slice where each byte is encoding +to+ bits.
|
91
|
+
# @param [Array] data
|
92
|
+
# @param [Integer] from
|
93
|
+
# @param [Integer] to
|
94
|
+
# @param [Boolean] padding
|
95
|
+
# @return [Array]
|
96
|
+
def convert_bits(data, from, to, padding=true)
|
97
|
+
acc = 0
|
98
|
+
bits = 0
|
99
|
+
ret = []
|
100
|
+
maxv = (1 << to) - 1
|
101
|
+
max_acc = (1 << (from + to - 1)) - 1
|
102
|
+
data.each do |v|
|
103
|
+
return nil if v < 0 || (v >> from) != 0
|
104
|
+
acc = ((acc << from) | v) & max_acc
|
105
|
+
bits += from
|
106
|
+
while bits >= to
|
107
|
+
bits -= to
|
108
|
+
ret << ((acc >> bits) & maxv)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
if padding
|
112
|
+
ret << ((acc << (to - bits)) & maxv) unless bits == 0
|
113
|
+
elsif bits >= from || ((acc << (to - bits)) & maxv) != 0
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
ret
|
117
|
+
end
|
118
|
+
|
89
119
|
# Compute Bech32 checksum
|
90
120
|
def polymod(values)
|
91
121
|
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bech32
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shigeyuki Azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -75,6 +75,9 @@ files:
|
|
75
75
|
- bin/setup
|
76
76
|
- exe/bech32
|
77
77
|
- lib/bech32.rb
|
78
|
+
- lib/bech32/nostr.rb
|
79
|
+
- lib/bech32/nostr/entity.rb
|
80
|
+
- lib/bech32/nostr/nip19.rb
|
78
81
|
- lib/bech32/segwit_addr.rb
|
79
82
|
- lib/bech32/version.rb
|
80
83
|
homepage: https://github.com/azuchi/bech32rb
|