Class: Ethereum::EthashRuby::Hashimoto

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/ethereum/ethash_ruby/hashimoto.rb

Instance Method Summary collapse

Methods included from Utils

#decode_int, #deserialize_hash, #encode_int, #hash_words, #keccak256, #keccak512, #serialize_hash, #zpad

Instance Method Details

#calc_dataset_item(cache, i) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ethereum/ethash_ruby/hashimoto.rb', line 45

def calc_dataset_item(cache, i)
  n = cache.size
  r = HASH_BYTES / WORD_BYTES

  mix = cache[i % n].dup
  mix[0] ^= i
  mix = keccak512 mix

  DATASET_PARENTS.times do |j|
    cache_index = fnv(i ^ j, mix[j % r])
    mix = mix.zip(cache[cache_index % n]).map {|(v1,v2)| fnv(v1, v2) }
  end

  keccak512(mix)
end

#fnv(v1, v2) ⇒ Object



61
62
63
# File 'lib/ethereum/ethash_ruby/hashimoto.rb', line 61

def fnv(v1, v2)
  (v1 * FNV_PRIME ^ v2) % Constant::TT32
end

#get_full_size(block_number) ⇒ Object



65
66
67
68
69
70
# File 'lib/ethereum/ethash_ruby/hashimoto.rb', line 65

def get_full_size(block_number)
  sz = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number / EPOCH_LENGTH)
  sz -= MIX_BYTES
  sz -= 2 * MIX_BYTES while !Prime.prime?(sz / MIX_BYTES)
  sz
end

#light(block_number, cache, header, nonce) ⇒ Object



11
12
13
14
15
# File 'lib/ethereum/ethash_ruby/hashimoto.rb', line 11

def light(block_number, cache, header, nonce)
  run header, nonce, get_full_size(block_number) do |x|
    calc_dataset_item(cache, x)
  end
end

#run(header, nonce, full_size, &dataset_lookup) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ethereum/ethash_ruby/hashimoto.rb', line 17

def run(header, nonce, full_size, &dataset_lookup)
  n = full_size / HASH_BYTES
  w = MIX_BYTES / WORD_BYTES
  mixhashes = MIX_BYTES / HASH_BYTES

  s = keccak512(header + nonce.reverse)

  mix = []
  mixhashes.times { mix.concat s }

  ACCESSES.times do |i|
    p = fnv(i ^ s[0], mix[i % w]) % (n / mixhashes) * mixhashes

    newdata = []
    mixhashes.times {|j| newdata.concat dataset_lookup.call(p + j) }
    mix = mix.zip(newdata).map {|(a,b)| fnv(a, b) }
  end

  cmix = []
  (mix.size / WORD_BYTES).times do |i|
    i *= WORD_BYTES
    cmix.push fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3])
  end

  { mixhash: serialize_hash(cmix),
    result: serialize_hash(keccak256(s + cmix)) }
end