Module: Bitcoin::Descriptor::Checksum

Defined in:
lib/bitcoin/descriptor/checksum.rb

Overview

Constant Summary collapse

INPUT_CHARSET =
"0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "
CHECKSUM_CHARSET =
Bech32::CHARSET
GENERATOR =
[0xF5DEE51989, 0xA9FDCA3312, 0x1BAB10E32D, 0x3706B1677A, 0x644D626FFD]

Class Method Summary collapse

Class Method Details

.descsum_check(s) ⇒ Boolean

Verify that the checksum is correct in a descriptor

Parameters:

  • s (String)

    Descriptor string.

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
# File 'lib/bitcoin/descriptor/checksum.rb', line 16

def descsum_check(s)
  return false unless s[-9] == '#'
  s[-8..-1].each_char do |c|
    return false unless CHECKSUM_CHARSET.include?(c)
  end
  symbols = descsum_expand(s[0...-9]) + s[-8..-1].each_char.map{|c|CHECKSUM_CHARSET.index(c)}
  descsum_polymod(symbols) == 1
end

.descsum_create(s) ⇒ String

Add a checksum to a descriptor without

Parameters:

  • s (String)

    Descriptor string without checksum.

Returns:

  • (String)

    Descriptor string with checksum.



28
29
30
31
32
33
34
35
# File 'lib/bitcoin/descriptor/checksum.rb', line 28

def descsum_create(s)
  symbols = descsum_expand(s) + [0, 0, 0, 0, 0, 0, 0, 0]
  checksum = descsum_polymod(symbols) ^ 1
  result = 8.times.map do |i|
    CHECKSUM_CHARSET[(checksum >> (5 * (7 - i))) & 31]
  end.join
  "#{s}##{result}"
end

.descsum_expand(s) ⇒ Array

Internal function that does the character to symbol expansion.

Parameters:

  • s (String)

    Descriptor string without checksum.

Returns:

  • (Array)

    symbols. An array of integer.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/bitcoin/descriptor/checksum.rb', line 40

def descsum_expand(s)
  groups = []
  symbols = []
  s.each_char do |c|
    return nil unless INPUT_CHARSET.include?(c)
    v = INPUT_CHARSET.index(c)
    symbols << (v & 31)
    groups << (v >> 5)
    if groups.length == 3
      symbols << (groups[0] * 9 + groups[1] * 3 + groups[2])
      groups = []
    end
  end
  symbols << groups[0] if groups.length == 1
  symbols << (groups[0] * 3 + groups[1]) if groups.length == 2
  symbols
end

.descsum_polymod(symbols) ⇒ Integer

Internal function that computes the descriptor checksum.

Parameters:

Returns:



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/bitcoin/descriptor/checksum.rb', line 61

def descsum_polymod(symbols)
  chk = 1
  symbols.each do |value|
    top = chk >> 35
    chk = (chk & 0x7FFFFFFFF) << 5 ^ value
    5.times do |i|
      chk ^= GENERATOR[i] if ((top >> i) & 1) == 1
    end
  end
  chk
end