base58-alphabets 0.0.1 → 0.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
2
  SHA256:
3
- metadata.gz: 93de3aafa549247ab62457454bfcd47c62e718314c8a7ecb6057160c0b317755
4
- data.tar.gz: 9e74c2d2b9106b54be273b22a97dff3a8055cd66ac3ce1d85f5b84a18058ba30
3
+ metadata.gz: 000b32a445c54f6eb556e6b6c3804bfa2d4df87c1caef2ff001b10a714b38403
4
+ data.tar.gz: 2984225c57d1514eb716eaddfb07d66079ba7edcfacf9f722ecfcf22e84015e0
5
5
  SHA512:
6
- metadata.gz: 4ce2677b5f3f6f7c8a4f01014cc29d2888c9bcab241576c3780c95c53b9fe70c8796f97f1fcad3acdcf8a6ee35542db4efb4919d5204688c58c25319d95011e6
7
- data.tar.gz: da0dabbb21e0c3c98bddf912cadc0a06f31cd52f2a56e06f72cb2f9bb09e8c9bbf3b11398d07a51f64f30070703a6b4ad613e19d72169d9172a376b82536f0cc
6
+ metadata.gz: 9a71c550deb538e9928a743103435b5ac7c4f544e7d806529a84a52d4e76ff9ee49ccab0d33602a5deff93511dc92dede5e954697aa9cce59eef4c9da3c118dd
7
+ data.tar.gz: 579c12f8837066b4f4265df52ff36108341a6d290a60d152a195d532171b7fa92cc0d2da58039cd1ce4babe5ab1ac90e85865619cf01ce251193d55cd5b16ead
@@ -3,4 +3,9 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/base58-alphabets.rb
6
+ lib/base58-alphabets/base.rb
7
+ lib/base58-alphabets/base58.rb
8
+ lib/base58-alphabets/bitcoin.rb
6
9
  lib/base58-alphabets/version.rb
10
+ test/helper.rb
11
+ test/test_base58_bitcoin.rb
data/README.md CHANGED
@@ -11,6 +11,67 @@ Encode / decode numbers with Bitcoin or Flickr base58 notation / alphabet
11
11
 
12
12
 
13
13
 
14
+ ## What's Base 58?
15
+
16
+
17
+ > Similar to Base64, but modified to avoid both non-alphanumeric
18
+ > characters (`+` and `/`) and letters which might look ambiguous
19
+ > when printed (`0` - zero, `I` - capital i, `O` - capital o and `l` - lower case L).
20
+ > Satoshi Nakamoto invented the base58 encoding scheme when creating bitcoin.
21
+ > Some messaging and social media systems line break on non-alphanumeric
22
+ > strings. This is avoided by not using URI reserved characters such as `+`.
23
+ >
24
+ > (Source: [Base58 @ Wikipedia](https://en.wikipedia.org/wiki/Binary-to-text_encoding#Base58))
25
+
26
+
27
+
28
+ ## Bitcoin
29
+
30
+ The bitcoin notation / alphabet (`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`)
31
+
32
+
33
+ Triva Quiz: What characters (digits/letters) are
34
+ missing in the base 56 alphabets?
35
+
36
+ - `0` (Zero), `O` (Upper-O), `I` (Upper-I), `l` (Lower-L)
37
+
38
+ Why use base56 (and not "standard" base64)?
39
+
40
+ ```
41
+ // - Don't want 0OIl characters that look the same in some fonts and
42
+ // could be used to create visually identical looking account numbers.
43
+ // - A string with non-alphanumeric characters is not as easily accepted as an account number.
44
+ // - E-mail usually won't line-break if there's no punctuation to break at.
45
+ // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
46
+ ```
47
+
48
+ (Source: `base58.h` - Bitcoin Source Code Header Comments)
49
+
50
+
51
+
52
+ ### Bitcoin (Base58) Notation
53
+
54
+ |Num |Character |Num |Character |Num |Character |Num |Character|
55
+ |----:|----------:|----:|----------:|----:|----------:|----:|--------:|
56
+ | 0 | **1** | 1 | **2** | 2 | **3** | 3 | **4** |
57
+ | 4 | **5** | 5 | **6** | 6 | **7** | 7 | **8** |
58
+ | 8 | **9** | 9 | **A** | 10 | **B** | 11 | **C** |
59
+ | 12 | **D** | 13 | **E** | 14 | **F** | 15 | **G** |
60
+ | 16 | **H** | 17 | **J** | 18 | **K** | 19 | **L** |
61
+ | 20 | **M** | 21 | **N** | 22 | **P** | 23 | **Q** |
62
+ | 24 | **R** | 25 | **S** | 26 | **T** | 27 | **U** |
63
+ | 28 | **V** | 29 | **W** | 30 | **X** | 31 | **Y** |
64
+ | 32 | **Z** | 33 | **a** | 34 | **b** | 35 | **c** |
65
+ | 36 | **d** | 37 | **e** | 38 | **f** | 39 | **g** |
66
+ | 40 | **h** | 41 | **i** | 42 | **j** | 43 | **k** |
67
+ | 44 | **m** | 45 | **n** | 46 | **o** | 47 | **p** |
68
+ | 48 | **q** | 49 | **r** | 50 | **s** | 51 | **t** |
69
+ | 52 | **u** | 53 | **v** | 54 | **w** | 55 | **x** |
70
+ | 56 | **y** | 57 | **z** |
71
+
72
+
73
+
74
+
14
75
 
15
76
  ## License
16
77
 
@@ -6,9 +6,9 @@ require 'pp'
6
6
  ## our own code
7
7
  require 'base58-alphabets/version' # note: let version always go first
8
8
 
9
-
10
-
11
-
9
+ require 'base58-alphabets/base'
10
+ require 'base58-alphabets/bitcoin'
11
+ require 'base58-alphabets/base58'
12
12
 
13
13
 
14
14
 
@@ -0,0 +1,41 @@
1
+ #########
2
+ # shared code for formats / variants with single char alphabets
3
+ # e.g. Bitcoin, Flickr, ...
4
+
5
+ module Base58
6
+ class Base
7
+
8
+ # Converts a base10 integer to a base58 string.
9
+ def self.encode( num_or_bytes )
10
+ if num_or_bytes.is_a?( Array )
11
+ bytes = num_or_bytes
12
+ else
13
+ num = num_or_bytes
14
+ bytes = Base58._bytes( num )
15
+ end
16
+
17
+ bytes.reduce( String.new ) do |buf, byte|
18
+ buf << alphabet[byte]
19
+ buf
20
+ end
21
+ end
22
+
23
+
24
+ # Converts a base58 string to a base10 integer.
25
+ def self.decode( str_or_bytes )
26
+ if str_or_bytes.is_a?( Array )
27
+ bytes = str_or_bytes
28
+ else ## assume string
29
+ str = str_or_bytes
30
+ bytes = str.each_char.reduce([]) do |bytes,char|
31
+ byte = number[char]
32
+ raise ArgumentError, "Value passed not a valid base58 string - >#{char}< not found in alphabet" if byte.nil?
33
+ bytes << byte
34
+ bytes
35
+ end
36
+ end
37
+ Base58._pack( bytes )
38
+ end
39
+
40
+ end # class Base
41
+ end # module Base58
@@ -0,0 +1,85 @@
1
+ module Base58
2
+
3
+ BASE = 58 # ALPHABET.length == 58 ## 58 chars/letters/digits
4
+
5
+ class Configuration
6
+
7
+ MAPPING = {
8
+ bitcoin: Bitcoin,
9
+ ## flickr: Flickr,
10
+ }
11
+
12
+ attr_reader :format
13
+
14
+ def initialize
15
+ @format = Bitcoin
16
+ end
17
+
18
+ def format=(value)
19
+ if value.is_a?( Symbol )
20
+ @format = MAPPING[ value ]
21
+ else ## assume class
22
+ @format = value
23
+ end
24
+ end
25
+ end # class Configuration
26
+
27
+ ## lets you use
28
+ ## Base58.configure do |config|
29
+ ## config.format = :bitcoin
30
+ ## end
31
+
32
+ def self.configuration
33
+ @configuration ||= Configuration.new
34
+ end
35
+
36
+ def self.configure
37
+ yield( configuration )
38
+ end
39
+
40
+ ## add convenience helper for format
41
+ def self.format() configuration.format; end
42
+ def self.format=(value) self.configuration.format = value; end
43
+
44
+
45
+
46
+
47
+ def self.encode( num_or_bytes, klass: configuration.format )
48
+ klass.encode( num_or_bytes )
49
+ end
50
+
51
+ def self.decode( str_or_bytes, klass: configuration.format )
52
+ klass.decode( str_or_bytes )
53
+ end
54
+
55
+
56
+
57
+
58
+ ####
59
+ # (private) helper - note: leading underscore in name e.g. _bytes
60
+ def self._bytes( num )
61
+ b = []
62
+ while num >= BASE
63
+ mod = num % BASE
64
+ b << mod
65
+ num = (num - mod) / BASE
66
+ end
67
+ b << num
68
+ b = b.reverse
69
+ b
70
+ end
71
+
72
+ def self._pack( bytes )
73
+ num = 0
74
+ bytes.reverse.each_with_index do |byte,index|
75
+ num += byte * (BASE**(index))
76
+ end
77
+ num
78
+ end
79
+
80
+ ## encoding alphabet - letter-to-number by index / array
81
+ def self.alphabet( klass: configuration.format ) klass.alphabet; end
82
+
83
+ ## decoding letter-to-number mapping / hash
84
+ def self.number( klass: configuration.format ) klass.number; end
85
+ end # module Base58
@@ -0,0 +1,85 @@
1
+
2
+
3
+ module Base58
4
+ class Bitcoin < Base
5
+
6
+ ALPHABET = %w[ 1 2 3 4 5 6 7 8 9
7
+ A B C D E F G H J K L M N P Q R S T U V W X Y Z
8
+ a b c d e f g h i j k m n o p q r s t u v w x y z ]
9
+
10
+
11
+ def self.alphabet() ALPHABET; end ## add alpha / char aliases - why? why not?
12
+
13
+ ## Note:
14
+ ## for decoding allow (misspelled) l/I for 1 - why? why not?
15
+ ## and (misspelled) 0/O for o - why? why not?
16
+
17
+
18
+ NUMBER = {
19
+ '1' => 0, ## 'l' => 0, 'I' => 0,
20
+ '2' => 1,
21
+ '3' => 2,
22
+ '4' => 3,
23
+ '5' => 4,
24
+ '6' => 5,
25
+ '7' => 6,
26
+ '8' => 7,
27
+ '9' => 8,
28
+ 'A' => 9,
29
+ 'B' => 10,
30
+ 'C' => 11,
31
+ 'D' => 12,
32
+ 'E' => 13,
33
+ 'F' => 14,
34
+ 'G' => 15,
35
+ 'H' => 16,
36
+ 'J' => 17,
37
+ 'K' => 18,
38
+ 'L' => 19,
39
+ 'M' => 20,
40
+ 'N' => 21,
41
+ 'P' => 22,
42
+ 'Q' => 23,
43
+ 'R' => 24,
44
+ 'S' => 25,
45
+ 'T' => 26,
46
+ 'U' => 27,
47
+ 'V' => 28,
48
+ 'W' => 29,
49
+ 'X' => 30,
50
+ 'Y' => 31,
51
+ 'Z' => 32,
52
+ 'a' => 33,
53
+ 'b' => 34,
54
+ 'c' => 35,
55
+ 'd' => 36,
56
+ 'e' => 37,
57
+ 'f' => 38,
58
+ 'g' => 39,
59
+ 'h' => 40,
60
+ 'i' => 41,
61
+ 'j' => 42,
62
+ 'k' => 43,
63
+ 'm' => 44,
64
+ 'n' => 45,
65
+ 'o' => 46, ## '0' => 46, 'O' => 46,
66
+ 'p' => 47,
67
+ 'q' => 48,
68
+ 'r' => 49,
69
+ 's' => 50,
70
+ 't' => 51,
71
+ 'u' => 52,
72
+ 'v' => 53,
73
+ 'w' => 54,
74
+ 'x' => 55,
75
+ 'y' => 56,
76
+ 'z' => 57,
77
+ }
78
+
79
+ def self.number() NUMBER; end ## add num alias - why? why not?
80
+
81
+ ## add shortcuts (convenience) aliases
82
+ NUM = NUMBER
83
+
84
+ end # class Bitcoin
85
+ end # module Base58
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Base58
4
4
  MAJOR = 0
5
- MINOR = 0
6
- PATCH = 1
5
+ MINOR = 1
6
+ PATCH = 0
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
@@ -0,0 +1,10 @@
1
+ ## $:.unshift(File.dirname(__FILE__))
2
+
3
+ ## minitest setup
4
+
5
+ require 'minitest/autorun'
6
+
7
+
8
+ ## our own code
9
+
10
+ require 'base58-alphabets'
@@ -0,0 +1,34 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_base58_bitcoin.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestBase58Bitcoin < MiniTest::Test
10
+
11
+
12
+ def test_bitcoin
13
+ assert_equal "2j", Base58::Bitcoin.encode( 100 )
14
+ assert_equal "4fr", Base58::Bitcoin.encode( 12345 )
15
+ assert_equal "b2pH", Base58::Bitcoin.encode( 6639914 )
16
+
17
+ assert_equal 100, Base58::Bitcoin.decode( "2j" )
18
+ assert_equal 12345, Base58::Bitcoin.decode( "4fr" )
19
+ assert_equal 6639914, Base58::Bitcoin.decode( "b2pH" )
20
+
21
+
22
+ Base58.format = :bitcoin
23
+ assert_equal "2j", Base58.encode( 100 )
24
+ assert_equal "4fr", Base58.encode( 12345 )
25
+ assert_equal "b2pH", Base58.encode( 6639914 )
26
+
27
+ assert_equal 100, Base58.decode( "2j" )
28
+ assert_equal 12345, Base58.decode( "4fr" )
29
+ assert_equal 6639914, Base58.decode( "b2pH" )
30
+ end
31
+
32
+
33
+
34
+ end # class TestBase58Bitcoin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: base58-alphabets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
@@ -59,7 +59,12 @@ files:
59
59
  - README.md
60
60
  - Rakefile
61
61
  - lib/base58-alphabets.rb
62
+ - lib/base58-alphabets/base.rb
63
+ - lib/base58-alphabets/base58.rb
64
+ - lib/base58-alphabets/bitcoin.rb
62
65
  - lib/base58-alphabets/version.rb
66
+ - test/helper.rb
67
+ - test/test_base58_bitcoin.rb
63
68
  homepage: https://github.com/rubycoco/blockchain
64
69
  licenses:
65
70
  - Public Domain