Bitcoin Forum
April 25, 2024, 11:18:50 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Ethereum Cache Generation Examples  (Read 155 times)
u87982 (OP)
Newbie
*
Offline Offline

Activity: 6
Merit: 1


View Profile
November 04, 2017, 03:52:24 PM
 #1

Does anyone have an example of Ethereum cache generation with the first few bytes of the cache after the initial dataset creation, then after each round of RandMemoHash?  I'm trying to re-create the code done here: https://github.com/ethereum/wiki/wiki/Ethash in Scala.  I'm getting the wrong results and want to check my work.  If anyone does Scala and wants to see the code, it's below.  I think my problem probably has something to do with byte ordering and I'd like something to check it against.  Thanks.

Code:
import org.bouncycastle.jcajce.provider.digest.SHA3
import org.bouncycastle.util.encoders.Hex

object Ethash {
 
  val CACHE_BYTES_INIT:Long   = Math.pow(2, 24).toLong
  val CACHE_BYTES_GROWTH:Long = Math.pow(2, 17).toLong
  val EPOCH_LENGTH:Long       = 30000
  val HASH_BYTES:Int          = 64
  val CACHE_ROUNDS:Int        = 3
 
  def cacheSize(blockNumber:Long):Long = {
    val linearSize:Long = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (blockNumber / EPOCH_LENGTH) - HASH_BYTES
    Stream.from(0).map(x => linearSize - (2*x*HASH_BYTES)).filter(x => Utilities.isPrime(x/HASH_BYTES)).head
  }
 
  def makeCache(size:Long, seed:Array[Byte]):Array[Byte] = {
    import Utilities.sha3_512
    val n:Int = (size/HASH_BYTES).toInt
   
    //Sequentially produce initial dataset
    val ans = Stream.iterate(seed){x => Utilities.sha3_512(x)}.drop(1).flatten.take(size.toInt).toArray
    val hashes:Array[Sha3Hash] = ans.sliding(64, 64).map { x => new Sha3Hash(x) }.toArray
   
    //Use a low-round version of randmemohash
    0.to(CACHE_ROUNDS-1).foreach{ _ =>
      0.to(n - 1).foreach{ i =>
        val v = (hashes(i).bytes.head & 0xFF) % n
        hashes(i) = new Sha3Hash(sha3_512( hashes((i-1+n) % n).xor(hashes(v)) ))
      }
    }
   
    hashes.map { x => x.bytes.toSeq }.toSeq.flatten.toArray
  }
}

object Utilities {
 
  def isPrime(x:Long):Boolean =
    !2L.to(Math.sqrt(x).toLong).exists{factor => x%factor == 0}
 
  def sha3_512(x:Array[Byte]):Array[Byte] = new SHA3.Digest512().digest(x)
 
}

class Sha3Hash(val bytes:Array[Byte]) {
  if (bytes.size != 64) throw new Exception(s"Byte array for a Sha3Hash must be 64 bytes")

  def xor(other:Sha3Hash):Array[Byte] = bytes.zip(other.bytes).map(pr => (pr._1 ^ pr._2).toByte).toArray
 
  override def toString = Hex.toHexString(bytes)
 
}
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!