bech32 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1dbf369ac8990456626ab97fbc98580c01a47110
4
- data.tar.gz: 6c12e12379890d8a47aec779e19f68c04d0ce919
2
+ SHA256:
3
+ metadata.gz: 975a0d606b86cdb7487afad52363ef284de471f1530cf7614b0a7db0728dc937
4
+ data.tar.gz: 1e3d9f3f389cbfd94a8af919a0ec842395605649138bdf3860ac9db2617e3939
5
5
  SHA512:
6
- metadata.gz: 29940231175f3150e370c4fbe5b9d2955e61673af9bdc953304a61761048047fde43827037b25fa66dea0f4ba28e9a0be080a3aebfa76a7acc9c809f88f1fc50
7
- data.tar.gz: 659fd697fc7edcad0645c26768ef6f320dd5db4fdd8e986d2cc19fb3b5df88791d0dc2a7309792576457800a8107034875aca91e445671148b8155f9364472c1
6
+ metadata.gz: ab8fdc36df45376ea1ec0e7d7553fb6309900d8db824998f327dbfe670451a00ec240bbd75fe59e1bdda2590981d174e0be086756e919582dad55ce5441fe5fb
7
+ data.tar.gz: 07bf7ac092a89c997932d380a57f30916baa809fd3adf2c86b7418e599949be6fc593b226bcdb7240247fde19d7f092ebdcdd82bfce154adde9d16b5de2df68e
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ ruby-3.0.0
data/.travis.yml CHANGED
@@ -1,6 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
- - 2.2.2
5
- - 2.3.0
6
- - 2.4.0
3
+ - 2.2.10
4
+ - 2.3.8
5
+ - 2.4.10
6
+ - 2.5.8
7
+ - 2.6.6
8
+ - 2.7.2
9
+ - 3.0.0
data/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # Bech32 [![Build Status](https://travis-ci.org/azuchi/bech32rb.svg?branch=master)](https://travis-ci.org/azuchi/bech32rb) [![Gem Version](https://badge.fury.io/rb/bech32.svg)](https://badge.fury.io/rb/bech32) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) <img src="http://segwit.co/static/public/images/logo.png" width="100">
2
2
 
3
- The implementation of the Bech32 encoder and decoder for Ruby.
3
+ The implementation of the Bech32/Bech32m encoder and decoder for Ruby.
4
4
 
5
5
  Bech32 is checksummed base32 format that is used in following Bitcoin address format.
6
6
 
7
7
  https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
8
8
 
9
+ Bech32m is checksummed base32m format that is used in following Bitcoin address format.
10
+
11
+ https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki
12
+
9
13
  ## Installation
10
14
 
11
15
  Add this line to your application's Gemfile:
@@ -35,13 +39,15 @@ require 'bech32'
35
39
  Decode Bech32-encoded data into hrp part and data part.
36
40
 
37
41
  ```ruby
38
- hrp, data = Bech32.decode('BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4')
42
+ hrp, data, spec = Bech32.decode('BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4')
39
43
 
40
44
  # hrp is human-readable part of Bech32 format
41
45
  'bc'
42
46
 
43
47
  # data is data part of Bech32 format
44
48
  [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]
49
+
50
+ # spec is whether Bech32::Encoding::BECH32 or Bech32::Encoding::BECH32M
45
51
  ```
46
52
 
47
53
  Decode Bech32-encoded Segwit address into `Bech32::SegwitAddr` instance.
@@ -55,6 +61,20 @@ segwit_addr.to_script_pubkey
55
61
  => 0014751e76e8199196d454941c45d1b3a323f1433bd6
56
62
  ```
57
63
 
64
+ #### Advanced
65
+
66
+ 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.
67
+ However, LN specification [BOLT#11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) has no limitation.
68
+
69
+ To decode data of more than 90 characters, specify `max_length` at decode as below. (The default value of `max_length` is 90.)
70
+
71
+ ```ruby
72
+ MAX_INTEGER = 2**31 - 1
73
+ Bech32.decode(bechString, MAX_INTEGER)
74
+ ```
75
+
76
+ Note that between length of the addresses and the error-detection capabilities are [trade-off](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#checksum-design).
77
+
58
78
  ### Encode
59
79
 
60
80
  Encode Bech32 human-readable part and data part into Bech32 string.
@@ -63,7 +83,7 @@ Encode Bech32 human-readable part and data part into Bech32 string.
63
83
  hrp = 'bc'
64
84
  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]
65
85
 
66
- bech = Bech32.encode(hrp, data)
86
+ bech = Bech32.encode(hrp, data, Bech32::Encoding::BECH32)
67
87
  => bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
68
88
  ```
