Class: Base58::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/base58-alphabets/base.rb

Direct Known Subclasses

Bitcoin, Flickr

Constant Summary collapse

BASE =

ALPHABET.length == 58 ## 58 chars/letters/digits

58
HEX_RE =

check if it is a hex (string)

- allow optiona 0x or 0X  and allow abcdef and ABCDEF
/\A(?:0x)?[0-9a-f]+\z/i

Class Method Summary collapse

Class Method Details

._bytes(num, base: BASE) ⇒ Object

(private) helper - note: leading underscore in name e.g. _bytes



92
93
94
95
96
97
98
99
100
101
# File 'lib/base58-alphabets/base.rb', line 92

def self._bytes( num, base: BASE )   ## num_to_bytes

  ## note: 0 leads to empty []  and NOT [0] !!!!

  b = []
  while num > 0
    num, mod = num.divmod( base )
    b << mod
  end
  b = b.reverse
  b
end

._pack(bytes) ⇒ Object

bytes_to_num



104
105
106
107
108
109
110
# File 'lib/base58-alphabets/base.rb', line 104

def self._pack( bytes )   ## bytes_to_num

  num = 0
  bytes.reverse.each_with_index do |byte,index|
    num += byte * (BASE**(index))
  end
  num
end

._strip0x(str) ⇒ Object

todo/check: add alias e.g. strip_hex_prefix or such - why? why not?



113
114
115
# File 'lib/base58-alphabets/base.rb', line 113

def self._strip0x( str )    ## todo/check: add alias e.g. strip_hex_prefix or such - why? why not?

  (str[0,2] == '0x' || str[0,2] == '0X') ?  str[2..-1] : str
end

.decode_bin(str) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/base58-alphabets/base.rb', line 69

def self.decode_bin( str )
  num = decode_num( str )

  ## use base 256 for characters to binary conversion!!!

  data = _bytes( num, base: 256 ).pack( 'C*' )

  ## check for leading zeros

  str.bytes.each do |byte|
    break if byte != alphabet[0].ord
    data = "\x00" + data
  end
  data
end

.decode_hex(str) ⇒ Object



83
84
85
# File 'lib/base58-alphabets/base.rb', line 83

def self.decode_hex( str )
  decode_bin( str ).unpack( 'H*' )[0]
end

.decode_num(str) ⇒ Object

Converts a base58 string to a base10 integer.



58
59
60
61
62
63
64
65
66
# File 'lib/base58-alphabets/base.rb', line 58

def self.decode_num( str )     ## todo/check: add alias base58_to_num / base58_to_int

  bytes = str.each_char.reduce([]) do |bytes,char|
               byte = number[char]
               raise ArgumentError, "Value passed not a valid base58 string - >#{char}< not found in alphabet"  if byte.nil?
               bytes << byte
               bytes
          end
  _pack( bytes )
end

.encode_bin(data) ⇒ Object

Converts binary string into its Base58 representation. If string is empty returns an empty string.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/base58-alphabets/base.rb', line 27

def self.encode_bin( data )   ## todo/check: add alias such as bin_to_base58 / data_to_base58 - why? why not?

  leading_zeroes = 0
  num = 0
  base = 1
  data.bytes.reverse_each do |byte|
      if byte == 0
        leading_zeroes += 1
      else
        leading_zeroes = 0
        num += base*byte
      end
      base *= 256
  end

  (alphabet[0]*leading_zeroes) + encode_num( num )
end

.encode_hex(str) ⇒ Object

Converts hex string into its Base58 representation.

Raises:

  • (ArgumentError)


46
47
48
49
50
51
52
# File 'lib/base58-alphabets/base.rb', line 46

def self.encode_hex( str )
  ## todo/check: allow empty string ("") - why? why not?

  raise ArgumentError, "expected hex string (0-9a-f) - got >#{str}< - can't pack string; sorry"   unless str =~ HEX_RE || str.empty?

  str = _strip0x( str )  ##  check if input starts with 0x or 0X if yes - (auto-)cut off!!!!!

  encode_bin( [str].pack('H*') )
end

.encode_num(num) ⇒ Object

Converts a base10 integer to a base58 string.



17
18
19
20
21
22
# File 'lib/base58-alphabets/base.rb', line 17

def self.encode_num( num )   ## num_to_base58 / int_to_base58

  _bytes( num ).reduce( String.new ) do |buf, byte|
    buf << alphabet[byte]
    buf
  end
end