This is an automated email from the git hooks/post-receive script.
dgoulet pushed a commit to branch main in repository tor.
commit 903c6cf1ab5ba115bbfd33385e0acd5f88ad2ba3 Author: Micah Elizabeth Scott beth@torproject.org AuthorDate: Fri Mar 31 13:36:58 2023 -0700
hs_pow: client side effort adjustment
The goal of this patch is to add an additional mechanism for adjusting PoW effort upwards, where clients rather than services can choose to solve their puzzles at a higher effort than what was suggested in the descriptor.
I wanted to use hs_cache's existing unreachability stats to drive this effort bump, but this revealed some cases where a circuit (intro or rend) closed early on can end up in hs_cache with an all zero intro point key, where nobody will find it. This moves intro_auth_pk initialization earlier in a couple places and adds nonfatal asserts to catch the problem if it shows up elsewhere.
The actual effort adjustment method I chose is to multiply the suggested effort by (1 + unresponsive_count), then ensure the result is at least 1. If a service has suggested effort of 0 but we fail to connect, retries will all use an effort of 1. If the suggestion was 50, we'll try 50, 100, 150, 200, etc. This is bounded both by our client effort limit and by the limit on unresponsive_count (currently 5).
Signed-off-by: Micah Elizabeth Scott beth@torproject.org --- src/core/or/circuituse.c | 23 +++++--- src/feature/hs/hs_cache.c | 2 + src/feature/hs/hs_circuit.c | 1 + src/feature/hs/hs_client.c | 130 ++++++++++++++++++++++++++++---------------- src/feature/hs/hs_client.h | 2 + src/feature/hs/hs_pow.c | 27 ++++----- src/feature/hs/hs_pow.h | 23 ++++++-- src/test/test_hs_client.c | 2 + src/test/test_hs_pow_slow.c | 15 +++-- 9 files changed, 142 insertions(+), 83 deletions(-)
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index b78f72e835..ac9005e1d4 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -564,14 +564,6 @@ circuit_expire_building(void) continue; }
- /* Ignore circuits that are waiting for an introduction to a service with - * PoW enabled, it can take an arbitrary amount of time. They will get - * cleaned up if the SOCKS connection is closed. */ - if (TO_ORIGIN_CIRCUIT(victim)->hs_with_pow_circ && - victim->purpose == CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) { - continue; - } - build_state = TO_ORIGIN_CIRCUIT(victim)->build_state; if (build_state && build_state->onehop_tunnel) cutoff = begindir_cutoff; @@ -2560,6 +2552,11 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, circ->hs_ident = hs_ident_circuit_new(&edge_conn->hs_ident->identity_pk); } + if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { + if (hs_client_setup_intro_circ_auth_key(circ) < 0) { + return 0; + } + } if (circ->base_.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND && circ->base_.state == CIRCUIT_STATE_OPEN) circuit_has_opened(circ); @@ -3012,6 +3009,16 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) conn, CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT, &introcirc); if (retval < 0) return -1; /* failed */
+ if (rendcirc && introcirc) { + /* Let's fill out the hs_ident fully as soon as possible, so that + * unreachability counts can be updated properly even if circuits close + * early. */ + tor_assert_nonfatal(!ed25519_public_key_is_zero( + &introcirc->hs_ident->intro_auth_pk)); + ed25519_pubkey_copy(&rendcirc->hs_ident->intro_auth_pk, + &introcirc->hs_ident->intro_auth_pk); + } + if (retval > 0) { /* one has already sent the intro. keep waiting. */ tor_assert(introcirc); diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c index dcca1d7086..0cc7dfd031 100644 --- a/src/feature/hs/hs_cache.c +++ b/src/feature/hs/hs_cache.c @@ -581,6 +581,8 @@ cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk,
tor_assert(service_pk); tor_assert(auth_key); + tor_assert_nonfatal(!ed25519_public_key_is_zero(service_pk)); + tor_assert_nonfatal(!ed25519_public_key_is_zero(auth_key));
/* Lookup the intro state cache for this service key. */ cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey); diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index 92217d760a..d5188b514f 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -251,6 +251,7 @@ create_intro_circuit_identifier(const hs_service_t *service,
ident = hs_ident_circuit_new(&service->keys.identity_pk); ed25519_pubkey_copy(&ident->intro_auth_pk, &ip->auth_key_kp.pubkey); + tor_assert_nonfatal(!ed25519_public_key_is_zero(&ident->intro_auth_pk));
return ident; } diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 2a620da953..6303b8fe75 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -549,6 +549,7 @@ find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
tor_assert(ident); tor_assert(desc); + tor_assert_nonfatal(!ed25519_public_key_is_zero(&ident->intro_auth_pk));
SMARTLIST_FOREACH_BEGIN(desc->encrypted_data.intro_points, const hs_desc_intro_point_t *, ip) { @@ -634,15 +635,8 @@ send_introduce1(origin_circuit_t *intro_circ, return -1; /* transient failure */ }
- /* Cell has been sent successfully. Copy the introduction point - * authentication and encryption key in the rendezvous circuit identifier so - * we can compute the ntor keys when we receive the RENDEZVOUS2 cell. */ - memcpy(&rend_circ->hs_ident->intro_enc_pk, &ip->enc_key, - sizeof(rend_circ->hs_ident->intro_enc_pk)); - ed25519_pubkey_copy(&rend_circ->hs_ident->intro_auth_pk, - &intro_circ->hs_ident->intro_auth_pk); - - /* Now, we wait for an ACK or NAK on this circuit. */ + /* Cell has been sent successfully. + * Now, we wait for an ACK or NAK on this circuit. */ circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT); /* Set timestamp_dirty, because circuit_expire_building expects it to @@ -657,6 +651,17 @@ send_introduce1(origin_circuit_t *intro_circ, * tackle. If asked for higher, we solve it at this cap. */ #define CLIENT_MAX_POW_EFFORT 10000
+/** Set a client-side minimum effort. If the client is choosing to increase + * effort on retry, it will always pick a value >= this lower limit. */ +#define CLIENT_MIN_RETRY_POW_EFFORT 8 + +/** Client effort will double on every retry until this level is hit */ +#define CLIENT_POW_EFFORT_DOUBLE_UNTIL 1000 + +/** After we reach DOUBLE_UNTIL, client effort is multiplied by this amount + * on every retry until we reach MAX_POW_EFFORT. */ +#define CLIENT_POW_RETRY_MULTIPLIER (1.5f) + /** Send an INTRODUCE1 cell along the intro circuit and populate the rend * circuit identifier with the needed key material for the e2e encryption. * Return 0 on success, -1 if there is a transient error such that an action @@ -731,37 +736,76 @@ consider_sending_introduce1(origin_circuit_t *intro_circ, goto perm_err; }
- /* If the descriptor contains PoW parameters then the service is - * expecting a PoW solution in the INTRODUCE cell, which we solve here. */ - if (have_module_pow() && - desc->encrypted_data.pow_params && - desc->encrypted_data.pow_params->suggested_effort > 0) { - log_debug(LD_REND, "PoW params present in descriptor."); + /* Copy the introduction point authentication and encryption key + * in the rendezvous circuit identifier so we can compute the ntor keys + * when we receive the RENDEZVOUS2 cell. */ + memcpy(&rend_circ->hs_ident->intro_enc_pk, &ip->enc_key, + sizeof(rend_circ->hs_ident->intro_enc_pk));
- /* make sure we can't be tricked into hopeless quests */ - if (desc->encrypted_data.pow_params->suggested_effort > - CLIENT_MAX_POW_EFFORT) { + /* Optionally choose to solve a client puzzle for this connection. This + * is only available if we have PoW support at compile time, and if the + * service has provided a PoW seed in its descriptor. The puzzle is enabled + * any time effort is nonzero, which can be recommended by the service or + * self-imposed as a result of previous timeouts. + */ + if (have_module_pow() && desc->encrypted_data.pow_params) { + hs_pow_solver_inputs_t pow_inputs = { + .effort = desc->encrypted_data.pow_params->suggested_effort + }; + memcpy(pow_inputs.seed, desc->encrypted_data.pow_params->seed, + sizeof pow_inputs.seed); + log_debug(LD_REND, "PoW params present in descriptor, suggested_effort=%u", + pow_inputs.effort); + + if (pow_inputs.effort > CLIENT_MAX_POW_EFFORT) { log_notice(LD_REND, "Onion service suggested effort %d which is " "higher than we want to solve. Solving at %d instead.", - desc->encrypted_data.pow_params->suggested_effort, - CLIENT_MAX_POW_EFFORT); - - /* clobber it in-place. hopefully this won't have bad side effects. */ - desc->encrypted_data.pow_params->suggested_effort = - CLIENT_MAX_POW_EFFORT; + pow_inputs.effort, CLIENT_MAX_POW_EFFORT); + pow_inputs.effort = CLIENT_MAX_POW_EFFORT; }
- /* send it to the client-side pow cpuworker for solving. */ - intro_circ->hs_currently_solving_pow = 1; - if (0 != hs_pow_queue_work(intro_circ->global_identifier, - rend_circ->global_identifier, - desc->encrypted_data.pow_params)) { - log_debug(LD_REND, "Failed to enqueue PoW request"); + const hs_cache_intro_state_t *state = + hs_cache_client_intro_state_find(&intro_circ->hs_ident->identity_pk, + &intro_circ->hs_ident->intro_auth_pk); + uint32_t unreachable_count = state ? state->unreachable_count : 0; + if (state) { + log_debug(LD_REND, "hs_cache state during PoW consideration, " + "error=%d timed_out=%d unreachable_count=%u", + state->error, state->timed_out, state->unreachable_count); + } + uint64_t new_effort = pow_inputs.effort; + for (unsigned n_retry = 0; n_retry < unreachable_count; n_retry++) { + if (new_effort >= CLIENT_MAX_POW_EFFORT) { + break; + } + if (new_effort < CLIENT_POW_EFFORT_DOUBLE_UNTIL) { + new_effort <<= 1; + } else { + new_effort = (uint64_t) (CLIENT_POW_RETRY_MULTIPLIER * new_effort); + } + new_effort = MAX((uint64_t)CLIENT_MIN_RETRY_POW_EFFORT, new_effort); + new_effort = MIN((uint64_t)CLIENT_MAX_POW_EFFORT, new_effort); + } + if (pow_inputs.effort != (uint32_t)new_effort) { + log_notice(LD_REND, "Increasing PoW effort from %d to %d after intro " + "point unreachable_count=%d", + pow_inputs.effort, (int)new_effort, unreachable_count); + pow_inputs.effort = (uint32_t)new_effort; }
- /* can't proceed with the intro1 cell yet, so yield back to the - * main loop */ - goto tran_err; + if (pow_inputs.effort > 0) { + /* send it to the client-side pow cpuworker for solving. */ + intro_circ->hs_currently_solving_pow = 1; + if (hs_pow_queue_work(intro_circ->global_identifier, + rend_circ->global_identifier, + &pow_inputs) != 0) { + log_warn(LD_REND, "Failed to enqueue PoW request"); + } + + /* can't proceed with the intro1 cell yet, so yield back to the + * main loop */ + goto tran_err; + } }
/* move on to the next phase: actually try to send it */ @@ -796,8 +840,8 @@ consider_sending_introduce1(origin_circuit_t *intro_circ, * * Return 0 if everything went well, otherwise return -1 in the case of errors. */ -static int -setup_intro_circ_auth_key(origin_circuit_t *circ) +int +hs_client_setup_intro_circ_auth_key(origin_circuit_t *circ) { const hs_descriptor_t *desc; const hs_desc_intro_point_t *ip; @@ -843,13 +887,6 @@ client_intro_circ_has_opened(origin_circuit_t *circ) log_info(LD_REND, "Introduction circuit %u has opened. Attaching streams.", (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
- /* This is an introduction circuit so we'll attach the correct - * authentication key to the circuit identifier so it can be identified - * properly later on. */ - if (setup_intro_circ_auth_key(circ) < 0) { - return; - } - connection_ap_attach_pending(1); }
@@ -2047,6 +2084,7 @@ hs_client_circuit_cleanup_on_free(const circuit_t *circ)
orig_circ = CONST_TO_ORIGIN_CIRCUIT(circ); tor_assert(orig_circ->hs_ident); + const ed25519_public_key_t *intro_pk = &orig_circ->hs_ident->intro_auth_pk;
has_timed_out = (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT); @@ -2061,22 +2099,22 @@ hs_client_circuit_cleanup_on_free(const circuit_t *circ) safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)), safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)), failure); + tor_assert_nonfatal(!ed25519_public_key_is_zero(intro_pk)); hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk, - &orig_circ->hs_ident->intro_auth_pk, - failure); + intro_pk, failure); break; case CIRCUIT_PURPOSE_C_INTRODUCING: if (has_timed_out || !orig_circ->build_state) { break; } + tor_assert_nonfatal(!ed25519_public_key_is_zero(intro_pk)); failure = INTRO_POINT_FAILURE_UNREACHABLE; log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s " "(while building circuit). Marking as unreachable.", safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)), safe_str_client(build_state_get_exit_nickname(orig_circ->build_state))); hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk, - &orig_circ->hs_ident->intro_auth_pk, - failure); + intro_pk, failure); break; default: break; diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index e87cc00b75..234306a3c3 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -119,6 +119,8 @@ int hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk, int hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk); void hs_client_dir_info_changed(void);
+int hs_client_setup_intro_circ_auth_key(origin_circuit_t *circ); + int hs_client_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ);
diff --git a/src/feature/hs/hs_pow.c b/src/feature/hs/hs_pow.c index 199c290004..1f6932a55d 100644 --- a/src/feature/hs/hs_pow.c +++ b/src/feature/hs/hs_pow.c @@ -177,7 +177,7 @@ unpack_equix_solution(const uint8_t *bytes_in, * store the solution in pow_solution_out. Returns 0 on success and -1 * otherwise. Called by a client. */ int -hs_pow_solve(const hs_pow_desc_params_t *pow_params, +hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, hs_pow_solution_t *pow_solution_out) { int ret = -1; @@ -185,17 +185,15 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params, uint8_t *challenge = NULL; equix_ctx *ctx = NULL;
- tor_assert(pow_params); + tor_assert(pow_inputs); tor_assert(pow_solution_out); - - /* Select E (just using suggested for now) */ - uint32_t effort = pow_params->suggested_effort; + const uint32_t effort = pow_inputs->effort;
/* Generate a random nonce N. */ crypto_rand((char *)nonce, sizeof nonce);
/* Build EquiX challenge (C || N || INT_32(E)). */ - challenge = build_equix_challenge(pow_params->seed, nonce, effort); + challenge = build_equix_challenge(pow_inputs->seed, nonce, effort);
ctx = build_equix_ctx(EQUIX_CTX_SOLVE); if (!ctx) { @@ -218,7 +216,7 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params, /* Store the effort E. */ pow_solution_out->effort = effort; /* We only store the first 4 bytes of the seed C. */ - memcpy(pow_solution_out->seed_head, pow_params->seed, + memcpy(pow_solution_out->seed_head, pow_inputs->seed, sizeof(pow_solution_out->seed_head)); /* Store the solution S */ memcpy(&pow_solution_out->equix_solution, sol_bytes, sizeof sol_bytes); @@ -353,8 +351,8 @@ hs_pow_free_service_state(hs_pow_service_state_t *state) */ typedef struct pow_worker_job_t {
- /** Input: The pow challenge we need to solve. */ - hs_pow_desc_params_t *pow_params; + /** Inputs for the PoW solver (seed, chosen effort) */ + hs_pow_solver_inputs_t pow_inputs;
/** State: we'll look these up to figure out how to proceed after. */ uint32_t intro_circ_identifier; @@ -377,15 +375,15 @@ pow_worker_threadfn(void *state_, void *work_) pow_worker_job_t *job = work_; job->pow_solution_out = tor_malloc_zero(sizeof(hs_pow_solution_t));
- if (hs_pow_solve(job->pow_params, job->pow_solution_out)) { - log_info(LD_REND, "Haven't solved the PoW yet. Returning."); + if (hs_pow_solve(&job->pow_inputs, job->pow_solution_out)) { + log_warn(LD_REND, "Failed to run the proof of work solver"); tor_free(job->pow_solution_out); job->pow_solution_out = NULL; /* how we signal that we came up empty */ return WQ_RPL_REPLY; }
/* we have a winner! */ - log_info(LD_REND, "cpuworker pow: we have a winner!"); + log_info(LD_REND, "cpuworker has a proof of work solution"); return WQ_RPL_REPLY; }
@@ -397,7 +395,6 @@ pow_worker_job_free(pow_worker_job_t *job) { if (!job) return; - tor_free(job->pow_params); tor_free(job->pow_solution_out); tor_free(job); } @@ -470,14 +467,14 @@ pow_worker_replyfn(void *work_) int hs_pow_queue_work(uint32_t intro_circ_identifier, uint32_t rend_circ_identifier, - const hs_pow_desc_params_t *pow_params) + const hs_pow_solver_inputs_t *pow_inputs) { tor_assert(in_main_thread());
pow_worker_job_t *job = tor_malloc_zero(sizeof(*job)); job->intro_circ_identifier = intro_circ_identifier; job->rend_circ_identifier = rend_circ_identifier; - job->pow_params = tor_memdup(pow_params, sizeof(hs_pow_desc_params_t)); + memcpy(&job->pow_inputs, pow_inputs, sizeof job->pow_inputs);
workqueue_entry_t *work; work = cpuworker_queue_work(WQ_PRI_LOW, diff --git a/src/feature/hs/hs_pow.h b/src/feature/hs/hs_pow.h index fe78a48d9a..6e3611be69 100644 --- a/src/feature/hs/hs_pow.h +++ b/src/feature/hs/hs_pow.h @@ -56,6 +56,17 @@ typedef struct hs_pow_desc_params_t { time_t expiration_time; } hs_pow_desc_params_t;
+/** The inputs to the PoW solver, derived from the descriptor data and the + * client's per-connection effort choices. */ +typedef struct hs_pow_solver_inputs_t { + /** Seed value from a current descriptor */ + uint8_t seed[HS_POW_SEED_LEN]; + + /** Effort chosen by the client. May be higher or ower than + * suggested_effort in the descriptor. */ + uint32_t effort; +} hs_pow_solver_inputs_t; + /** State and parameters of PoW defenses, stored in the service state. */ typedef struct hs_pow_service_state_t { /* If PoW defenses are enabled this is a priority queue containing acceptable @@ -124,7 +135,7 @@ typedef struct hs_pow_solution_t { #define have_module_pow() (1)
/* API */ -int hs_pow_solve(const hs_pow_desc_params_t *pow_params, +int hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, hs_pow_solution_t *pow_solution_out);
int hs_pow_verify(const hs_pow_service_state_t *pow_state, @@ -135,16 +146,16 @@ void hs_pow_free_service_state(hs_pow_service_state_t *state);
int hs_pow_queue_work(uint32_t intro_circ_identifier, uint32_t rend_circ_identifier, - const hs_pow_desc_params_t *pow_params); + const hs_pow_solver_inputs_t *pow_inputs);
#else /* !defined(HAVE_MODULE_POW) */ #define have_module_pow() (0)
static inline int -hs_pow_solve(const hs_pow_desc_params_t *pow_params, +hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, hs_pow_solution_t *pow_solution_out) { - (void)pow_params; + (void)pow_inputs; (void)pow_solution_out; return -1; } @@ -173,11 +184,11 @@ hs_pow_free_service_state(hs_pow_service_state_t *state) static inline int hs_pow_queue_work(uint32_t intro_circ_identifier, uint32_t rend_circ_identifier, - const hs_pow_desc_params_t *pow_params) + const hs_pow_solver_inputs_t *pow_inputs) { (void)intro_circ_identifier; (void)rend_circ_identifier; - (void)pow_params; + (void)pow_inputs; return -1; }
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index 11a5589d21..f873d90212 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -177,6 +177,7 @@ helper_get_circ_and_stream_for_test(origin_circuit_t **circ_out,
/* prop224: Setup hs ident on the circuit */ or_circ->hs_ident = hs_ident_circuit_new(&service_pk); + or_circ->hs_ident->intro_auth_pk.pubkey[0] = 42;
TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
@@ -1186,6 +1187,7 @@ test_socks_hs_errors(void *arg) circ->purpose = CIRCUIT_PURPOSE_C_REND_READY; ocirc = TO_ORIGIN_CIRCUIT(circ); ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey); + ocirc->hs_ident->intro_auth_pk.pubkey[0] = 42; ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, diff --git a/src/test/test_hs_pow_slow.c b/src/test/test_hs_pow_slow.c index fdade2d3fa..e7d1311cee 100644 --- a/src/test/test_hs_pow_slow.c +++ b/src/test/test_hs_pow_slow.c @@ -187,17 +187,16 @@ test_hs_pow_vectors(void *arg) uint8_t rng_bytes[HS_POW_NONCE_LEN]; hs_pow_solution_t output; hs_pow_solution_t solution = { 0 }; - hs_pow_desc_params_t params = { - .type = HS_POW_DESC_V1, - .suggested_effort = vectors[vec_i].effort, + hs_pow_solver_inputs_t input = { + .effort = vectors[vec_i].effort, };
- tt_int_op(strlen(seed_hex), OP_EQ, 2 * sizeof params.seed); + tt_int_op(strlen(seed_hex), OP_EQ, 2 * sizeof input.seed); tt_int_op(strlen(solve_rng_hex), OP_EQ, 2 * sizeof rng_bytes); tt_int_op(strlen(nonce_hex), OP_EQ, 2 * sizeof solution.nonce); tt_int_op(strlen(sol_hex), OP_EQ, 2 * sizeof solution.equix_solution);
- tt_int_op(base16_decode((char*)params.seed, HS_POW_SEED_LEN, + tt_int_op(base16_decode((char*)input.seed, HS_POW_SEED_LEN, seed_hex, 2 * HS_POW_SEED_LEN), OP_EQ, HS_POW_SEED_LEN); tt_int_op(base16_decode((char*)rng_bytes, sizeof rng_bytes, @@ -210,11 +209,11 @@ test_hs_pow_vectors(void *arg) sizeof solution.equix_solution, sol_hex, 2 * sizeof solution.equix_solution), OP_EQ, HS_POW_EQX_SOL_LEN); - memcpy(solution.seed_head, params.seed, HS_POW_SEED_HEAD_LEN); + memcpy(solution.seed_head, input.seed, HS_POW_SEED_HEAD_LEN);
memset(&output, 0xaa, sizeof output); testing_enable_prefilled_rng(rng_bytes, HS_POW_NONCE_LEN); - tt_int_op(0, OP_EQ, hs_pow_solve(¶ms, &output)); + tt_int_op(0, OP_EQ, hs_pow_solve(&input, &output)); testing_disable_prefilled_rng();
tt_mem_op(solution.seed_head, OP_EQ, output.seed_head, @@ -224,7 +223,7 @@ test_hs_pow_vectors(void *arg) tt_mem_op(&solution.equix_solution, OP_EQ, &output.equix_solution, sizeof output.equix_solution);
- tt_int_op(testing_one_hs_pow_solution(&output, params.seed), OP_EQ, 0); + tt_int_op(testing_one_hs_pow_solution(&output, input.seed), OP_EQ, 0); }
done: