hackedteam/rcs-db

View on GitHub
scripts/coins/b58encode.rb

Summary

Maintainability
B
4 hrs
Test Coverage
require 'digest'

module B58Encode
  extend self
  
  @@__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  @@__b58base = @@__b58chars.bytesize

  def self.encode(v)
    # encode v, which is a string of bytes, to base58.    

    long_value = 0
    
    v.chars.to_a.reverse.each_with_index do |c, i| 
      long_value += (256**i) * c.ord
    end

    result = ''
    
    while long_value >= @@__b58base do
      div, mod = long_value.divmod(@@__b58base)
      result = @@__b58chars[mod] + result
      long_value = div
    end
      
    result = @@__b58chars[long_value] + result

    # Bitcoin does a little leading-zero-compression:
    # leading 0-bytes in the input become leading-1s
    nPad = 0
    v.chars.to_a.each do |c|
      if c == "\0"
        nPad += 1
      else
        break
      end
    end
    
    return (@@__b58chars[0]*nPad) + result
  end
  
  def self.decode(v, length)
    #decode v into a string of len bytes

    long_value = 0

    v.chars.to_a.reverse.each_with_index do |c, i| 
      long_value += @@__b58chars.index(c) * (@@__b58base**i)
    end
    
    result = ''
    
    while long_value >= 256 do
      div, mod = long_value.divmod(256)
      result = mod.chr + result
      long_value = div
    end
    
    result = long_value.chr + result

    nPad = 0
    v.chars.to_a.each do |c|
      if c == @@__b58chars[0]
         nPad += 1
      else
         break
      end
    end
    
    result = 0.chr*nPad + result
    
    if !length.nil? and result.size != length
      return nil
    end

    return result  
  end
  
  def hash_160(public_key)
    h1 = Digest::SHA256.new.digest(public_key)
    h2 = Digest::RMD160.new.digest(h1)
    return h2
  end

  def public_key_to_bc_address(public_key, version = "\x00")
    h160 = hash_160(public_key)
    return hash_160_to_bc_address(h160, version=version)
  end

  def hash_160_to_bc_address(h160, version = "\x00")
    vh160 = version + h160
    h3 = Digest::SHA256.new.digest(Digest::SHA256.new.digest(vh160))
    addr = vh160 + h3[0..3]
    return self.encode(addr)
  end

  def bc_address_to_hash_160(addr)
    bytes = self.decode(addr, 25)
    return bytes[1..20]
  end
end

if __FILE__ == $0
  x = ['005cc87f4a3fdfe3a2346b6953267ca867282630d3f9b78e64'].pack('H*')
  encoded = B58Encode.encode(x)
  puts "#{encoded}, '19TbMSWwHvnxAKy12iNm3KdbGfzfaMFViT'"
  puts "#{B58Encode.decode(encoded, x.bytesize).unpack('H*')}, #{x.unpack('H*')}"
  
  key = "\x03\xF6\x8B\xCE\x1A\a\xC8W\xE0\xB8,\xAD\xF7\x18M\xAE\xC7\xCA\xEA+5;y\x1F1\xA0\xF6\xAF\ny\xA6\x83\x1C"
  address = "1MpehHPzn1dNFqNiZsLRiFEdk75Ck6FhN5"
  
  puts "#{B58Encode.public_key_to_bc_address(key)}, #{address}"
end