daily pastebin goal
48%
SHARE
TWEET

Untitled

a guest Jun 1st, 2011 280 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. require 'digest'
  2.  
  3. class BlockHeader
  4.   # Block header          : 160 bytes
  5.   # - Version             : 4 bytes
  6.   # - Previous block hash : 32 bytes
  7.   # - Merkle root         : 32 bytes
  8.   # - Timestamp           : 4 bytes
  9.   # - Bits                : 4 bytes
  10.   # - Nonce               : 4 bytes
  11.  
  12.   attr_accessor :raw,
  13.     :previous_block,
  14.     :nonce,
  15.     :timestamp,
  16.     :version,
  17.     :merkle_root,
  18.     :bits
  19.  
  20.   # Initialize block header from a raw pool solution
  21.   def initialize(raw)
  22.     self.raw = raw
  23.   end
  24.  
  25.   def raw=(str)
  26.     # We keep only the first 80 bytes of data
  27.     @raw = str[0, 160]
  28.   end
  29.  
  30.   def version
  31.     @version ||= @raw[0, 8].hex
  32.   end
  33.  
  34.   def previous_block
  35.     @previous_block ||= word_reverse(@raw[8, 64])
  36.   end
  37.  
  38.   def merkle_root
  39.     @merkle_root ||= word_reverse(@raw[72, 64])
  40.   end
  41.  
  42.   def timestamp
  43.     @timestamp ||= @raw[136, 8].hex
  44.   end
  45.  
  46.   def bits
  47.     @bits ||= @raw[144, 8].hex
  48.   end
  49.  
  50.   def nonce
  51.     @nonce ||= @raw[152, 8].hex
  52.   end
  53.  
  54.   # Reverses a string using chunks of 8 chars (4 hex bytes)
  55.   def word_reverse(str)
  56.     res = []
  57.  
  58.     while str.length > 0 do
  59.       res << str[-8, 8]
  60.       str = str[0, str.length - 8]
  61.     end
  62.  
  63.     res.join
  64.   end
  65.  
  66.   # Computes a block hash from the block header fields
  67.   def block_hash
  68.     byte_reverse Digest::SHA2.hexdigest(Digest::SHA2.digest(hex2bin(hashable_string)))
  69.   end
  70.  
  71.   private
  72.     # Converts a hex string to binary, without 0x00 byte ending
  73.     def hex2bin(str)
  74.       (0..((str.length/2)-1)).inject([]) do |r, i|
  75.         r << [str[i*2, 2]].pack("H2")
  76.       end.join
  77.     end
  78.  
  79.     # Converts a binary string to hex
  80.     def bin2hex(str)
  81.       str.unpack("H*")[0]
  82.     end
  83.  
  84.     # Creates the hashed string from block header fields in little endian
  85.     def hashable_string
  86.       byte_reverse("%08x" % version) +
  87.         byte_reverse(previous_block) +
  88.         byte_reverse(merkle_root) +
  89.         byte_reverse("%08x" % timestamp) +
  90.         byte_reverse("%08x" % bits) +
  91.         byte_reverse("%08x" % nonce)
  92.     end
  93.  
  94.     # Takes a hex string and reverses all bytes to switch endianness
  95.     def byte_reverse(str)
  96.       bin2hex(hex2bin(str).reverse)
  97.     end
  98. end
RAW Paste Data
Top