mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 05:03:43 +01:00
equix: API changes for new result codes and hashx compatibility
This change adapts Equi-X to the corresponding HashX API changes that added HASHX_TRY_COMPILE. The new regularized HashX return codes are reflected by revised corresponding Equi-X return codes. Both solve and verify operations now return an error/success code, and a new equix_solutions_buffer struct includes both the solution buffer and information about the solution count and hashx implementation. With this change, it's possible to discern between hash construction failures (invalid seed) and some external error like an mprotect() failure. Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
This commit is contained in:
parent
5a4f92ea7b
commit
a3513dea54
@ -30,16 +30,35 @@ typedef struct equix_solution {
|
||||
} equix_solution;
|
||||
|
||||
/*
|
||||
* Solution verification results
|
||||
* Extra informational flags returned by the solver
|
||||
*/
|
||||
typedef enum equix_solution_flags {
|
||||
EQUIX_SOLVER_DID_USE_COMPILER = (1 << 0),
|
||||
} equix_solution_flags;
|
||||
|
||||
/*
|
||||
* Fixed size buffer containing up to EQUIX_MAX_SOLS solutions.
|
||||
*/
|
||||
typedef struct equix_solutions_buffer {
|
||||
unsigned count;
|
||||
equix_solution_flags flags;
|
||||
equix_solution sols[EQUIX_MAX_SOLS];
|
||||
} equix_solutions_buffer;
|
||||
|
||||
/*
|
||||
* Result type for solve and verify operations
|
||||
*/
|
||||
typedef enum equix_result {
|
||||
EQUIX_OK, /* Solution is valid */
|
||||
EQUIX_CHALLENGE, /* The challenge is invalid (the internal hash
|
||||
EQUIX_FAIL_CHALLENGE, /* The challenge is invalid (the internal hash
|
||||
function doesn't pass validation). */
|
||||
EQUIX_ORDER, /* Indices are not in the correct order. */
|
||||
EQUIX_PARTIAL_SUM, /* The partial sums of the hash values don't
|
||||
EQUIX_FAIL_ORDER, /* Indices are not in the correct order. */
|
||||
EQUIX_FAIL_PARTIAL_SUM, /* The partial sums of the hash values don't
|
||||
have the required number of trailing zeroes. */
|
||||
EQUIX_FINAL_SUM /* The hash values don't sum to zero. */
|
||||
EQUIX_FAIL_FINAL_SUM, /* The hash values don't sum to zero. */
|
||||
EQUIX_FAIL_COMPILE, /* Can't compile, and no fallback is enabled */
|
||||
EQUIX_FAIL_NO_SOLVER, /* Solve requested on a context with no solver */
|
||||
EQUIX_FAIL_INTERNAL, /* Internal error (bug) */
|
||||
} equix_result;
|
||||
|
||||
/*
|
||||
@ -49,17 +68,15 @@ typedef struct equix_ctx equix_ctx;
|
||||
|
||||
/*
|
||||
* Flags for context creation
|
||||
*/
|
||||
*/
|
||||
typedef enum equix_ctx_flags {
|
||||
EQUIX_CTX_VERIFY = 0, /* Context for verification */
|
||||
EQUIX_CTX_SOLVE = 1, /* Context for solving */
|
||||
EQUIX_CTX_COMPILE = 2, /* Compile internal hash function */
|
||||
EQUIX_CTX_HUGEPAGES = 4, /* Allocate solver memory using HugePages */
|
||||
EQUIX_CTX_MUST_COMPILE = 2, /* Must compile internal hash function */
|
||||
EQUIX_CTX_TRY_COMPILE = 4, /* Compile if possible */
|
||||
EQUIX_CTX_HUGEPAGES = 8, /* Allocate solver memory using HugePages */
|
||||
} equix_ctx_flags;
|
||||
|
||||
/* Sentinel value used to indicate unsupported type */
|
||||
#define EQUIX_NOTSUPP ((equix_ctx*)-1)
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define EQUIX_WIN
|
||||
#endif
|
||||
@ -93,8 +110,7 @@ extern "C" {
|
||||
* @param flags is the type of context to be created
|
||||
*
|
||||
* @return pointer to a newly created context. Returns NULL on memory
|
||||
* allocation failure and EQUIX_NOTSUPP if the requested type
|
||||
* is not supported.
|
||||
* allocation failure.
|
||||
*/
|
||||
EQUIX_API equix_ctx* equix_alloc(equix_ctx_flags flags);
|
||||
|
||||
@ -114,13 +130,17 @@ EQUIX_API void equix_free(equix_ctx* ctx);
|
||||
* @param output pointer to the output array where solutions will be
|
||||
* stored
|
||||
*
|
||||
* @return the number of solutions found
|
||||
* @return On success, returns EQUIX_OK and sets output->count to the number
|
||||
* of solutions found, with the solutions themselves written to the
|
||||
* output buffer. If the challenge is unusable, returns
|
||||
* EQUIX_FAIL_CHALLENGE. If the EQUIX_CTX_MUST_COMPILE flag is in use
|
||||
* and the compiler fails, this can return EQUIX_FAIL_COMPILE.
|
||||
*/
|
||||
EQUIX_API int equix_solve(
|
||||
EQUIX_API equix_result equix_solve(
|
||||
equix_ctx* ctx,
|
||||
const void* challenge,
|
||||
size_t challenge_size,
|
||||
equix_solution output[EQUIX_MAX_SOLS]);
|
||||
equix_solutions_buffer *output);
|
||||
|
||||
/*
|
||||
* Verify an Equi-X solution.
|
||||
@ -130,8 +150,9 @@ EQUIX_API int equix_solve(
|
||||
* @param challenge_size size of the challenge
|
||||
* @param solution pointer to the solution to be verified
|
||||
*
|
||||
* @return verification result
|
||||
*/
|
||||
* @return Verification result. This can return EQUIX_OK or any of the
|
||||
* EQUIX_FAIL_* error codes.
|
||||
*/
|
||||
EQUIX_API equix_result equix_verify(
|
||||
equix_ctx* ctx,
|
||||
const void* challenge,
|
||||
|
@ -10,11 +10,6 @@
|
||||
#include <hashx_thread.h>
|
||||
#include <hashx_time.h>
|
||||
|
||||
typedef struct solver_output {
|
||||
equix_solution sols[EQUIX_MAX_SOLS];
|
||||
int count;
|
||||
} solver_output;
|
||||
|
||||
typedef struct worker_job {
|
||||
int id;
|
||||
hashx_thread thread;
|
||||
@ -23,17 +18,29 @@ typedef struct worker_job {
|
||||
int start;
|
||||
int step;
|
||||
int end;
|
||||
solver_output* output;
|
||||
equix_solutions_buffer* output;
|
||||
} worker_job;
|
||||
|
||||
static hashx_thread_retval worker(void* args) {
|
||||
worker_job* job = (worker_job*)args;
|
||||
job->total_sols = 0;
|
||||
solver_output* outptr = job->output;
|
||||
equix_solutions_buffer* outptr = job->output;
|
||||
for (int seed = job->start; seed < job->end; seed += job->step) {
|
||||
int count = equix_solve(job->ctx, &seed, sizeof(seed), outptr->sols);
|
||||
outptr->count = count;
|
||||
job->total_sols += count;
|
||||
equix_result result = equix_solve(job->ctx, &seed,
|
||||
sizeof(seed), outptr);
|
||||
if (result == EQUIX_OK) {
|
||||
job->total_sols += outptr->count;
|
||||
} else if (result == EQUIX_FAIL_CHALLENGE) {
|
||||
outptr->count = 0;
|
||||
} else if (result == EQUIX_FAIL_COMPILE) {
|
||||
printf("Error: not supported. Try with --interpret\n");
|
||||
exit(1);
|
||||
break;
|
||||
} else {
|
||||
printf("Error: unexpected solve failure (%d)\n", (int)result);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
outptr++;
|
||||
}
|
||||
return HASHX_THREAD_SUCCESS;
|
||||
@ -54,7 +61,10 @@ static const char* result_names[] = {
|
||||
"Invalid nonce",
|
||||
"Indices out of order",
|
||||
"Nonzero partial sum",
|
||||
"Nonzero final sum"
|
||||
"Nonzero final sum",
|
||||
"HashX compiler failed",
|
||||
"(Internal) Solver not allocated",
|
||||
"(Internal error)"
|
||||
};
|
||||
|
||||
static void print_help(char* executable) {
|
||||
@ -85,7 +95,7 @@ int main(int argc, char** argv) {
|
||||
read_int_option("--threads", argc, argv, &threads, 1);
|
||||
equix_ctx_flags flags = EQUIX_CTX_SOLVE;
|
||||
if (!interpret) {
|
||||
flags |= EQUIX_CTX_COMPILE;
|
||||
flags |= EQUIX_CTX_MUST_COMPILE;
|
||||
}
|
||||
if (huge_pages) {
|
||||
flags |= EQUIX_CTX_HUGEPAGES;
|
||||
@ -102,15 +112,11 @@ int main(int argc, char** argv) {
|
||||
printf("Error: memory allocation failure\n");
|
||||
return 1;
|
||||
}
|
||||
if (jobs[thd].ctx == EQUIX_NOTSUPP) {
|
||||
printf("Error: not supported. Try with --interpret\n");
|
||||
return 1;
|
||||
}
|
||||
jobs[thd].id = thd;
|
||||
jobs[thd].start = start + thd;
|
||||
jobs[thd].step = threads;
|
||||
jobs[thd].end = start + nonces;
|
||||
jobs[thd].output = malloc(sizeof(solver_output) * per_thread);
|
||||
jobs[thd].output = malloc(sizeof(equix_solutions_buffer) * per_thread);
|
||||
if (jobs[thd].output == NULL) {
|
||||
printf("Error: memory allocation failure\n");
|
||||
return 1;
|
||||
@ -141,7 +147,7 @@ int main(int argc, char** argv) {
|
||||
if (print_sols) {
|
||||
for (int thd = 0; thd < threads; ++thd) {
|
||||
worker_job* job = &jobs[thd];
|
||||
solver_output* outptr = job->output;
|
||||
equix_solutions_buffer* outptr = job->output;
|
||||
for (int seed = job->start; seed < job->end; seed += job->step) {
|
||||
for (int sol = 0; sol < outptr->count; ++sol) {
|
||||
print_solution(seed, &outptr->sols[sol]);
|
||||
@ -153,7 +159,7 @@ int main(int argc, char** argv) {
|
||||
time_start = hashx_time();
|
||||
for (int thd = 0; thd < threads; ++thd) {
|
||||
worker_job* job = &jobs[thd];
|
||||
solver_output* outptr = job->output;
|
||||
equix_solutions_buffer* outptr = job->output;
|
||||
for (int seed = job->start; seed < job->end; seed += job->step) {
|
||||
for (int sol = 0; sol < outptr->count; ++sol) {
|
||||
equix_result result = equix_verify(job->ctx, &seed, sizeof(seed), &outptr->sols[sol]);
|
||||
|
@ -8,21 +8,23 @@
|
||||
#include "solver_heap.h"
|
||||
|
||||
equix_ctx* equix_alloc(equix_ctx_flags flags) {
|
||||
equix_ctx* ctx_failure = NULL;
|
||||
equix_ctx* ctx = malloc(sizeof(equix_ctx));
|
||||
if (ctx == NULL) {
|
||||
goto failure;
|
||||
}
|
||||
ctx->flags = flags & EQUIX_CTX_COMPILE;
|
||||
ctx->hash_func = hashx_alloc(flags & EQUIX_CTX_COMPILE ?
|
||||
HASHX_COMPILED : HASHX_INTERPRETED);
|
||||
ctx->flags = (equix_ctx_flags)0;
|
||||
|
||||
if (flags & EQUIX_CTX_MUST_COMPILE) {
|
||||
ctx->hash_func = hashx_alloc(HASHX_TYPE_COMPILED);
|
||||
} else if (flags & EQUIX_CTX_TRY_COMPILE) {
|
||||
ctx->hash_func = hashx_alloc(HASHX_TRY_COMPILE);
|
||||
} else {
|
||||
ctx->hash_func = hashx_alloc(HASHX_TYPE_INTERPRETED);
|
||||
}
|
||||
if (ctx->hash_func == NULL) {
|
||||
goto failure;
|
||||
}
|
||||
if (ctx->hash_func == HASHX_NOTSUPP) {
|
||||
ctx_failure = EQUIX_NOTSUPP;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (flags & EQUIX_CTX_SOLVE) {
|
||||
if (flags & EQUIX_CTX_HUGEPAGES) {
|
||||
ctx->heap = hashx_vm_alloc_huge(sizeof(solver_heap));
|
||||
@ -33,16 +35,19 @@ equix_ctx* equix_alloc(equix_ctx_flags flags) {
|
||||
if (ctx->heap == NULL) {
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
ctx->heap = NULL;
|
||||
}
|
||||
|
||||
ctx->flags = flags;
|
||||
return ctx;
|
||||
failure:
|
||||
equix_free(ctx);
|
||||
return ctx_failure;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void equix_free(equix_ctx* ctx) {
|
||||
if (ctx != NULL && ctx != EQUIX_NOTSUPP) {
|
||||
if (ctx != NULL) {
|
||||
if (ctx->flags & EQUIX_CTX_SOLVE) {
|
||||
if (ctx->flags & EQUIX_CTX_HUGEPAGES) {
|
||||
hashx_vm_free(ctx->heap, sizeof(solver_heap));
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <equix.h>
|
||||
#include <hashx.h>
|
||||
@ -25,61 +26,89 @@ static bool verify_order(const equix_solution* solution) {
|
||||
static uint64_t sum_pair(hashx_ctx* hash_func, equix_idx left, equix_idx right) {
|
||||
uint8_t hash_left[HASHX_SIZE];
|
||||
uint8_t hash_right[HASHX_SIZE];
|
||||
hashx_exec(hash_func, left, hash_left);
|
||||
hashx_exec(hash_func, right, hash_right);
|
||||
hashx_result r_left = hashx_exec(hash_func, left, hash_left);
|
||||
hashx_result r_right = hashx_exec(hash_func, right, hash_right);
|
||||
assert(r_left == HASHX_OK && r_right == HASHX_OK);
|
||||
return load64(hash_left) + load64(hash_right);
|
||||
}
|
||||
|
||||
static equix_result verify_internal(hashx_ctx* hash_func, const equix_solution* solution) {
|
||||
uint64_t pair0 = sum_pair(hash_func, solution->idx[0], solution->idx[1]);
|
||||
if (pair0 & EQUIX_STAGE1_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair1 = sum_pair(hash_func, solution->idx[2], solution->idx[3]);
|
||||
if (pair1 & EQUIX_STAGE1_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair4 = pair0 + pair1;
|
||||
if (pair4 & EQUIX_STAGE2_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair2 = sum_pair(hash_func, solution->idx[4], solution->idx[5]);
|
||||
if (pair2 & EQUIX_STAGE1_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair3 = sum_pair(hash_func, solution->idx[6], solution->idx[7]);
|
||||
if (pair3 & EQUIX_STAGE1_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair5 = pair2 + pair3;
|
||||
if (pair5 & EQUIX_STAGE2_MASK) {
|
||||
return EQUIX_PARTIAL_SUM;
|
||||
return EQUIX_FAIL_PARTIAL_SUM;
|
||||
}
|
||||
uint64_t pair6 = pair4 + pair5;
|
||||
if (pair6 & EQUIX_FULL_MASK) {
|
||||
return EQUIX_FINAL_SUM;
|
||||
return EQUIX_FAIL_FINAL_SUM;
|
||||
}
|
||||
return EQUIX_OK;
|
||||
}
|
||||
|
||||
int equix_solve(
|
||||
static equix_result equix_hashx_make(
|
||||
equix_ctx* ctx,
|
||||
const void* challenge,
|
||||
size_t challenge_size)
|
||||
{
|
||||
switch (hashx_make(ctx->hash_func, challenge, challenge_size)) {
|
||||
case HASHX_OK:
|
||||
return EQUIX_OK;
|
||||
case HASHX_FAIL_SEED:
|
||||
return EQUIX_FAIL_CHALLENGE;
|
||||
case HASHX_FAIL_COMPILE:
|
||||
return EQUIX_FAIL_COMPILE;
|
||||
case HASHX_FAIL_UNDEFINED:
|
||||
case HASHX_FAIL_UNPREPARED:
|
||||
default:
|
||||
return EQUIX_FAIL_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
equix_result equix_solve(
|
||||
equix_ctx* ctx,
|
||||
const void* challenge,
|
||||
size_t challenge_size,
|
||||
equix_solution output[EQUIX_MAX_SOLS])
|
||||
equix_solutions_buffer *output)
|
||||
{
|
||||
if ((ctx->flags & EQUIX_CTX_SOLVE) == 0) {
|
||||
return 0;
|
||||
return EQUIX_FAIL_NO_SOLVER;
|
||||
}
|
||||
|
||||
if (!hashx_make(ctx->hash_func, challenge, challenge_size)) {
|
||||
return 0;
|
||||
equix_result result = equix_hashx_make(ctx, challenge, challenge_size);
|
||||
if (result != EQUIX_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return equix_solver_solve(ctx->hash_func, ctx->heap, output);
|
||||
output->flags = 0;
|
||||
hashx_type func_type;
|
||||
if (hashx_query_type(ctx->hash_func, &func_type) == HASHX_OK &&
|
||||
func_type == HASHX_TYPE_COMPILED) {
|
||||
output->flags |= EQUIX_SOLVER_DID_USE_COMPILER;
|
||||
}
|
||||
|
||||
output->count = equix_solver_solve(ctx->hash_func, ctx->heap, output->sols);
|
||||
return EQUIX_OK;
|
||||
}
|
||||
|
||||
|
||||
equix_result equix_verify(
|
||||
equix_ctx* ctx,
|
||||
const void* challenge,
|
||||
@ -87,10 +116,13 @@ equix_result equix_verify(
|
||||
const equix_solution* solution)
|
||||
{
|
||||
if (!verify_order(solution)) {
|
||||
return EQUIX_ORDER;
|
||||
return EQUIX_FAIL_ORDER;
|
||||
}
|
||||
if (!hashx_make(ctx->hash_func, challenge, challenge_size)) {
|
||||
return EQUIX_CHALLENGE;
|
||||
|
||||
equix_result result = equix_hashx_make(ctx, challenge, challenge_size);
|
||||
if (result != EQUIX_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return verify_internal(ctx->hash_func, solution);
|
||||
}
|
||||
|
@ -49,7 +49,8 @@ typedef stage3_idx_item s3_idx;
|
||||
|
||||
static FORCE_INLINE uint64_t hash_value(hashx_ctx* hash_func, equix_idx index) {
|
||||
char hash[HASHX_SIZE];
|
||||
hashx_exec(hash_func, index, hash);
|
||||
hashx_result result = hashx_exec(hash_func, index, hash);
|
||||
assert(result == HASHX_OK);
|
||||
return load64(hash);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
typedef bool test_func();
|
||||
|
||||
static equix_ctx* ctx = NULL;
|
||||
static equix_solution solution[EQUIX_MAX_SOLS];
|
||||
static equix_solutions_buffer output;
|
||||
static int nonce;
|
||||
static int valid_count = 0;
|
||||
static int test_no = 0;
|
||||
@ -26,8 +26,8 @@ static int test_no = 0;
|
||||
} while(0)
|
||||
|
||||
static bool test_alloc() {
|
||||
ctx = equix_alloc(EQUIX_CTX_SOLVE);
|
||||
assert(ctx != NULL && ctx != EQUIX_NOTSUPP);
|
||||
ctx = equix_alloc(EQUIX_CTX_SOLVE | EQUIX_CTX_TRY_COMPILE);
|
||||
assert(ctx != NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -37,60 +37,65 @@ static bool test_free() {
|
||||
}
|
||||
|
||||
static bool test_solve() {
|
||||
int num_solutions = 0;
|
||||
for (nonce = 0; num_solutions == 0 && nonce < 20; ++nonce) {
|
||||
num_solutions = equix_solve(ctx, &nonce, sizeof(nonce), solution);
|
||||
output.count = 0;
|
||||
for (nonce = 0; output.count == 0 && nonce < 20; ++nonce) {
|
||||
equix_result result = equix_solve(ctx, &nonce, sizeof(nonce), &output);
|
||||
assert(result == EQUIX_OK);
|
||||
}
|
||||
--nonce;
|
||||
assert(num_solutions > 0);
|
||||
assert(output.count > 0);
|
||||
assert(output.flags == EQUIX_SOLVER_DID_USE_COMPILER || output.flags == 0);
|
||||
printf("(using %s HashX) ",
|
||||
(EQUIX_SOLVER_DID_USE_COMPILER & output.flags)
|
||||
? "compiled" : "interpreted");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_verify1() {
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &solution[0]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &output.sols[0]);
|
||||
assert(result == EQUIX_OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_verify2() {
|
||||
SWAP_IDX(solution[0].idx[0], solution[0].idx[1]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &solution[0]);
|
||||
assert(result == EQUIX_ORDER);
|
||||
SWAP_IDX(output.sols[0].idx[0], output.sols[0].idx[1]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &output.sols[0]);
|
||||
assert(result == EQUIX_FAIL_ORDER);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_verify3() {
|
||||
SWAP_IDX(solution[0].idx[0], solution[0].idx[4]);
|
||||
SWAP_IDX(solution[0].idx[1], solution[0].idx[5]);
|
||||
SWAP_IDX(solution[0].idx[2], solution[0].idx[6]);
|
||||
SWAP_IDX(solution[0].idx[3], solution[0].idx[7]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &solution[0]);
|
||||
assert(result == EQUIX_ORDER);
|
||||
SWAP_IDX(solution[0].idx[0], solution[0].idx[4]);
|
||||
SWAP_IDX(solution[0].idx[1], solution[0].idx[5]);
|
||||
SWAP_IDX(solution[0].idx[2], solution[0].idx[6]);
|
||||
SWAP_IDX(solution[0].idx[3], solution[0].idx[7]);
|
||||
SWAP_IDX(output.sols[0].idx[0], output.sols[0].idx[4]);
|
||||
SWAP_IDX(output.sols[0].idx[1], output.sols[0].idx[5]);
|
||||
SWAP_IDX(output.sols[0].idx[2], output.sols[0].idx[6]);
|
||||
SWAP_IDX(output.sols[0].idx[3], output.sols[0].idx[7]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &output.sols[0]);
|
||||
assert(result == EQUIX_FAIL_ORDER);
|
||||
SWAP_IDX(output.sols[0].idx[0], output.sols[0].idx[4]);
|
||||
SWAP_IDX(output.sols[0].idx[1], output.sols[0].idx[5]);
|
||||
SWAP_IDX(output.sols[0].idx[2], output.sols[0].idx[6]);
|
||||
SWAP_IDX(output.sols[0].idx[3], output.sols[0].idx[7]);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_verify4() {
|
||||
SWAP_IDX(solution[0].idx[1], solution[0].idx[2]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &solution[0]);
|
||||
assert(result == EQUIX_PARTIAL_SUM);
|
||||
SWAP_IDX(solution[0].idx[1], solution[0].idx[2]);
|
||||
SWAP_IDX(output.sols[0].idx[1], output.sols[0].idx[2]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &output.sols[0]);
|
||||
assert(result == EQUIX_FAIL_PARTIAL_SUM);
|
||||
SWAP_IDX(output.sols[0].idx[1], output.sols[0].idx[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void permute_idx(int start) {
|
||||
if (start == EQUIX_NUM_IDX - 1) {
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &solution[0]);
|
||||
equix_result result = equix_verify(ctx, &nonce, sizeof(nonce), &output.sols[0]);
|
||||
valid_count += result == EQUIX_OK;
|
||||
}
|
||||
else {
|
||||
for (int i = start; i < EQUIX_NUM_IDX; ++i) {
|
||||
SWAP_IDX(solution[0].idx[start], solution[0].idx[i]);
|
||||
SWAP_IDX(output.sols[0].idx[start], output.sols[0].idx[i]);
|
||||
permute_idx(start + 1);
|
||||
SWAP_IDX(solution[0].idx[start], solution[0].idx[i]);
|
||||
SWAP_IDX(output.sols[0].idx[start], output.sols[0].idx[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user