/* This is the first round of the new protocol run starting at * <b>valid_after</b>. Do the necessary housekeeping. */ STATIC void new_protocol_run(time_t valid_after) { sr_commit_t *our_commitment = NULL; /* Only compute the srv at the end of the reveal phase. */ if (sr_state->phase == SR_PHASE_REVEAL) { /* We are about to compute a new shared random value that will be set in * our state as the current value so rotate values. */ state_rotate_srv(); /* Compute the shared randomness value of the day. */ sr_compute_srv(); } /* Prepare for the new protocol run by reseting the state */ reset_state_for_new_protocol_run(valid_after); /* Do some logging */ log_info(LD_DIR, "SR: Protocol run #%" PRIu64 " starting!", sr_state->n_protocol_runs); /* Generate fresh commitments for this protocol run */ our_commitment = sr_generate_our_commit(valid_after, get_my_v3_authority_cert()); if (our_commitment) { /* Add our commitment to our state. In case we are unable to create one * (highly unlikely), we won't vote for this protocol run since our * commitment won't be in our state. */ sr_state_add_commit(our_commitment); } }
/* Save <b>commit</b> to our persistent state. Depending on the current * phase, different actions are taken. Steals reference of <b>commit</b>. * The commit object MUST be valid and verified before adding it to the * state. */ STATIC void save_commit_to_state(sr_commit_t *commit) { sr_phase_t phase = sr_state_get_phase(); ASSERT_COMMIT_VALID(commit); switch (phase) { case SR_PHASE_COMMIT: /* During commit phase, just save any new authoritative commit */ sr_state_add_commit(commit); break; case SR_PHASE_REVEAL: save_commit_during_reveal_phase(commit); sr_commit_free(commit); break; default: tor_assert(0); } }
/* Update the current SR state as needed for the upcoming voting round at * <b>valid_after</b>. */ void sr_state_update(time_t valid_after) { sr_phase_t next_phase; if (BUG(!sr_state)) return; /* Don't call this function twice in the same voting period. */ if (valid_after <= sr_state->valid_after) { log_info(LD_DIR, "SR: Asked to update state twice. Ignoring."); return; } /* Get phase of upcoming round. */ next_phase = get_sr_protocol_phase(valid_after); /* If we are transitioning to a new protocol phase, prepare the stage. */ if (is_phase_transition(next_phase)) { if (next_phase == SR_PHASE_COMMIT) { /* Going into commit phase means we are starting a new protocol run. */ new_protocol_run(valid_after); } /* Set the new phase for this round */ sr_state->phase = next_phase; } else if (sr_state->phase == SR_PHASE_COMMIT && digestmap_size(sr_state->commits) == 0) { /* We are _NOT_ in a transition phase so if we are in the commit phase * and have no commit, generate one. Chances are that we are booting up * so let's have a commit in our state for the next voting period. */ sr_commit_t *our_commit = sr_generate_our_commit(valid_after, get_my_v3_authority_cert()); if (our_commit) { /* Add our commitment to our state. In case we are unable to create one * (highly unlikely), we won't vote for this protocol run since our * commitment won't be in our state. */ sr_state_add_commit(our_commit); } } sr_state_set_valid_after(valid_after); /* Count the current round */ if (sr_state->phase == SR_PHASE_COMMIT) { /* invariant check: we've not entered reveal phase yet */ if (BUG(sr_state->n_reveal_rounds != 0)) return; sr_state->n_commit_rounds++; } else { sr_state->n_reveal_rounds++; } { /* Debugging. */ char tbuf[ISO_TIME_LEN + 1]; format_iso_time(tbuf, valid_after); log_info(LD_DIR, "SR: State prepared for upcoming voting period (%s). " "Upcoming phase is %s (counters: %d commit & %d reveal rounds).", tbuf, get_phase_str(sr_state->phase), sr_state->n_commit_rounds, sr_state->n_reveal_rounds); } }