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;
|
||||
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 );
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,11 +23,21 @@ namespace fc { namespace equihash {
|
|||
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 );
|
||||
if( test_canonical_order && !test.CheckIndexesCanon() )
|
||||
return false;
|
||||
if( test_intermediate_zeros )
|
||||
return test.FullTest();
|
||||
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 )
|
||||
|
|
|
|||
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>()) {};
|
||||
|
||||
bool Test();
|
||||
bool FullTest()const;
|
||||
bool CheckIndexesCanon()const;
|
||||
Proof CanonizeIndexes()const;
|
||||
};
|
||||
|
||||
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 <algorithm>
|
||||
|
||||
|
||||
static uint64_t rdtsc(void) {
|
||||
#ifdef _MSC_VER
|
||||
return __rdtsc();
|
||||
|
|
@ -158,7 +157,9 @@ Proof Equihash::FindProof(){
|
|||
dup = true;
|
||||
}
|
||||
if (!dup)
|
||||
return solutions[i];
|
||||
{
|
||||
return solutions[i].CanonizeIndexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Proof(n, k, seed, nonce, std::vector<uint32_t>());
|
||||
|
|
@ -188,12 +189,51 @@ Proof Equihash::FindProof( Nonce _nonce )
|
|||
dup = true;
|
||||
}
|
||||
if (!dup)
|
||||
return solutions[i];
|
||||
{
|
||||
return solutions[i].CanonizeIndexes();
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
uint32_t input[SEED_LENGTH + 2];
|
||||
|
|
@ -218,3 +258,86 @@ bool Proof::Test()
|
|||
|
||||
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