69
89
 
data/bech32.gemspec CHANGED
@@ -1,10 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bech32/version'
4
5
 
5
6
  Gem::Specification.new do |spec|
6
7
  spec.name = "bech32"
7
- spec.version = "1.0.1"
8
+ spec.version = Bech32::VERSION
8
9
  spec.authors = ["Shigeyuki Azuchi"]
9
10
  spec.email = ["azuchi@haw.co.jp"]
10
11
 
@@ -18,6 +19,6 @@ Gem::Specification.new do |spec|
18
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
20
  spec.require_paths = ["lib"]
20
21
 
21
- spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rake", ">= 12.3.3"
22
23
  spec.add_development_dependency "rspec", "~> 3.0"
23
24
  end
data/lib/bech32.rb CHANGED
@@ -1,66 +1,84 @@
1
1
  module Bech32
2
2
 
3
+ module Encoding
4
+ BECH32 = 1
5
+ BECH32M = 2
6
+ end
7
+
3
8
  autoload :SegwitAddr, 'bech32/segwit_addr'
4
9
 
5
10
  SEPARATOR = '1'
6
11
 
7
12
  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)
8
13
 
14
+ BECH32M_CONST = 0x2bc830a3
15
+
9
16
  module_function
10
17
 
11
18
  # Returns the encoded Bech32 string.
12
19
  #
13
20
  # require 'bech32'
14
21
  #
15
- # bech = Bech32.encode('bc', [])
22
+ # bech = Bech32.encode('bc', [], Bech32::Encoding::BECH32)
16
23
  #
17
24
  # <i>Generates:</i>
18
25
  # 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4' # bech
19
26
  #
20
- def encode(hrp, data)
21
- checksummed = data + create_checksum(hrp, data)
27
+ def encode(hrp, data, spec)
28
+ checksummed = data + create_checksum(hrp, data, spec)
22
29
  hrp + SEPARATOR + checksummed.map{|i|CHARSET[i]}.join
23
30
  end
24
31
 
25
- # Returns the Bach32 decoded hrp and data.
32
+ # Returns the Bech32 decoded hrp and data.
26
33
  #
27
34
  # require 'bech32'
28
35
  #
29
36
  # addr = 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4'
30
- # hrp, data = Bech32.decode(addr)
37
+ # hrp, data, spec = Bech32.decode(addr)
31
38
  #
32
39
  # <i>Generates:</i>
33
40
  # 'bc' # hrp
34
41
  # [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
42
+ # 1 # spec see Bech32::Encoding
35
43
  #
36
- def decode(bech)
44
+ def decode(bech, max_length = 90)
37
45
  # check uppercase/lowercase
46
+ return nil if bech.bytes.index{|x| x < 33 || x > 126}
38
47
  return nil if (bech.downcase != bech && bech.upcase != bech)
39
- bech.each_char{|c|return nil if c.ord < 33 || c.ord > 126}
40
48
  bech = bech.downcase
41
49
  # check data length
42
50
  pos = bech.rindex(SEPARATOR)
43
- return nil if pos.nil? || pos + 7 > bech.length || bech.length > 90
51
+ return nil if pos.nil? || pos + 7 > bech.length || bech.length > max_length
44
52
  # check valid charset
45
53
  bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)}
46
54
  # split hrp and data
47
55
  hrp = bech[0..pos-1]
48
56
  data = bech[pos+1..-1].each_char.map{|c|CHARSET.index(c)}
49
57
  # check checksum
50
- return nil unless verify_checksum(hrp, data)
51
- [hrp, data[0..-7]]
58
+ spec = verify_checksum(hrp, data)
59
+ spec ? [hrp, data[0..-7], spec] : nil
52
60
  end
53
61
 
54
62
  # Returns computed checksum values of +hrp+ and +data+
55
- def create_checksum(hrp, data)
63
+ def create_checksum(hrp, data, spec)
56
64
  values = expand_hrp(hrp) + data
57
- polymod = polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
65
+ const = (spec == Bech32::Encoding::BECH32M ? Bech32::BECH32M_CONST : 1)
66
+ polymod = polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
58
67
  (0..5).map{|i|(polymod >> 5 * (5 - i)) & 31}
59
68
  end
60
69
 
61
70
  # Verify a checksum given Bech32 string
71
+ # @param [String] hrp hrp part.
72
+ # @param [Array[Integer]] data data array.
73
+ # @return [Integer] spec
62
74
  def verify_checksum(hrp, data)
63
- polymod(expand_hrp(hrp) + data) == 1
75
+ const = polymod(expand_hrp(hrp) + data)
76
+ case const
77
+ when 1
78
+ Encoding::BECH32
79
+ when BECH32M_CONST
80
+ Encoding::BECH32M
81
+ end
64
82
  end
65
83
 
66
84
  # Expand the hrp into values for checksum computation.
@@ -82,4 +100,4 @@ module Bech32
82
100
 
83
101
  private_class_method :polymod, :expand_hrp
84
102
 
85
- end
103
+ end
@@ -4,6 +4,7 @@ module Bech32
4
4
 
5
5
  HRP_MAINNET = 'bc'
6
6
  HRP_TESTNET = 'tb'
7
+ HRP_REGTEST = 'bcrt'
7
8
 
8
9
  attr_accessor :hrp # human-readable part
9
10
  attr_accessor :ver # witness version
@@ -16,32 +17,34 @@ module Bech32
16
17
 
17
18
  # Returns segwit script pubkey which generated from witness version and witness program.
18
19
  def to_script_pubkey
19
- v = ver == 0 ? ver : ver + 0x80
20
+ v = ver == 0 ? ver : ver + 0x50
20
21
  ([v, prog.length].pack("CC") + prog.map{|p|[p].pack("C")}.join).unpack('H*').first
21
22
  end
22
23
 
23
24
  # parse script pubkey into witness version and witness program
24
25
  def script_pubkey=(script_pubkey)
25
26
  values = [script_pubkey].pack('H*').unpack("C*")
26
- @ver = values[0]
27
+ @ver = values[0] == 0 ? values[0] : values[0] - 0x50
27
28
  @prog = values[2..-1]
28
29
  end
29
30
 
30
31
  # Returns segwit address string which generated from hrp, witness version and witness program.
31
32
  def addr
32
- Bech32.encode(hrp, [ver] + convert_bits(prog, 8, 5))
33
+ spec = (ver == 0 ? Bech32::Encoding::BECH32 : Bech32::Encoding::BECH32M)
34
+ Bech32.encode(hrp, [ver] + convert_bits(prog, 8, 5), spec)
33
35
  end
34
36
 
35
37
  private
36
38
 
37
39
  def parse_addr(addr)
38
- @hrp, data = Bech32.decode(addr)
39
- raise 'Invalid address.' if @hrp.nil? || ![HRP_MAINNET, HRP_TESTNET].include?(@hrp)
40
+ @hrp, data, spec = Bech32.decode(addr)
41
+ raise 'Invalid address.' if hrp.nil? || data[0].nil? || ![HRP_MAINNET, HRP_TESTNET, HRP_REGTEST].include?(hrp)
40
42
  @ver = data[0]
41
43
  raise 'Invalid witness version' if @ver > 16
42
44
  @prog = convert_bits(data[1..-1], 5, 8, false)
43
45
  raise 'Invalid witness program' if @prog.nil? || @prog.length < 2 || @prog.length > 40
44
46
  raise 'Invalid witness program with version 0' if @ver == 0 && (@prog.length != 20 && @prog.length != 32)
47
+ raise 'Witness version and encoding spec do not match' if (@ver == 0 && spec != Bech32::Encoding::BECH32) || (@ver != 0 && spec != Bech32::Encoding::BECH32M)
45
48
  end
46
49
 
47
50
  def convert_bits(data, from, to, padding=true)
@@ -0,0 +1,3 @@
1
+ module Bech32
2
+ VERSION = "1.1.0"
3
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bech32
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.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: 2017-07-04 00:00:00.000000000 Z
11
+ date: 2021-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '10.0'
19
+ version: 12.3.3
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '10.0'
26
+ version: 12.3.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -60,6 +60,7 @@ files:
60
60
  - bin/setup
61
61
  - lib/bech32.rb
62
62
  - lib/bech32/segwit_addr.rb
63
+ - lib/bech32/version.rb
63
64
  homepage: https://github.com/azuchi/bech32rb
64
65
  licenses:
65
66
  - MIT
@@ -79,8 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
80
  - !ruby/object:Gem::Version
80
81
  version: '0'
81
82
  requirements: []
82
- rubyforge_project:
83
- rubygems_version: 2.5.1
83
+ rubygems_version: 3.2.3
84
84
  signing_key:
85
85
  specification_version: 4
86
86
  summary: The implementation of Bech32 encoder and decoder.