Auto merge of #1260 - str4d:1175-byte-array-manipulation, r=ebfull
Update Equihash implementation to match the Zcash spec Closes #1175
This commit is contained in:
@@ -2,6 +2,69 @@
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "crypto/equihash.h"
|
||||
#include "uint256.h"
|
||||
|
||||
void TestExpandAndCompress(const std::string &scope, size_t bit_len, size_t byte_pad,
|
||||
std::vector<unsigned char> compact,
|
||||
std::vector<unsigned char> expanded)
|
||||
{
|
||||
SCOPED_TRACE(scope);
|
||||
|
||||
std::vector<unsigned char> out(expanded.size());
|
||||
ExpandArray(compact.data(), compact.size(),
|
||||
out.data(), out.size(), bit_len, byte_pad);
|
||||
EXPECT_EQ(expanded, out);
|
||||
|
||||
out.resize(compact.size());
|
||||
CompressArray(expanded.data(), expanded.size(),
|
||||
out.data(), out.size(), bit_len, byte_pad);
|
||||
EXPECT_EQ(compact, out);
|
||||
}
|
||||
|
||||
TEST(equihash_tests, expand_and_contract_arrays) {
|
||||
TestExpandAndCompress("8 11-bit chunks, all-ones", 11, 0,
|
||||
ParseHex("ffffffffffffffffffffff"),
|
||||
ParseHex("07ff07ff07ff07ff07ff07ff07ff07ff"));
|
||||
TestExpandAndCompress("8 21-bit chunks, alternating 1s and 0s", 21, 0,
|
||||
ParseHex("aaaaad55556aaaab55555aaaaad55556aaaab55555"),
|
||||
ParseHex("155555155555155555155555155555155555155555155555"));
|
||||
TestExpandAndCompress("8 21-bit chunks, based on example in the spec", 21, 0,
|
||||
ParseHex("000220000a7ffffe00123022b38226ac19bdf23456"),
|
||||
ParseHex("0000440000291fffff0001230045670089ab00cdef123456"));
|
||||
TestExpandAndCompress("16 14-bit chunks, alternating 11s and 00s", 14, 0,
|
||||
ParseHex("cccf333cccf333cccf333cccf333cccf333cccf333cccf333cccf333"),
|
||||
ParseHex("3333333333333333333333333333333333333333333333333333333333333333"));
|
||||
|
||||
TestExpandAndCompress("8 11-bit chunks, all-ones, 2-byte padding", 11, 2,
|
||||
ParseHex("ffffffffffffffffffffff"),
|
||||
ParseHex("000007ff000007ff000007ff000007ff000007ff000007ff000007ff000007ff"));
|
||||
}
|
||||
|
||||
void TestMinimalSolnRepr(const std::string &scope, size_t cBitLen,
|
||||
std::vector<eh_index> indices,
|
||||
std::vector<unsigned char> minimal)
|
||||
{
|
||||
SCOPED_TRACE(scope);
|
||||
|
||||
EXPECT_EQ(indices, GetIndicesFromMinimal(minimal, cBitLen));
|
||||
EXPECT_EQ(minimal, GetMinimalFromIndices(indices, cBitLen));
|
||||
}
|
||||
|
||||
TEST(equihash_tests, minimal_solution_representation) {
|
||||
TestMinimalSolnRepr("Test 1", 20,
|
||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||
ParseHex("000008000040000200001000008000040000200001"));
|
||||
TestMinimalSolnRepr("Test 2", 20,
|
||||
{2097151, 2097151, 2097151, 2097151,
|
||||
2097151, 2097151, 2097151, 2097151},
|
||||
ParseHex("ffffffffffffffffffffffffffffffffffffffffff"));
|
||||
TestMinimalSolnRepr("Test 3", 20,
|
||||
{131071, 128, 131071, 128, 131071, 128, 131071, 128},
|
||||
ParseHex("0ffff8002003fffe000800ffff8002003fffe00080"));
|
||||
TestMinimalSolnRepr("Test 4", 20,
|
||||
{68, 41, 2097151, 1233, 665, 1023, 1, 1048575},
|
||||
ParseHex("000220000a7ffffe004d10014c800ffc00002fffff"));
|
||||
}
|
||||
|
||||
TEST(equihash_tests, is_probably_duplicate) {
|
||||
std::shared_ptr<eh_trunc> p1 (new eh_trunc[4] {0, 1, 2, 3}, std::default_delete<eh_trunc[]>());
|
||||
@@ -17,9 +80,11 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
Equihash<48,5> Eh48_5;
|
||||
crypto_generichash_blake2b_state state;
|
||||
Eh48_5.InitialiseState(state);
|
||||
uint256 V = uint256S("0x00");
|
||||
crypto_generichash_blake2b_update(&state, V.begin(), V.size());
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return false;
|
||||
@@ -27,7 +92,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListGeneration;
|
||||
@@ -35,7 +100,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListSorting;
|
||||
@@ -43,7 +108,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListColliding;
|
||||
@@ -51,7 +116,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == RoundEnd;
|
||||
@@ -59,7 +124,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == FinalSorting;
|
||||
@@ -67,7 +132,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == FinalColliding;
|
||||
@@ -75,7 +140,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialGeneration;
|
||||
@@ -83,7 +148,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialSorting;
|
||||
@@ -91,7 +156,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialSubtreeEnd;
|
||||
@@ -99,7 +164,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialIndexEnd;
|
||||
@@ -107,7 +172,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialEnd;
|
||||
@@ -119,9 +184,11 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
Equihash<48,5> Eh48_5;
|
||||
crypto_generichash_blake2b_state state;
|
||||
Eh48_5.InitialiseState(state);
|
||||
uint256 V = uint256S("0x00");
|
||||
crypto_generichash_blake2b_update(&state, V.begin(), V.size());
|
||||
|
||||
{
|
||||
ASSERT_NO_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_NO_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return false;
|
||||
@@ -129,7 +196,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListGeneration;
|
||||
@@ -137,7 +204,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListSorting;
|
||||
@@ -145,7 +212,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == ListColliding;
|
||||
@@ -153,7 +220,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == RoundEnd;
|
||||
@@ -161,7 +228,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == FinalSorting;
|
||||
@@ -169,7 +236,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == FinalColliding;
|
||||
@@ -177,7 +244,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialGeneration;
|
||||
@@ -185,7 +252,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialSorting;
|
||||
@@ -193,7 +260,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialSubtreeEnd;
|
||||
@@ -201,7 +268,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialIndexEnd;
|
||||
@@ -209,7 +276,7 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<eh_index> soln) {
|
||||
ASSERT_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {
|
||||
return false;
|
||||
}, [](EhSolverCancelCheck pos) {
|
||||
return pos == PartialEnd;
|
||||
|
||||
Reference in New Issue
Block a user