class Ethereum::Miner

Public Class Methods

check_pow(block_number, header_hash, mixhash, nonce, difficulty) click to toggle source
# File lib/ethereum/miner.rb, line 6
def check_pow(block_number, header_hash, mixhash, nonce, difficulty)
  Logger.new('eth.miner').debug "checking pow",  block_number: block_number

  return false if mixhash.size != 32 || header_hash.size != 32 || nonce.size != 8

  cache = Ethash.get_cache block_number
  mining_output = hashimoto_light block_number, cache, header_hash, nonce

  return false if mining_output[:mixhash] != mixhash
  return Utils.big_endian_to_int(mining_output[:result]) <= (Constant::TT256 / difficulty)
end
hashimoto_light(*args) click to toggle source
# File lib/ethereum/miner.rb, line 19
def hashimoto_light(*args)
  Ethash.hashimoto_light(*args)
end
new(block) click to toggle source

Mines on the current head. Stores received transactions.

The process of finalising a block involves four stages:

  1. validate (or, if mining, determine) uncles;

  2. validate (or, if mining, determine) transactions;

  3. apply rewards;

  4. verify (or, if mining, compute a valid) state and nonce.

# File lib/ethereum/miner.rb, line 35
def initialize(block)
  @nonce = 0
  @block = block

  logger.debug "mining", block_number: @block.number, block_hash: Utils.encode_hex(@block.full_hash), block_difficulty: @block.difficulty
end

Public Instance Methods

mine(rounds=1000, start_nonce=0) click to toggle source
# File lib/ethereum/miner.rb, line 42
def mine(rounds=1000, start_nonce=0)
  blk = @block
  bin_nonce, mixhash = _mine(blk.number, blk.difficulty, blk.mining_hash, start_nonce, rounds)

  if bin_nonce.true?
    blk.mixhash = mixhash
    blk.nonce = bin_nonce
    return blk
  end
end

Private Instance Methods

_mine(block_number, difficulty, mining_hash, start_nonce=0, rounds=1000) click to toggle source
# File lib/ethereum/miner.rb, line 59
def _mine(block_number, difficulty, mining_hash, start_nonce=0, rounds=1000)
  raise AssertError, "start nonce must be an integer" unless start_nonce.is_a?(Integer)

  cache = Ethash.get_cache block_number
  nonce = start_nonce
  difficulty ||= 1
  target = Utils.zpad Utils.int_to_big_endian(Constant::TT256 / difficulty), 32

  (1..rounds).each do |i|
    bin_nonce = Utils.zpad Utils.int_to_big_endian((nonce+i) & Constant::TT64M1), 8
    o = Miner.hashimoto_light block_number, cache, mining_hash, bin_nonce

    if o[:result] <= target
      logger.debug "nonce found"
      raise AssertError, "nonce must be 8 bytes long" unless bin_nonce.size == 8
      raise AssertError, "mishash must be 32 bytes long" unless o[:mixhash].size == 32
      return bin_nonce, o[:mixhash]
    end
  end

  return nil, nil
end
logger() click to toggle source
# File lib/ethereum/miner.rb, line 55
def logger
  @logger ||= Logger.new 'eth.miner'
end