Skip to content

Instantly share code, notes, and snippets.

@yaronvel
Created February 23, 2017 07:52
Show Gist options
  • Select an option

  • Save yaronvel/49822d76105b45ebe4becb92ac4c607b to your computer and use it in GitHub Desktop.

Select an option

Save yaronvel/49822d76105b45ebe4becb92ac4c607b to your computer and use it in GitHub Desktop.
pragma solidity ^0.4.9;
import "./Ethash_asm.sol";
/**
* @title RLPReader
*
* RLPReader is used to read and parse RLP encoded data in memory.
*
* @author Andreas Olofsson ([email protected])
*/
library RLP {
uint constant DATA_SHORT_START = 0x80;
uint constant DATA_LONG_START = 0xB8;
uint constant LIST_SHORT_START = 0xC0;
uint constant LIST_LONG_START = 0xF8;
uint constant DATA_LONG_OFFSET = 0xB7;
uint constant LIST_LONG_OFFSET = 0xF7;
struct RLPItem {
uint _unsafe_memPtr; // Pointer to the RLP-encoded bytes.
uint _unsafe_length; // Number of bytes. This is the full length of the string.
}
struct Iterator {
RLPItem _unsafe_item; // Item that's being iterated over.
uint _unsafe_nextPtr; // Position of the next item in the list.
}
/* Iterator */
function next(Iterator memory self) internal constant returns (RLPItem memory subItem) {
if(hasNext(self)) {
var ptr = self._unsafe_nextPtr;
var itemLength = _itemLength(ptr);
subItem._unsafe_memPtr = ptr;
subItem._unsafe_length = itemLength;
self._unsafe_nextPtr = ptr + itemLength;
}
else
throw;
}
function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) {
subItem = next(self);
if(strict && !_validate(subItem))
throw;
return;
}
function hasNext(Iterator memory self) internal constant returns (bool) {
var item = self._unsafe_item;
return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length;
}
/* RLPItem */
/// @dev Creates an RLPItem from an array of RLP encoded bytes.
/// @param self The RLP encoded bytes.
/// @return An RLPItem
function toRLPItem(bytes memory self) internal constant returns (RLPItem memory) {
uint len = self.length;
if (len == 0) {
return RLPItem(0, 0);
}
uint memPtr;
assembly {
memPtr := add(self, 0x20)
}
return RLPItem(memPtr, len);
}
/// @dev Creates an RLPItem from an array of RLP encoded bytes.
/// @param self The RLP encoded bytes.
/// @param strict Will throw if the data is not RLP encoded.
/// @return An RLPItem
function toRLPItem(bytes memory self, bool strict) internal constant returns (RLPItem memory) {
var item = toRLPItem(self);
if(strict) {
uint len = self.length;
if(_payloadOffset(item) > len)
throw;
if(_itemLength(item._unsafe_memPtr) != len)
throw;
if(!_validate(item))
throw;
}
return item;
}
/// @dev Check if the RLP item is null.
/// @param self The RLP item.
/// @return 'true' if the item is null.
function isNull(RLPItem memory self) internal constant returns (bool ret) {
return self._unsafe_length == 0;
}
/// @dev Check if the RLP item is a list.
/// @param self The RLP item.
/// @return 'true' if the item is a list.
function isList(RLPItem memory self) internal constant returns (bool ret) {
if (self._unsafe_length == 0)
return false;
uint memPtr = self._unsafe_memPtr;
assembly {
ret := iszero(lt(byte(0, mload(memPtr)), 0xC0))
}
}
/// @dev Check if the RLP item is data.
/// @param self The RLP item.
/// @return 'true' if the item is data.
function isData(RLPItem memory self) internal constant returns (bool ret) {
if (self._unsafe_length == 0)
return false;
uint memPtr = self._unsafe_memPtr;
assembly {
ret := lt(byte(0, mload(memPtr)), 0xC0)
}
}
/// @dev Check if the RLP item is empty (string or list).
/// @param self The RLP item.
/// @return 'true' if the item is null.
function isEmpty(RLPItem memory self) internal constant returns (bool ret) {
if(isNull(self))
return false;
uint b0;
uint memPtr = self._unsafe_memPtr;
assembly {
b0 := byte(0, mload(memPtr))
}
return (b0 == DATA_SHORT_START || b0 == LIST_SHORT_START);
}
/// @dev Get the number of items in an RLP encoded list.
/// @param self The RLP item.
/// @return The number of items.
function items(RLPItem memory self) internal constant returns (uint) {
if (!isList(self))
return 0;
uint b0;
uint memPtr = self._unsafe_memPtr;
assembly {
b0 := byte(0, mload(memPtr))
}
uint pos = memPtr + _payloadOffset(self);
uint last = memPtr + self._unsafe_length - 1;
uint itms;
while(pos <= last) {
pos += _itemLength(pos);
itms++;
}
return itms;
}
/// @dev Create an iterator.
/// @param self The RLP item.
/// @return An 'Iterator' over the item.
function iterator(RLPItem memory self) internal constant returns (Iterator memory it) {
if (!isList(self))
throw;
uint ptr = self._unsafe_memPtr + _payloadOffset(self);
it._unsafe_item = self;
it._unsafe_nextPtr = ptr;
}
/// @dev Return the RLP encoded bytes.
/// @param self The RLPItem.
/// @return The bytes.
function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) {
var len = self._unsafe_length;
if (len == 0)
return;
bts = new bytes(len);
_copyToBytes(self._unsafe_memPtr, bts, len);
}
/// @dev Decode an RLPItem into bytes. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toData(RLPItem memory self) internal constant returns (bytes memory bts) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
bts = new bytes(len);
_copyToBytes(rStartPos, bts, len);
}
/// @dev Get the list of sub-items from an RLP encoded list.
/// Warning: This is inefficient, as it requires that the list is read twice.
/// @param self The RLP item.
/// @return Array of RLPItems.
function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) {
if(!isList(self))
throw;
var numItems = items(self);
list = new RLPItem[](numItems);
var it = iterator(self);
uint idx;
while(hasNext(it)) {
list[idx] = next(it);
idx++;
}
}
/// @dev Decode an RLPItem into an ascii string. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toAscii(RLPItem memory self) internal constant returns (string memory str) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
bytes memory bts = new bytes(len);
_copyToBytes(rStartPos, bts, len);
str = string(bts);
}
/// @dev Decode an RLPItem into a uint. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toUint(RLPItem memory self) internal constant returns (uint data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
if (len > 32 || len == 0)
throw;
assembly {
data := div(mload(rStartPos), exp(256, sub(32, len)))
}
}
/// @dev Decode an RLPItem into a boolean. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toBool(RLPItem memory self) internal constant returns (bool data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
if (len != 1)
throw;
uint temp;
assembly {
temp := byte(0, mload(rStartPos))
}
if (temp > 1)
throw;
return temp == 1 ? true : false;
}
/// @dev Decode an RLPItem into a byte. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toByte(RLPItem memory self) internal constant returns (byte data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
if (len != 1)
throw;
uint temp;
assembly {
temp := byte(0, mload(rStartPos))
}
return byte(temp);
}
/// @dev Decode an RLPItem into an int. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toInt(RLPItem memory self) internal constant returns (int data) {
return int(toUint(self));
}
/// @dev Decode an RLPItem into a bytes32. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toBytes32(RLPItem memory self) internal constant returns (bytes32 data) {
return bytes32(toUint(self));
}
/// @dev Decode an RLPItem into an address. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toAddress(RLPItem memory self) internal constant returns (address data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
if (len != 20)
throw;
assembly {
data := div(mload(rStartPos), exp(256, 12))
}
}
// Get the payload offset.
function _payloadOffset(RLPItem memory self) private constant returns (uint) {
if(self._unsafe_length == 0)
return 0;
uint b0;
uint memPtr = self._unsafe_memPtr;
assembly {
b0 := byte(0, mload(memPtr))
}
if(b0 < DATA_SHORT_START)
return 0;
if(b0 < DATA_LONG_START || (b0 >= LIST_SHORT_START && b0 < LIST_LONG_START))
return 1;
if(b0 < LIST_SHORT_START)
return b0 - DATA_LONG_OFFSET + 1;
return b0 - LIST_LONG_OFFSET + 1;
}
// Get the full length of an RLP item.
function _itemLength(uint memPtr) private constant returns (uint len) {
uint b0;
assembly {
b0 := byte(0, mload(memPtr))
}
if (b0 < DATA_SHORT_START)
len = 1;
else if (b0 < DATA_LONG_START)
len = b0 - DATA_SHORT_START + 1;
else if (b0 < LIST_SHORT_START) {
assembly {
let bLen := sub(b0, 0xB7) // bytes length (DATA_LONG_OFFSET)
let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length
len := add(1, add(bLen, dLen)) // total length
}
}
else if (b0 < LIST_LONG_START)
len = b0 - LIST_SHORT_START + 1;
else {
assembly {
let bLen := sub(b0, 0xF7) // bytes length (LIST_LONG_OFFSET)
let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length
len := add(1, add(bLen, dLen)) // total length
}
}
}
// Get start position and length of the data.
function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) {
if(!isData(self))
throw;
uint b0;
uint start = self._unsafe_memPtr;
assembly {
b0 := byte(0, mload(start))
}
if (b0 < DATA_SHORT_START) {
memPtr = start;
len = 1;
return;
}
if (b0 < DATA_LONG_START) {
len = self._unsafe_length - 1;
memPtr = start + 1;
} else {
uint bLen;
assembly {
bLen := sub(b0, 0xB7) // DATA_LONG_OFFSET
}
len = self._unsafe_length - 1 - bLen;
memPtr = start + bLen + 1;
}
return;
}
// Assumes that enough memory has been allocated to store in target.
function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private constant {
// Exploiting the fact that 'tgt' was the last thing to be allocated,
// we can write entire words, and just overwrite any excess.
assembly {
{
let i := 0 // Start at arr + 0x20
let words := div(add(btsLen, 31), 32)
let rOffset := btsPtr
let wOffset := add(tgt, 0x20)
tag_loop:
jumpi(end, eq(i, words))
{
let offset := mul(i, 0x20)
mstore(add(wOffset, offset), mload(add(rOffset, offset)))
i := add(i, 1)
}
jump(tag_loop)
end:
mstore(add(tgt, add(0x20, mload(tgt))), 0)
}
}
}
// Check that an RLP item is valid.
function _validate(RLPItem memory self) private constant returns (bool ret) {
// Check that RLP is well-formed.
uint b0;
uint b1;
uint memPtr = self._unsafe_memPtr;
assembly {
b0 := byte(0, mload(memPtr))
b1 := byte(1, mload(memPtr))
}
if(b0 == DATA_SHORT_START + 1 && b1 < DATA_SHORT_START)
return false;
return true;
}
}
contract RLPReaderTest {
using RLP for RLP.RLPItem;
using RLP for RLP.Iterator;
using RLP for bytes;
function RLPReaderTest() {}
function testItemStrict(bytes rlp) constant returns (bool res) {
res = true;
rlp.toRLPItem(true);
}
function testFirst(bytes rlp) constant returns (uint memPtr, uint len, byte first) {
var item = rlp.toRLPItem();
memPtr = item._unsafe_memPtr;
len = item._unsafe_length;
uint b0;
assembly {
b0 := byte(0, mload(memPtr))
}
first = byte(b0);
}
function testIsList(bytes rlp) constant returns (bool ret) {
ret = rlp.toRLPItem().isList();
}
function testIsData(bytes rlp) constant returns (bool ret) {
ret = rlp.toRLPItem().isData();
}
function testIsNull(bytes rlp) constant returns (bool ret) {
ret = rlp.toRLPItem().isNull();
}
function testIsEmpty(bytes rlp) constant returns (bool ret) {
ret = rlp.toRLPItem().isEmpty();
}
function testItems(bytes rlp) constant returns (uint) {
return rlp.toRLPItem().items();
}
function testSubItem(bytes rlp, uint index) constant returns (uint memPtr, uint len, bool isList, uint[] list, uint listLen) {
var it = rlp.toRLPItem().iterator();
uint idx;
while(it.hasNext() && idx < index) {
it.next();
idx++;
}
var si = it.next();
return _testItem(si);
}
function testToData(bytes rlp) constant returns (bytes memory bts) {
bts = rlp.toRLPItem().toData();
}
function testToUint(bytes rlp) constant returns (uint) {
return rlp.toRLPItem().toUint();
}
function testToInt(bytes rlp) constant returns (int) {
return rlp.toRLPItem().toInt();
}
function testToBytes32(bytes rlp) constant returns (bytes32) {
return rlp.toRLPItem().toBytes32();
}
function testToAddress(bytes rlp) constant returns (address) {
return rlp.toRLPItem().toAddress();
}
function testToByte(bytes rlp) constant returns (byte) {
return rlp.toRLPItem().toByte();
}
function testToBool(bytes rlp) constant returns (bool) {
return rlp.toRLPItem().toBool();
}
function _testItem(RLP.RLPItem item) internal constant returns (uint memPtr, uint len, bool isList, uint[] memory list, uint listLen) {
memPtr = item._unsafe_memPtr;
len = item._unsafe_length;
isList = item.isList();
if (isList) {
uint i;
listLen = item.items();
list = new uint[](listLen);
var it = item.iterator();
while(it.hasNext() && i < listLen) {
var si = it.next();
uint ptr;
assembly {
ptr := mload(si)
}
list[i] = ptr;
i++;
}
}
}
function testItem(bytes rlp) constant returns (uint memPtr, uint len, bool isList, uint[] list, uint listLen) {
var item = rlp.toRLPItem();
return _testItem(item);
}
function getItem(bytes rlp, uint itemIndex) constant returns(uint) {
var it = rlp.toRLPItem().iterator();
uint idx;
while(it.hasNext() && idx < itemIndex) {
it.next();
idx++;
}
return it.next().toUint();
}
}
contract Agt {
using RLP for RLP.RLPItem;
using RLP for RLP.Iterator;
using RLP for bytes;
struct BlockHeader {
uint prevBlockHash; // 0
uint coinbase; // 1
uint blockNumber; // 8
uint timestamp; // 11
bytes32 extraData; // 12
}
function Agt() {}
function parseBlockHeader( bytes rlpHeader ) constant internal returns(BlockHeader) {
BlockHeader memory header;
var it = rlpHeader.toRLPItem().iterator();
uint idx;
while(it.hasNext()) {
if( idx == 0 ) header.prevBlockHash = it.next().toUint();
else if ( idx == 2 ) header.coinbase = it.next().toUint();
else if ( idx == 8 ) header.blockNumber = it.next().toUint();
else if ( idx == 11 ) header.timestamp = it.next().toUint();
else if ( idx == 12 ) header.extraData = bytes32(it.next().toUint());
else it.next();
idx++;
}
return header;
}
event VerifyAgt( string msg, uint index );
struct VerifyAgtData {
uint rootHash;
uint rootMin;
uint rootMax;
uint leafHash;
uint leafCounter;
}
function verifyAgt( /*uint[3] root, // [0] = min, [1] = max, [2] = root hash
uint[2] leafData, // [0] = hash, [1] = counter
//uint leaf32BytesHash,
//uint leafCounter,*/
VerifyAgtData data,
uint branchIndex,
uint[] countersBranch,
uint[] hashesBranch ) constant internal returns(bool) {
uint currentHash = data.leafHash & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint leftCounterMin;
uint leftCounterMax;
uint leftHash;
uint rightCounterMin;
uint rightCounterMax;
uint rightHash;
uint min = data.leafCounter;
uint max = data.leafCounter;
for( uint i = 0 ; i < countersBranch.length ; i++ ) {
if( branchIndex & 0x1 > 0 ) {
leftCounterMin = countersBranch[i] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
leftCounterMax = countersBranch[i] >> 128;
leftHash = hashesBranch[i];
rightCounterMin = min;
rightCounterMax = max;
rightHash = currentHash;
}
else {
leftCounterMin = min;
leftCounterMax = max;
leftHash = currentHash;
rightCounterMin = countersBranch[i] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
rightCounterMax = countersBranch[i] >> 128;
rightHash = hashesBranch[i];
}
currentHash = uint(sha3(leftCounterMin + (leftCounterMax << 128),
leftHash,
rightCounterMin + (rightCounterMax << 128),
rightHash)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
if( (leftCounterMin >= leftCounterMax) || (rightCounterMin >= rightCounterMax) ) {
if( i > 0 ) {
VerifyAgt( "counters mismatch",i);
return false;
}
if( leftCounterMin > leftCounterMax ) {
VerifyAgt( "counters mismatch",i);
return false;
}
if( rightCounterMin > rightCounterMax ) {
VerifyAgt( "counters mismatch",i);
return false;
}
}
if( leftCounterMax >= rightCounterMin ) return false;
min = leftCounterMin;
max = rightCounterMax;
branchIndex = branchIndex / 2;
}
if( min != data.rootMin ) {
VerifyAgt( "min does not match root min",min);
return false;
}
if( max != data.rootMax ) {
VerifyAgt( "max does not match root max",max);
return false;
}
if( currentHash != data.rootHash ) {
VerifyAgt( "hash does not match root hash",currentHash);
return false;
}
return true;
}
}
contract TestPool is Ethash, Agt {
address public minerAddress = 0x00B3B47928458109848009ABCDEFFFEA3459012095;
address public contractAddress = 0x00A1A2A3A4A34598ABCDEFFED45902390854389043;
address public owner;
string public version = "0.0.1";
bool public newVersionReleased = false;
struct SubmissionData {
uint numShares;
uint difficulty;
uint min;
uint max;
uint augMerkle;
uint blockNumber;
}
struct MinerData {
bytes32 minerId;
address paymentAddress;
SubmissionData lastSubmission;
uint lastCounter;
}
mapping(address=>MinerData) minersData;
uint numMiners;
struct EthashCacheData {
uint128 merkleRoot;
uint64 fullSizeIn128Resultion;
uint64 branchDepth;
}
mapping(uint=>EthashCacheData) epochData;
event Debug( string msg );
function TestPool() { owner = msg.sender; }
function declareNewerVersion() {
if( owner != msg.sender ) throw;
newVersionReleased = true;
}
function to56Encoding( uint id, uint numChars ) constant returns(bytes32) {
if( id >= (26+26+10)**numChars ) throw;
uint result = 0;
for( uint i = 0 ; i < numChars ; i++ ) {
uint b = id % (26+26+10);
uint8 char;
if( b < 26 ) {
char = uint8(b + 0x61); //0x61 = 'a'
}
else if( b < 26 + 26 ) {
char = uint8(b + 0x41 - 26); // 0x41 = 'A'
}
else {
char = uint8(b + 0x30 - 52); // 0x30 = '0'
}
result = result * (26+26+10) + char;
id /= (26+26+10);
}
return bytes32(result);
}
function register( uint timestamp, address paymentAddress ) {
// TODO - replace timestamp with now
Debug("register");
minersData[minerAddress].lastCounter = timestamp * (2**64);
minersData[minerAddress].paymentAddress = paymentAddress;
// build id
uint id = uint(minerAddress) % (26+26+10)**11;
minersData[minerAddress].minerId = to56Encoding(id,11);
/*
if( id >= (26+26+10)**5 ) throw; // too many miners
byte[5] memory byteId;
for( uint i = 0 ; i < 5 ; i++ ) {
uint b = id % (26+26+10);
if( b < 26 ) {
byteId[i] = byte(b + 0x61); //0x61 = 'a'
}
else if( b < 26 + 26 ) {
byteId[i] = byte(b + 0x41 - 26); // 0x41 = 'A'
}
else {
byteId[i] = byte(b + 0x30 - 52); // 0x30 = '0'
}
id /= (26+26+10);
}
minersData[minerAddress].minerId = byteId;
*/
}
function getMinerId() constant returns(bytes32) {
return minersData[minerAddress].minerId;
}
function getClaimSeed( ) constant returns(uint){
MinerData memory data = minersData[minerAddress];
if( block.number > data.lastSubmission.blockNumber + 200 ) return 0;
if( block.number <= data.lastSubmission.blockNumber + 1 ) return 0;
return uint(block.blockhash(data.lastSubmission.blockNumber + 1));
}
function submitClaim( uint numShares, uint difficulty, uint min, uint max, uint augMerkle ) {
MinerData memory data = minersData[minerAddress];
if( data.lastCounter >= min ) {
data.lastCounter = max + 1;
Debug("submit claim - miner cheated");
return;
}
MinerData memory newData;
newData.lastCounter = max + 1;
newData.lastSubmission.numShares = numShares;
newData.lastSubmission.difficulty = difficulty;
newData.lastSubmission.min = min;
newData.lastSubmission.max = max;
newData.lastSubmission.augMerkle = augMerkle;
newData.lastSubmission.blockNumber = block.number;
minersData[minerAddress] = newData;
Debug("submit claim ok");
}
function setEpochData( uint128 merkleRoot, uint64 fullSizeIn128Resultion, uint64 branchDepth, uint epoch ) {
EthashCacheData memory data;
data.merkleRoot = merkleRoot;
data.fullSizeIn128Resultion = fullSizeIn128Resultion;
data.branchDepth = branchDepth;
epochData[epoch] = data;
Debug("set epoch data");
}
function verifyExtraData( bytes32 extraData, bytes32 minerId, uint difficulty ) constant returns(bool) {
uint i;
// compare id
for( i = 0 ; i < 11 ; i++ ) {
if( extraData[10+i] != minerId[i] ) {
ErrorLog( "verifyExtraData: miner id not as expected", 0 );
return false;
}
}
// compare difficulty
bytes32 encodedDiff = to56Encoding(difficulty,11);
for( i = 0 ; i < 11 ; i++ ) {
if(extraData[i+21] != encodedDiff[i]) {
ErrorLog( "verifyExtraData: difficulty is not as expected", uint(encodedDiff) );
return false;
}
}
return true;
}
event ErrorLog( string msg, uint i );
event Pay( string msg, uint amount );
function verifyClaim( bytes rlpHeader,
uint nonce,
uint shareIndex,
uint[] dataSetLookup,
uint[] witnessForLookup,
uint[] augCountersBranch,
uint[] augHashesBranch ) returns(uint) {
BlockHeader memory header = parseBlockHeader(rlpHeader);
SubmissionData submissionData = minersData[ minerAddress ].lastSubmission;
// check extra data
if( ! verifyExtraData( header.extraData,
minersData[ minerAddress ].minerId,
submissionData.difficulty ) ) {
ErrorLog( "extra data not as expected", uint(header.extraData) );
return 20;
}
// check counter
uint counter = header.timestamp * (2 ** 64) + nonce;
if( counter < submissionData.min ) {
ErrorLog( "counter is smaller than min",counter);
return 4;
}
if( counter > submissionData.max ) {
ErrorLog( "counter is smaller than max",counter);
return 5;
}
// verify agt
uint leafHash = uint(sha3(rlpHeader));
VerifyAgtData memory agtData;
agtData.rootHash = submissionData.augMerkle;
agtData.rootMin = submissionData.min;
agtData.rootMax = submissionData.max;
agtData.leafHash = leafHash;
agtData.leafCounter = counter;
if( ! verifyAgt( agtData,
shareIndex,
augCountersBranch,
augHashesBranch ) ) {
ErrorLog( "verifyAgt failed",0);
return 6;
}
// get epoch data
EthashCacheData memory eData = epochData[header.blockNumber / 30000];
// verify ethash
uint ethash = hashimoto( bytes32(leafHash),
bytes8(nonce),
eData.fullSizeIn128Resultion,
dataSetLookup,
witnessForLookup,
eData.branchDepth,
eData.merkleRoot );
if( ethash > ((2**256-1)/submissionData.difficulty )) {
ErrorLog( "ethash difficulty too low",ethash);
return 7;
}
if( block.difficulty > 0 ) {
Pay( "verification completed you will be paid",
3 ether * submissionData.difficulty * submissionData.numShares / block.difficulty );
}
else {
Pay( "verification completed you will be paid",
3 ether * submissionData.difficulty * submissionData.numShares / 100000 );
}
return 8;
}
function array( uint[] x ) returns(bytes32){
return sha3(x);
}
function bytesstream( bytes x ) returns(bytes32) {
return sha3(x);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment