Module: Bech32

Defined in:
lib/bech32.rb,
lib/bech32/nostr.rb,
lib/bech32/version.rb,
lib/bech32/nostr/nip19.rb,
lib/bech32/segwit_addr.rb,
lib/bech32/nostr/entity.rb

Defined Under Namespace

Modules: Encoding, Nostr Classes: SegwitAddr

Constant Summary collapse

SEPARATOR =
'1'
CHARSET =
%w(q p z r y 9 x 8 g f 2 t v d w 0 s 3 j n 5 4 k h c e 6 m u a 7 l)
BECH32M_CONST =
0x2bc830a3
VERSION =
'1.4.1'

Class Method Summary collapse

Class Method Details

.convert_bits(data, from, to, padding = true) ⇒ Array

Convert a data where each byte is encoding from bits to a byte slice where each byte is encoding to bits.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/bech32.rb', line 96

def convert_bits(data, from, to, padding=true)
  acc = 0
  bits = 0
  ret = []
  maxv = (1 << to) - 1
  max_acc = (1 << (from + to - 1)) - 1
  data.each do |v|
    return nil if v < 0 || (v >> from) != 0
    acc = ((acc << from) | v) & max_acc
    bits += from
    while bits >= to
      bits -= to
      ret << ((acc >> bits) & maxv)
    end
  end
  if padding
    ret << ((acc << (to - bits)) & maxv) unless bits == 0
  elsif bits >= from || ((acc << (to - bits)) & maxv) != 0
    return nil
  end
  ret
end

.create_checksum(hrp, data, spec) ⇒ Object

Returns computed checksum values of hrp and data



64
65
66
67
68
69
# File 'lib/bech32.rb', line 64

def create_checksum(hrp, data, spec)
  values = expand_hrp(hrp) + data
  const = (spec == Bech32::Encoding::BECH32M ? Bech32::BECH32M_CONST : 1)
  polymod = polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
  (0..5).map{|i|(polymod >> 5 * (5 - i)) & 31}
end

.decode(bech, max_length = 90) ⇒ Object

Returns the Bech32 decoded hrp and data.

require 'bech32'

addr = 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4'
hrp, data, spec = Bech32.decode(addr)

<i>Generates:</i>
'bc' # hrp
[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] # data
1 # spec see Bech32::Encoding


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bech32.rb', line 45

def decode(bech, max_length = 90)
  # check uppercase/lowercase
  return nil if bech.bytes.index{|x| x < 33 || x > 126}
  return nil if (bech.downcase != bech && bech.upcase != bech)
  bech = bech.downcase
  # check data length
  pos = bech.rindex(SEPARATOR)
  return nil if pos.nil? || pos + 7 > bech.length || bech.length > max_length
  # check valid charset
  bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)}
  # split hrp and data
  hrp = bech[0..pos-1]
  data = bech[pos+1..-1].each_char.map{|c|CHARSET.index(c)}
  # check checksum
  spec = verify_checksum(hrp, data)
  spec ? [hrp, data[0..-7], spec] : nil
end

.encode(hrp, data, spec) ⇒ Object

Returns the encoded Bech32 string.

require 'bech32'

bech = Bech32.encode('bc', [], Bech32::Encoding::BECH32)

<i>Generates:</i>
'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4' # bech


28
29
30
31
# File 'lib/bech32.rb', line 28

def encode(hrp, data, spec)
  checksummed = data + create_checksum(hrp, data, spec)
  hrp + SEPARATOR + checksummed.map{|i|CHARSET[i]}.join
end

.verify_checksum(hrp, data) ⇒ Integer

Verify a checksum given Bech32 string



75
76
77
78
79
80
81
82
83
# File 'lib/bech32.rb', line 75

def verify_checksum(hrp, data)
  const = polymod(expand_hrp(hrp) + data)
  case const
  when 1
    Encoding::BECH32
  when BECH32M_CONST
    Encoding::BECH32M
  end
end