lib/bitcoin/bech32.rb in bitcoin-ruby-0.0.18 vs lib/bitcoin/bech32.rb in bitcoin-ruby-0.0.19
- old
+ new
@@ -1,172 +1,166 @@
# encoding: ascii-8bit
-# Ruby reference implementation: https://github.com/sipa/bech32/tree/master/ref/c
-module Bitcoin; end
-module Bitcoin::Bech32
- CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l".unpack("C*")
- CHARSET_REV = [
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
- -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
- 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
- -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
- 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
- ]
+module Bitcoin
+ # Ruby reference implementation: https://github.com/sipa/bech32/tree/master/ref/c
+ module Bech32
+ CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'.unpack('C*')
+ CHARSET_REV = [
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
+ ].freeze
- class << self
-
- def polymod_step(pre)
- b = pre >> 25
- return ((pre & 0x1FFFFFF) << 5) ^ \
+ class << self
+ def polymod_step(pre)
+ b = pre >> 25
+ ((pre & 0x1FFFFFF) << 5) ^ \
(-((b >> 0) & 1) & 0x3b6a57b2) ^ \
(-((b >> 1) & 1) & 0x26508e6d) ^ \
(-((b >> 2) & 1) & 0x1ea119fa) ^ \
(-((b >> 3) & 1) & 0x3d4233dd) ^ \
(-((b >> 4) & 1) & 0x2a1462b3)
- end
-
- def encode(hrp, data)
- buf = []
- chk = 1
-
- hrp.unpack("C*").each do |ch|
- return nil if ch < 33 || ch > 126
- return nil if ch >= 'A'.ord && ch <= 'Z'.ord
- chk = polymod_step(chk) ^ (ch >> 5)
end
- return nil if (hrp.bytesize + 7 + data.size) > 90
+ def encode(hrp, data)
+ buf = []
+ chk = 1
- chk = polymod_step(chk)
- hrp.unpack("C*").each do |ch|
- chk = polymod_step(chk) ^ (ch & 0x1f)
- buf << ch
- end
+ hrp.unpack('C*').each do |ch|
+ return nil if ch < 33 || ch > 126
+ return nil if ch >= 'A'.ord && ch <= 'Z'.ord
+ chk = polymod_step(chk) ^ (ch >> 5)
+ end
- buf << '1'.ord
+ return nil if (hrp.bytesize + 7 + data.size) > 90
- data.each do |i|
- return nil if (i >> 5) != 0
- chk = polymod_step(chk) ^ i
- buf << CHARSET[i]
- end
-
- 6.times do |n|
chk = polymod_step(chk)
- end
+ hrp.unpack('C*').each do |ch|
+ chk = polymod_step(chk) ^ (ch & 0x1f)
+ buf << ch
+ end
- chk ^= 1
+ buf << '1'.ord
- 6.times do |i|
- buf << CHARSET[(chk >> ((5 - i) * 5)) & 0x1f]
- end
+ data.each do |i|
+ return nil if (i >> 5) != 0
+ chk = polymod_step(chk) ^ i
+ buf << CHARSET[i]
+ end
- return buf.pack("C*")
- end
+ 6.times do
+ chk = polymod_step(chk)
+ end
- def decode(input)
- chk = 1
- input_len = input.bytesize
- have_lower, have_upper = false, false
+ chk ^= 1
- return nil if input_len < 8 || input_len > 90
+ 6.times do |i|
+ buf << CHARSET[(chk >> ((5 - i) * 5)) & 0x1f]
+ end
- data_len = 0
- while data_len < input_len && input[(input_len - 1) - data_len] != '1' do
- data_len += 1
+ buf.pack('C*')
end
- hrp_len = input_len - (1 + data_len)
- return nil if hrp_len < 1 || data_len < 6
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
+ def decode(input)
+ chk = 1
+ input_len = input.bytesize
+ have_lower = false
+ have_upper = false
- data_len -= 6
+ return nil if input_len < 8 || input_len > 90
- hrp = []
- hrp_len.times do |i|
- ch = input[i].ord
- return nil if ch < 33 || ch > 126
+ data_len = 0
+ data_len += 1 while data_len < input_len && input[(input_len - 1) - data_len] != '1'
- if ch >= 'a'.ord && ch <= 'z'.ord
- have_lower = true
- elsif ch >= 'A'.ord && ch <= 'Z'.ord
- have_upper = true
- ch = (ch - 'A'.ord) + 'a'.ord
- end
+ hrp_len = input_len - (1 + data_len)
+ return nil if hrp_len < 1 || data_len < 6
- hrp << ch
- chk = polymod_step(chk) ^ (ch >> 5)
- end
+ hrp = []
+ hrp_len.times do |i|
+ ch = input[i].ord
+ return nil if ch < 33 || ch > 126
- chk = polymod_step(chk)
+ if ch >= 'a'.ord && ch <= 'z'.ord
+ have_lower = true
+ elsif ch >= 'A'.ord && ch <= 'Z'.ord
+ have_upper = true
+ ch = (ch - 'A'.ord) + 'a'.ord
+ end
- hrp_len.times do |i|
- chk = polymod_step(chk) ^ (input[i].ord & 0x1f)
- end
+ hrp << ch
+ chk = polymod_step(chk) ^ (ch >> 5)
+ end
- data = []
- i = hrp_len + 1
- while i < input_len do
- ch = input[i].ord
- v = ((ch & 0x80) != 0) ? -1 : CHARSET_REV[ch]
+ chk = polymod_step(chk)
- have_lower = true if ch >= 'a'.ord && ch <= 'z'.ord
- have_upper = true if ch >= 'A'.ord && ch <= 'Z'.ord
- return nil if v == -1
+ hrp_len.times do |i|
+ chk = polymod_step(chk) ^ (input[i].ord & 0x1f)
+ end
- chk = polymod_step(chk) ^ v
- if (i + 6) < input_len
- data << v
+ data = []
+ i = hrp_len + 1
+ while i < input_len
+ ch = input[i].ord
+ v = (ch & 0x80) != 0 ? -1 : CHARSET_REV[ch]
+
+ have_lower = true if ch >= 'a'.ord && ch <= 'z'.ord
+ have_upper = true if ch >= 'A'.ord && ch <= 'Z'.ord
+ return nil if v == -1
+
+ chk = polymod_step(chk) ^ v
+ data << v if (i + 6) < input_len
+ i += 1
end
- i += 1
- end
- return nil if have_lower && have_upper
- return nil if chk != 1
+ return nil if have_lower && have_upper
+ return nil if chk != 1
- return [hrp.pack("C*"), data]
- end
+ [hrp.pack('C*'), data]
+ end
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
- # Utility for converting bytes of data between bases. These is used for
- # BIP 173 address encoding/decoding to convert between sequences of bytes
- # representing 8-bit values and groups of 5 bits. Conversions may be padded
- # with trailing 0 bits to the nearest byte boundary. Returns nil if
- # conversion requires padding and pad is false.
- #
- # For example:
- #
- # convert_bits("\xFF\xFF", from_bits: 8, to_bits: 5, pad: true)
- # => "\x1F\x1F\x1F\10"
- #
- # See https://github.com/bitcoin/bitcoin/blob/595a7bab23bc21049526229054ea1fff1a29c0bf/src/utilstrencodings.h#L154
- def convert_bits(chunks, from_bits:, to_bits:, pad:)
- output_mask = (1 << to_bits) - 1
- buffer_mask = (1 << (from_bits + to_bits - 1)) - 1
+ # Utility for converting bytes of data between bases. These is used for
+ # BIP 173 address encoding/decoding to convert between sequences of bytes
+ # representing 8-bit values and groups of 5 bits. Conversions may be padded
+ # with trailing 0 bits to the nearest byte boundary. Returns nil if
+ # conversion requires padding and pad is false.
+ #
+ # For example:
+ #
+ # convert_bits("\xFF\xFF", from_bits: 8, to_bits: 5, pad: true)
+ # => "\x1F\x1F\x1F\10"
+ #
+ # See https://github.com/bitcoin/bitcoin/blob/595a7bab23bc21049526229054ea1fff1a29c0bf/src/utilstrencodings.h#L154
+ def convert_bits(chunks, from_bits:, to_bits:, pad:)
+ output_mask = (1 << to_bits) - 1
+ buffer_mask = (1 << (from_bits + to_bits - 1)) - 1
- buffer = 0
- bits = 0
+ buffer = 0
+ bits = 0
- output = []
- chunks.each do |chunk|
- buffer = ((buffer << from_bits) | chunk) & buffer_mask
- bits += from_bits
- while bits >= to_bits
- bits -= to_bits
- output << ((buffer >> bits) & output_mask)
+ output = []
+ chunks.each do |chunk|
+ buffer = ((buffer << from_bits) | chunk) & buffer_mask
+ bits += from_bits
+ while bits >= to_bits
+ bits -= to_bits
+ output << ((buffer >> bits) & output_mask)
+ end
end
- end
- if pad && bits > 0
- output << ((buffer << (to_bits - bits)) & output_mask)
- end
+ output << ((buffer << (to_bits - bits)) & output_mask) if pad && bits > 0
- if !pad && (bits >= from_bits || ((buffer << (to_bits - bits)) & output_mask) != 0)
- return nil
- end
+ if !pad && (bits >= from_bits || ((buffer << (to_bits - bits)) & output_mask) != 0)
+ return nil
+ end
- output
+ output
+ end
end
-
end
end