Created
January 25, 2017 20:59
-
-
Save yaronvel/1478182d0bd49dad58bcd0c4edf5ae3e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract SHA3_512_Wrapper { | |
function sponge(uint[9] M) constant returns(uint[16]); | |
} | |
contract Ethash { | |
SHA3_512_Wrapper sha3_512; | |
function Ethash() { | |
sha3_512 = SHA3_512_Wrapper(0xe78a0f7e598cc8b0bb87894b0f60dd2a88d6a8ab); | |
} | |
uint merkleRoot = 0xcddd312dd2c15f394a49b417cd01bd2cabe7b863cbe3b65bfa22e4012da15bb4; | |
function setMerkleRoot(uint root) { | |
merkleRoot = root; | |
} | |
/* | |
function sha3_512(bytes32 header, bytes8 nonceLe ) constant returns (uint[16]) { | |
return [uint(0),1,2,3,4,5,6,7,8,9,10,11,12,13,14,16]; | |
}*/ | |
function fnv( uint v1, uint v2 ) constant returns(uint) { | |
return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF; | |
} | |
function computeCacheRoot( uint index, | |
uint[] dataSetLookup, | |
uint[] witness, | |
uint witnessIndex ) constant returns(uint) { | |
uint leaf = uint( sha3(dataSetLookup[4*witnessIndex], | |
dataSetLookup[4*witnessIndex + 1], | |
dataSetLookup[4*witnessIndex + 2], | |
dataSetLookup[4*witnessIndex + 3]) ); | |
uint[4] memory offsets = [ uint(2**0), 2**64, 2**128, 2**192]; | |
uint left; | |
uint right; | |
// witness[] stores 5 uint per cache element, each uint is 4 nodes | |
for( uint depth = 0 ; depth < 20 ; depth++ ) { | |
leaf = leaf & 0xFFFFFFFFFFFFFFFF; | |
// use offsets array to avoid expensive exp | |
uint node = (witness[5*witnessIndex + depth/4] / offsets[depth%4])&0xFFFFFFFFFFFFFFFF; | |
if( index & 0x1 > 0 ) { | |
left = leaf; | |
right = node; | |
} | |
else { | |
left = node; | |
right = leaf; | |
} | |
leaf = uint(sha3(left,right)); | |
index = index / 2; | |
} | |
return leaf; | |
} | |
function toBE( uint x ) constant returns(uint) { | |
uint y = 0; | |
for( uint i = 0 ; i < 32 ; i++ ) { | |
y = y * 256; | |
y += (x & 0xFF); | |
x = x / 256; | |
} | |
return y; | |
} | |
function computeSha3( uint[16] s, uint[8] cmix ) constant returns(uint) { | |
uint s0 = s[0] + s[1] * (2**32) + s[2] * (2**64) + s[3] * (2**96) + | |
(s[4] + s[5] * (2**32) + s[6] * (2**64) + s[7] * (2**96))*(2**128); | |
uint s1 = s[8] + s[9] * (2**32) + s[10] * (2**64) + s[11] * (2**96) + | |
(s[12] + s[13] * (2**32) + s[14] * (2**64) + s[15] * (2**96))*(2**128); | |
uint c = cmix[0] + cmix[1] * (2**32) + cmix[2] * (2**64) + cmix[3] * (2**96) + | |
(cmix[4] + cmix[5] * (2**32) + cmix[6] * (2**64) + cmix[7] * (2**96))*(2**128); | |
/* god knows why need to convert to big endian */ | |
return uint( sha3(toBE(s0),toBE(s1),toBE(c)) ); | |
} | |
event Log( string msg, uint i, uint p ); | |
function hashimoto( bytes32 header, | |
bytes8 nonceLe, | |
uint fullSize, | |
uint[] dataSetLookup, | |
uint[] witnessForLookup ) constant returns(uint) { | |
uint[16] memory s; | |
uint[32] memory mix; | |
uint[8] memory cmix; | |
uint[9] memory M; | |
uint i; | |
uint j; | |
uint headerAsInt = uint(header); | |
M[0] = uint(headerAsInt) & 0xFFFFFFFFFFFFFFFF; | |
headerAsInt = headerAsInt / 2**64; | |
M[1] = uint(headerAsInt) & 0xFFFFFFFFFFFFFFFF; | |
headerAsInt = headerAsInt / 2**64; | |
M[2] = uint(headerAsInt) & 0xFFFFFFFFFFFFFFFF; | |
headerAsInt = headerAsInt / 2**64; | |
M[3] = uint(headerAsInt) & 0xFFFFFFFFFFFFFFFF; | |
M[4] = uint(nonceLe); | |
s = sha3_512.sponge(M); | |
for( i = 0 ; i < 16 ; i++ ) { | |
mix[i] = s[i]; | |
mix[i+16] = s[i]; | |
} | |
for( i = 0 ; i < 64 ; i++ ) { | |
uint p = (fnv( i ^ s[0], mix[i % 32]) % (fullSize / 2)) * 2; | |
/* | |
if( computeCacheRoot(p,dataSetLookup,witnessForLookup,i) != merkleRoot ) { | |
// PoW failed | |
Log("computeCacheRoot failed", i, p); | |
return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; | |
}*/ | |
for( j = 0 ; j < 8 ; j++ ) { | |
mix[j] = fnv(mix[j], dataSetLookup[4*i] & 0xFFFFFFFF ); | |
mix[j+8] = fnv(mix[j+8], dataSetLookup[4*i + 1] & 0xFFFFFFFF ); | |
mix[j+16] = fnv(mix[j+16], dataSetLookup[4*i + 2] & 0xFFFFFFFF ); | |
mix[j+24] = fnv(mix[j+24], dataSetLookup[4*i + 3] & 0xFFFFFFFF ); | |
dataSetLookup[4*i ] = dataSetLookup[4*i ]/(2**32); | |
dataSetLookup[4*i + 1] = dataSetLookup[4*i + 1]/(2**32); | |
dataSetLookup[4*i + 2] = dataSetLookup[4*i + 2]/(2**32); | |
dataSetLookup[4*i + 3] = dataSetLookup[4*i + 3]/(2**32); | |
} | |
} | |
for( i = 0 ; i < 32 ; i += 4) { | |
cmix[i/4] = (fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3])); | |
} | |
Log("Ok",0,0); | |
return computeSha3(s,cmix); | |
} | |
function h(uint32 x, uint32 y) constant returns(uint) { | |
uint32[2] memory z; | |
z[0] = x; | |
z[1] = y; | |
return uint(sha3(z)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.1; | |
contract SHA3_512 { | |
function SHA3_512() {} | |
event Result(uint result); | |
function keccak_f(uint[25] A) constant returns(uint[25]) { | |
uint[5] memory C; | |
uint D_0; uint D_1; uint D_2; uint D_3; uint D_4; | |
uint[25] memory B; | |
uint[24] memory RC= [ | |
uint(0x0000000000000001), | |
0x0000000000008082, | |
0x800000000000808A, | |
0x8000000080008000, | |
0x000000000000808B, | |
0x0000000080000001, | |
0x8000000080008081, | |
0x8000000000008009, | |
0x000000000000008A, | |
0x0000000000000088, | |
0x0000000080008009, | |
0x000000008000000A, | |
0x000000008000808B, | |
0x800000000000008B, | |
0x8000000000008089, | |
0x8000000000008003, | |
0x8000000000008002, | |
0x8000000000000080, | |
0x000000000000800A, | |
0x800000008000000A, | |
0x8000000080008081, | |
0x8000000000008080, | |
0x0000000080000001, | |
0x8000000080008008 ]; | |
for( uint i = 0 ; i < 24 ; i++ ) { | |
/* Theta step */ | |
C[0]=A[0]^A[1]^A[2]^A[3]^A[4]; | |
C[1]=A[5]^A[6]^A[7]^A[8]^A[9]; | |
C[2]=A[10]^A[11]^A[12]^A[13]^A[14]; | |
C[3]=A[15]^A[16]^A[17]^A[18]^A[19]; | |
C[4]=A[20]^A[21]^A[22]^A[23]^A[24]; | |
D_0=C[4] ^ ((C[1] * 2)&0xffffffffffffffff | (C[1] / (2 ** 63))); | |
D_1=C[0] ^ ((C[2] * 2)&0xffffffffffffffff | (C[2] / (2 ** 63))); | |
D_2=C[1] ^ ((C[3] * 2)&0xffffffffffffffff | (C[3] / (2 ** 63))); | |
D_3=C[2] ^ ((C[4] * 2)&0xffffffffffffffff | (C[4] / (2 ** 63))); | |
D_4=C[3] ^ ((C[0] * 2)&0xffffffffffffffff | (C[0] / (2 ** 63))); | |
A[0]=A[0] ^ D_0; | |
A[1]=A[1] ^ D_0; | |
A[2]=A[2] ^ D_0; | |
A[3]=A[3] ^ D_0; | |
A[4]=A[4] ^ D_0; | |
A[5]=A[5] ^ D_1; | |
A[6]=A[6] ^ D_1; | |
A[7]=A[7] ^ D_1; | |
A[8]=A[8] ^ D_1; | |
A[9]=A[9] ^ D_1; | |
A[10]=A[10] ^ D_2; | |
A[11]=A[11] ^ D_2; | |
A[12]=A[12] ^ D_2; | |
A[13]=A[13] ^ D_2; | |
A[14]=A[14] ^ D_2; | |
A[15]=A[15] ^ D_3; | |
A[16]=A[16] ^ D_3; | |
A[17]=A[17] ^ D_3; | |
A[18]=A[18] ^ D_3; | |
A[19]=A[19] ^ D_3; | |
A[20]=A[20] ^ D_4; | |
A[21]=A[21] ^ D_4; | |
A[22]=A[22] ^ D_4; | |
A[23]=A[23] ^ D_4; | |
A[24]=A[24] ^ D_4; | |
/*Rho and pi steps*/ | |
B[0]=A[0]; | |
B[8]=((A[1] * (2 ** 36))&0xffffffffffffffff | (A[1] / (2 ** 28))); | |
B[11]=((A[2] * (2 ** 3))&0xffffffffffffffff | (A[2] / (2 ** 61))); | |
B[19]=((A[3] * (2 ** 41))&0xffffffffffffffff | (A[3] / (2 ** 23))); | |
B[22]=((A[4] * (2 ** 18))&0xffffffffffffffff | (A[4] / (2 ** 46))); | |
B[2]=((A[5] * (2 ** 1))&0xffffffffffffffff | (A[5] / (2 ** 63))); | |
B[5]=((A[6] * (2 ** 44))&0xffffffffffffffff | (A[6] / (2 ** 20))); | |
B[13]=((A[7] * (2 ** 10))&0xffffffffffffffff | (A[7] / (2 ** 54))); | |
B[16]=((A[8] * (2 ** 45))&0xffffffffffffffff | (A[8] / (2 ** 19))); | |
B[24]=((A[9] * (2 ** 2))&0xffffffffffffffff | (A[9] / (2 ** 62))); | |
B[4]=((A[10] * (2 ** 62))&0xffffffffffffffff | (A[10] / (2 ** 2))); | |
B[7]=((A[11] * (2 ** 6))&0xffffffffffffffff | (A[11] / (2 ** 58))); | |
B[10]=((A[12] * (2 ** 43))&0xffffffffffffffff | (A[12] / (2 ** 21))); | |
B[18]=((A[13] * (2 ** 15))&0xffffffffffffffff | (A[13] / (2 ** 49))); | |
B[21]=((A[14] * (2 ** 61))&0xffffffffffffffff | (A[14] / (2 ** 3))); | |
B[1]=((A[15] * (2 ** 28))&0xffffffffffffffff | (A[15] / (2 ** 36))); | |
B[9]=((A[16] * (2 ** 55))&0xffffffffffffffff | (A[16] / (2 ** 9))); | |
B[12]=((A[17] * (2 ** 25))&0xffffffffffffffff | (A[17] / (2 ** 39))); | |
B[15]=((A[18] * (2 ** 21))&0xffffffffffffffff | (A[18] / (2 ** 43))); | |
B[23]=((A[19] * (2 ** 56))&0xffffffffffffffff | (A[19] / (2 ** 8))); | |
B[3]=((A[20] * (2 ** 27))&0xffffffffffffffff | (A[20] / (2 ** 37))); | |
B[6]=((A[21] * (2 ** 20))&0xffffffffffffffff | (A[21] / (2 ** 44))); | |
B[14]=((A[22] * (2 ** 39))&0xffffffffffffffff | (A[22] / (2 ** 25))); | |
B[17]=((A[23] * (2 ** 8))&0xffffffffffffffff | (A[23] / (2 ** 56))); | |
B[20]=((A[24] * (2 ** 14))&0xffffffffffffffff | (A[24] / (2 ** 50))); | |
/*Xi state*/ | |
A[0]=B[0]^((~B[5]) & B[10]); | |
A[1]=B[1]^((~B[6]) & B[11]); | |
A[2]=B[2]^((~B[7]) & B[12]); | |
A[3]=B[3]^((~B[8]) & B[13]); | |
A[4]=B[4]^((~B[9]) & B[14]); | |
A[5]=B[5]^((~B[10]) & B[15]); | |
A[6]=B[6]^((~B[11]) & B[16]); | |
A[7]=B[7]^((~B[12]) & B[17]); | |
A[8]=B[8]^((~B[13]) & B[18]); | |
A[9]=B[9]^((~B[14]) & B[19]); | |
A[10]=B[10]^((~B[15]) & B[20]); | |
A[11]=B[11]^((~B[16]) & B[21]); | |
A[12]=B[12]^((~B[17]) & B[22]); | |
A[13]=B[13]^((~B[18]) & B[23]); | |
A[14]=B[14]^((~B[19]) & B[24]); | |
A[15]=B[15]^((~B[20]) & B[0]); | |
A[16]=B[16]^((~B[21]) & B[1]); | |
A[17]=B[17]^((~B[22]) & B[2]); | |
A[18]=B[18]^((~B[23]) & B[3]); | |
A[19]=B[19]^((~B[24]) & B[4]); | |
A[20]=B[20]^((~B[0]) & B[5]); | |
A[21]=B[21]^((~B[1]) & B[6]); | |
A[22]=B[22]^((~B[2]) & B[7]); | |
A[23]=B[23]^((~B[3]) & B[8]); | |
A[24]=B[24]^((~B[4]) & B[9]); | |
/*Last step*/ | |
A[0]=A[0]^RC[i]; | |
} | |
return A; | |
} | |
function sponge(uint[9] M) constant returns(uint[16]) { | |
if( (M.length * 8) != 72 ) throw; | |
M[5] = 0x01; | |
M[8] = 0x8000000000000000; | |
uint r = 72; | |
uint w = 8; | |
uint size = M.length * 8; | |
uint[25] memory S; | |
uint i; uint y; uint x; | |
/*Absorbing Phase*/ | |
for( i = 0 ; i < size/r ; i++ ) { | |
for( y = 0 ; y < 5 ; y++ ) { | |
for( x = 0 ; x < 5 ; x++ ) { | |
if( (x+5*y) < (r/w) ) { | |
S[5*x+y] = S[5*x+y] ^ M[i*9 + x + 5*y]; | |
} | |
} | |
} | |
S = keccak_f(S); | |
} | |
/*Squeezing phase*/ | |
uint[16] memory result; | |
uint b = 0; | |
while( b < 16 ) { | |
for( y = 0 ; y < 5 ; y++ ) { | |
for( x = 0 ; x < 5 ; x++ ) { | |
if( (x+5*y)<(r/w) && (b<16) ) { | |
result[b] = S[5*x+y] & 0xFFFFFFFF; | |
result[b+1] = S[5*x+y] / 0x100000000; | |
b+=2; | |
} | |
} | |
} | |
} | |
Result(result[0]); | |
Result(result[1]); | |
Result(result[2]); | |
Result(result[3]); | |
Result(result[4]); | |
Result(result[5]); | |
Result(result[6]); | |
Result(result[7]); | |
Result(result[8]); | |
Result(result[9]); | |
Result(result[10]); | |
Result(result[11]); | |
Result(result[12]); | |
Result(result[13]); | |
Result(result[14]); | |
Result(result[15]); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment