Implement test_canonical_order and test_intermediate_zeros for equihash
This commit is contained in:
parent
d7276e2d15
commit
fe8710a7aa
4 changed files with 142 additions and 5 deletions
|
|
@ -11,7 +11,8 @@ namespace fc { namespace equihash {
|
||||||
sha256 seed;
|
sha256 seed;
|
||||||
std::vector< uint32_t > inputs;
|
std::vector< uint32_t > inputs;
|
||||||
|
|
||||||
bool is_valid() const;
|
bool is_valid( bool test_canonical_order = false, bool test_intermediate_zeros = false ) const;
|
||||||
|
void canonize_indexes();
|
||||||
|
|
||||||
static proof hash( uint32_t n, uint32_t k, sha256 seed );
|
static proof hash( uint32_t n, uint32_t k, sha256 seed );
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,21 @@ namespace fc { namespace equihash {
|
||||||
return new_seed;
|
return new_seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool proof::is_valid() const
|
bool proof::is_valid( bool test_canonical_order, bool test_intermediate_zeros ) const
|
||||||
{
|
{
|
||||||
_POW::Proof test( n, k, sha_to_seed( seed ), EQUIHASH_NONCE, inputs );
|
_POW::Proof test( n, k, sha_to_seed( seed ), EQUIHASH_NONCE, inputs );
|
||||||
|
if( test_canonical_order && !test.CheckIndexesCanon() )
|
||||||
|
return false;
|
||||||
|
if( test_intermediate_zeros )
|
||||||
|
return test.FullTest();
|
||||||
return test.Test();
|
return test.Test();
|
||||||
|
}
|
||||||
|
|
||||||
|
void proof::canonize_indexes()
|
||||||
|
{
|
||||||
|
_POW::Proof p( n, k, sha_to_seed( seed ), EQUIHASH_NONCE, inputs );
|
||||||
|
_POW::Proof p_canon = p.CanonizeIndexes();
|
||||||
|
inputs = p_canon.inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
proof proof::hash( uint32_t n, uint32_t k, sha256 seed )
|
proof proof::hash( uint32_t n, uint32_t k, sha256 seed )
|
||||||
|
|
|
||||||
3
vendor/equihash/include/equihash/pow.hpp
vendored
3
vendor/equihash/include/equihash/pow.hpp
vendored
|
|
@ -64,6 +64,9 @@ namespace _POW{
|
||||||
Proof():n(0),k(1),seed(0),nonce(0),inputs(std::vector<Input>()) {};
|
Proof():n(0),k(1),seed(0),nonce(0),inputs(std::vector<Input>()) {};
|
||||||
|
|
||||||
bool Test();
|
bool Test();
|
||||||
|
bool FullTest()const;
|
||||||
|
bool CheckIndexesCanon()const;
|
||||||
|
Proof CanonizeIndexes()const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Tuple {
|
class Tuple {
|
||||||
|
|
|
||||||
129
vendor/equihash/src/pow.cpp
vendored
129
vendor/equihash/src/pow.cpp
vendored
|
|
@ -8,7 +8,6 @@ Modifications by Steemit, Inc. 2016
|
||||||
#include <equihash/blake2.h>
|
#include <equihash/blake2.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
static uint64_t rdtsc(void) {
|
static uint64_t rdtsc(void) {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return __rdtsc();
|
return __rdtsc();
|
||||||
|
|
@ -158,7 +157,9 @@ Proof Equihash::FindProof(){
|
||||||
dup = true;
|
dup = true;
|
||||||
}
|
}
|
||||||
if (!dup)
|
if (!dup)
|
||||||
return solutions[i];
|
{
|
||||||
|
return solutions[i].CanonizeIndexes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Proof(n, k, seed, nonce, std::vector<uint32_t>());
|
return Proof(n, k, seed, nonce, std::vector<uint32_t>());
|
||||||
|
|
@ -188,12 +189,51 @@ Proof Equihash::FindProof( Nonce _nonce )
|
||||||
dup = true;
|
dup = true;
|
||||||
}
|
}
|
||||||
if (!dup)
|
if (!dup)
|
||||||
return solutions[i];
|
{
|
||||||
|
return solutions[i].CanonizeIndexes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Proof(n, k, seed, nonce, std::vector<uint32_t>());
|
return Proof(n, k, seed, nonce, std::vector<uint32_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Proof Proof::CanonizeIndexes()const
|
||||||
|
{
|
||||||
|
std::vector< uint32_t > new_inputs = inputs;
|
||||||
|
|
||||||
|
size_t step = 1;
|
||||||
|
while( step < new_inputs.size() )
|
||||||
|
{
|
||||||
|
for( size_t i=0; i<new_inputs.size(); i+=step+step )
|
||||||
|
{
|
||||||
|
auto ita = new_inputs.begin()+i, itb = ita+step;
|
||||||
|
if( (*ita) >= (*itb) )
|
||||||
|
{
|
||||||
|
std::swap_ranges( ita, itb, itb );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step += step;
|
||||||
|
}
|
||||||
|
return Proof(n, k, seed, nonce, new_inputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Proof::CheckIndexesCanon()const
|
||||||
|
{
|
||||||
|
bool was_ok = true;
|
||||||
|
size_t step = 1;
|
||||||
|
while( step < inputs.size() )
|
||||||
|
{
|
||||||
|
for( size_t i=0; i<inputs.size(); i+=step+step )
|
||||||
|
{
|
||||||
|
auto ita = inputs.begin()+i, itb = ita+step;
|
||||||
|
if( (*ita) >= (*itb) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
step += step;
|
||||||
|
}
|
||||||
|
return was_ok;
|
||||||
|
}
|
||||||
|
|
||||||
bool Proof::Test()
|
bool Proof::Test()
|
||||||
{
|
{
|
||||||
uint32_t input[SEED_LENGTH + 2];
|
uint32_t input[SEED_LENGTH + 2];
|
||||||
|
|
@ -218,3 +258,86 @@ bool Proof::Test()
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Proof::FullTest()const
|
||||||
|
{
|
||||||
|
// Length must be 2**k
|
||||||
|
if( inputs.size() != size_t(1 << k) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ensure all values are distinct
|
||||||
|
std::vector<Input> sorted_inputs = inputs;
|
||||||
|
std::sort( sorted_inputs.begin(), sorted_inputs.end() );
|
||||||
|
for( size_t i=1; i<inputs.size(); i++ )
|
||||||
|
{
|
||||||
|
if( sorted_inputs[i-1] >= sorted_inputs[i] )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all values are canonically indexed
|
||||||
|
/*
|
||||||
|
if( !CheckIndexesCanon() )
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Initialize blocks array
|
||||||
|
uint32_t input[SEED_LENGTH + 2];
|
||||||
|
for( size_t i=0; i<SEED_LENGTH; i++ )
|
||||||
|
input[i] = seed[i];
|
||||||
|
input[SEED_LENGTH] = nonce;
|
||||||
|
input[SEED_LENGTH + 1] = 0;
|
||||||
|
uint32_t buf[MAX_N / 4];
|
||||||
|
|
||||||
|
std::vector< std::vector< uint32_t > > blocks;
|
||||||
|
|
||||||
|
const uint32_t max_input = uint32_t(1) << (n / (k + 1) + 1);
|
||||||
|
|
||||||
|
for( size_t i=0; i<inputs.size(); i++ )
|
||||||
|
{
|
||||||
|
input[SEED_LENGTH + 1] = inputs[i];
|
||||||
|
if( inputs[i] >= max_input )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
blake2b((uint8_t*)buf, &input, NULL, sizeof(buf), sizeof(input), 0);
|
||||||
|
blocks.emplace_back();
|
||||||
|
std::vector<uint32_t>& x = blocks.back();
|
||||||
|
x.resize(k+1);
|
||||||
|
for( size_t j=0; j<(k+1); j++ )
|
||||||
|
{
|
||||||
|
//select j-th block of n/(k+1) bits
|
||||||
|
x[j] = buf[j] >> (32 - n / (k + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
std::cout << "\n\nBegin loop iteration\n";
|
||||||
|
for( const std::vector< uint32_t >& x : blocks )
|
||||||
|
{
|
||||||
|
for( const uint32_t& e : x )
|
||||||
|
std::cout << std::hex << std::setw(5) << e << " ";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t count = blocks.size();
|
||||||
|
if( count == 0 )
|
||||||
|
return false;
|
||||||
|
if( count == 1 )
|
||||||
|
{
|
||||||
|
return (blocks[0].size() == 1) && (blocks[0][0] == 0);
|
||||||
|
}
|
||||||
|
if( (count&1) != 0 )
|
||||||
|
return false;
|
||||||
|
for( size_t i=0,new_i=0; i<count; i+=2,new_i++ )
|
||||||
|
{
|
||||||
|
if( blocks[i][0] != blocks[i+1][0] )
|
||||||
|
return false;
|
||||||
|
for( size_t j=1; j<blocks[i].size(); j++ )
|
||||||
|
blocks[new_i][j-1] = blocks[i][j] ^ blocks[i+1][j];
|
||||||
|
blocks[new_i].resize(blocks[new_i].size()-1);
|
||||||
|
}
|
||||||
|
blocks.resize(blocks.size() >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue