GNUnet  0.11.x
Data Structures | Typedefs | Enumerations | Functions | Variables
gnunet-service-consensus.c File Reference

multi-peer set reconciliation More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_block_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_applications.h"
#include "gnunet_set_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_consensus_service.h"
#include "consensus_protocol.h"
#include "consensus.h"
Include dependency graph for gnunet-service-consensus.c:

Go to the source code of this file.

Data Structures

struct  TaskKey
 Tuple of integers that together identify a task uniquely. More...
 
struct  SetKey
 
struct  SetEntry
 
struct  DiffKey
 
struct  RfnKey
 
struct  SetOpCls
 
struct  FinishCls
 
union  TaskFuncCls
 Closure for both start_task and cancel_task. More...
 
struct  TaskEntry
 
struct  Step
 
struct  RfnElementInfo
 
struct  ReferendumEntry
 
struct  DiffElementInfo
 
struct  DiffEntry
 Weighted diff. More...
 
struct  SetHandle
 
struct  ConsensusSession
 A consensus session consists of one local client and the remote authorities. More...
 
struct  SetCopyCls
 
struct  SetMutationProgressCls
 

Typedefs

typedef void(* TaskFunc) (struct TaskEntry *task)
 

Enumerations

enum  ReferendumVote { VOTE_STAY = 0, VOTE_ADD = 1, VOTE_REMOVE = 2 }
 
enum  EarlyStoppingPhase { EARLY_STOPPING_NONE = 0, EARLY_STOPPING_ONE_MORE = 1, EARLY_STOPPING_DONE = 2 }
 
enum  PhaseKind {
  PHASE_KIND_ALL_TO_ALL, PHASE_KIND_ALL_TO_ALL_2, PHASE_KIND_GRADECAST_LEADER, PHASE_KIND_GRADECAST_ECHO,
  PHASE_KIND_GRADECAST_ECHO_GRADE, PHASE_KIND_GRADECAST_CONFIRM, PHASE_KIND_GRADECAST_CONFIRM_GRADE, PHASE_KIND_APPLY_REP,
  PHASE_KIND_FINISH
}
 
enum  SetKind {
  SET_KIND_NONE = 0, SET_KIND_CURRENT, SET_KIND_LAST_GRADECAST, SET_KIND_LEADER_PROPOSAL,
  SET_KIND_ECHO_RESULT
}
 
enum  DiffKind { DIFF_KIND_NONE = 0, DIFF_KIND_LEADER_PROPOSAL, DIFF_KIND_LEADER_CONSENSUS, DIFF_KIND_GRADECAST_RESULT }
 
enum  RfnKind { RFN_KIND_NONE = 0, RFN_KIND_ECHO, RFN_KIND_CONFIRM, RFN_KIND_GRADECAST_RESULT }
 

Functions

static void finish_task (struct TaskEntry *task)
 
static void run_ready_steps (struct ConsensusSession *session)
 
static const char * phasename (uint16_t phase)
 
static const char * setname (uint16_t kind)
 
static const char * rfnname (uint16_t kind)
 
static const char * diffname (uint16_t kind)
 
static int send_to_client_iter (void *cls, const struct GNUNET_SET_Element *element)
 Send the final result set of the consensus to the client, element by element. More...
 
static struct SetEntrylookup_set (struct ConsensusSession *session, const struct SetKey *key)
 
static struct DiffEntrylookup_diff (struct ConsensusSession *session, const struct DiffKey *key)
 
static struct ReferendumEntrylookup_rfn (struct ConsensusSession *session, const struct RfnKey *key)
 
static void diff_insert (struct DiffEntry *diff, int weight, const struct GNUNET_SET_Element *element)
 
static void rfn_commit (struct ReferendumEntry *rfn, uint16_t commit_peer)
 
static void rfn_contest (struct ReferendumEntry *rfn, uint16_t contested_peer)
 
static uint16_t rfn_noncontested (struct ReferendumEntry *rfn)
 
static void rfn_vote (struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
 
static uint16_t task_other_peer (struct TaskEntry *task)
 
static int cmp_uint64_t (const void *pa, const void *pb)
 
static void set_result_cb (void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
 Callback for set operation results. More...
 
static void commit_set (struct ConsensusSession *session, struct TaskEntry *task)
 Commit the appropriate set for a task. More...
 
static void put_diff (struct ConsensusSession *session, struct DiffEntry *diff)
 
static void put_set (struct ConsensusSession *session, struct SetEntry *set)
 
static void put_rfn (struct ConsensusSession *session, struct ReferendumEntry *rfn)
 
static void task_cancel_reconcile (struct TaskEntry *task)
 
static void apply_diff_to_rfn (struct DiffEntry *diff, struct ReferendumEntry *rfn, uint16_t voting_peer, uint16_t num_peers)
 
static struct DiffEntrydiff_create (void)
 
struct ReferendumEntryrfn_create (uint16_t size)
 
static void rfn_majority (const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
 For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that voted for this outcome. More...
 
static void set_copy_cb (void *cls, struct GNUNET_SET_Handle *copy)
 
static void create_set_copy_for_task (struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
 Call the start function of the given task again after we created a copy of the given set. More...
 
static void set_mutation_done (void *cls)
 
static void try_finish_step_early (struct Step *step)
 
static void finish_step (struct Step *step)
 
static void task_start_apply_round (struct TaskEntry *task)
 Apply the result from one round of gradecasts (i.e. More...
 
static void task_start_grade (struct TaskEntry *task)
 
static void task_start_reconcile (struct TaskEntry *task)
 
static void task_start_eval_echo (struct TaskEntry *task)
 
static void task_start_finish (struct TaskEntry *task)
 
static void start_task (struct ConsensusSession *session, struct TaskEntry *task)
 
static int get_peer_idx (const struct GNUNET_PeerIdentity *peer, const struct ConsensusSession *session)
 Search peer in the list of peers in session. More...
 
static void compute_global_id (struct ConsensusSession *session, const struct GNUNET_HashCode *local_session_id)
 Compute a global, (hopefully) unique consensus session id, from the local id of the consensus session, and the identities of all participants. More...
 
static int peer_id_cmp (const void *h1, const void *h2)
 Compare two peer identities (for qsort()). More...
 
static void initialize_session_peer_list (struct ConsensusSession *session, const struct GNUNET_CONSENSUS_JoinMessage *join_msg)
 Create the sorted list of peers for the session, add the local peer if not in the join message. More...
 
static struct TaskEntrylookup_task (const struct ConsensusSession *session, const struct TaskKey *key)
 
static void set_listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request)
 Called when another peer wants to do a set operation with the local peer. More...
 
static void put_task (struct GNUNET_CONTAINER_MultiHashMap *taskmap, struct TaskEntry *t)
 
static void install_step_timeouts (struct ConsensusSession *session)
 
static void arrange_peers (uint16_t *p1, uint16_t *p2, uint16_t n)
 
static void step_depend_on (struct Step *step, struct Step *dep)
 Record dep as a dependency of step. More...
 
static struct Stepcreate_step (struct ConsensusSession *session, int round, int early_finishable)
 
static void construct_task_graph_gradecast (struct ConsensusSession *session, uint16_t rep, uint16_t lead, struct Step *step_before, struct Step *step_after)
 Construct the task graph for a single gradecast. More...
 
static void construct_task_graph (struct ConsensusSession *session)
 
static int check_client_join (void *cls, const struct GNUNET_CONSENSUS_JoinMessage *m)
 Check join message. More...
 
static void handle_client_join (void *cls, const struct GNUNET_CONSENSUS_JoinMessage *m)
 Called when a client wants to join a consensus session. More...
 
static int check_client_insert (void *cls, const struct GNUNET_CONSENSUS_ElementMessage *msg)
 Called when a client performs an insert operation. More...
 
static void handle_client_insert (void *cls, const struct GNUNET_CONSENSUS_ElementMessage *msg)
 Called when a client performs an insert operation. More...
 
static void handle_client_conclude (void *cls, const struct GNUNET_MessageHeader *message)
 Called when a client performs the conclude operation. More...
 
static void shutdown_task (void *cls)
 Called to clean up, after a shutdown has been requested. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Start processing consensus requests. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
 Callback called when a client connects to the service. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
 Callback called when a client disconnected from the service. More...
 
 GNUNET_SERVICE_MAIN ("consensus", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_conclude, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_var_size(client_insert, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT, struct GNUNET_CONSENSUS_ElementMessage, NULL), GNUNET_MQ_hd_var_size(client_join, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN, struct GNUNET_CONSENSUS_JoinMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static struct ConsensusSessionsessions_head
 Linked list of sessions this peer participates in. More...
 
static struct ConsensusSessionsessions_tail
 Linked list of sessions this peer participates in. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Configuration of the consensus service. More...
 
static struct GNUNET_PeerIdentity my_peer
 Peer that runs this service. More...
 
struct GNUNET_STATISTICS_Handlestatistics
 Statistics handle. More...
 

Detailed Description

multi-peer set reconciliation

Author
Florian Dold flo@d.nosp@m.old..nosp@m.me

Definition in file gnunet-service-consensus.c.

Typedef Documentation

◆ TaskFunc

typedef void(* TaskFunc) (struct TaskEntry *task)

Definition at line 230 of file gnunet-service-consensus.c.

Enumeration Type Documentation

◆ ReferendumVote

Enumerator
VOTE_STAY 

Vote that nothing should change.

This option is never voted explicitly.

VOTE_ADD 

Vote that an element should be added.

VOTE_REMOVE 

Vote that an element should be removed.

Definition at line 37 of file gnunet-service-consensus.c.

38 {
43  VOTE_STAY = 0,
47  VOTE_ADD = 1,
51  VOTE_REMOVE = 2,
52 };
Vote that an element should be removed.
Vote that nothing should change.
Vote that an element should be added.

◆ EarlyStoppingPhase

Enumerator
EARLY_STOPPING_NONE 
EARLY_STOPPING_ONE_MORE 
EARLY_STOPPING_DONE 

Definition at line 55 of file gnunet-service-consensus.c.

◆ PhaseKind

enum PhaseKind
Enumerator
PHASE_KIND_ALL_TO_ALL 
PHASE_KIND_ALL_TO_ALL_2 
PHASE_KIND_GRADECAST_LEADER 
PHASE_KIND_GRADECAST_ECHO 
PHASE_KIND_GRADECAST_ECHO_GRADE 
PHASE_KIND_GRADECAST_CONFIRM 
PHASE_KIND_GRADECAST_CONFIRM_GRADE 
PHASE_KIND_APPLY_REP 

Apply a repetition of the all-to-all gradecast to the current set.

PHASE_KIND_FINISH 

Definition at line 63 of file gnunet-service-consensus.c.

◆ SetKind

enum SetKind
Enumerator
SET_KIND_NONE 
SET_KIND_CURRENT 
SET_KIND_LAST_GRADECAST 

Last result set from a gradecast.

SET_KIND_LEADER_PROPOSAL 
SET_KIND_ECHO_RESULT 

Definition at line 81 of file gnunet-service-consensus.c.

◆ DiffKind

enum DiffKind
Enumerator
DIFF_KIND_NONE 
DIFF_KIND_LEADER_PROPOSAL 
DIFF_KIND_LEADER_CONSENSUS 
DIFF_KIND_GRADECAST_RESULT 

Definition at line 93 of file gnunet-service-consensus.c.

◆ RfnKind

enum RfnKind
Enumerator
RFN_KIND_NONE 
RFN_KIND_ECHO 
RFN_KIND_CONFIRM 
RFN_KIND_GRADECAST_RESULT 

Definition at line 101 of file gnunet-service-consensus.c.

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

Definition at line 2489 of file gnunet-service-consensus.c.

References finish_step(), Step::finished_tasks, GNUNET_assert, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_YES, TaskEntry::is_finished, TaskEntry::key, ConsensusSession::local_peer_idx, Step::session, TaskEntry::step, and Step::tasks_len.

Referenced by commit_set(), set_mutation_done(), set_result_cb(), task_start_apply_round(), task_start_eval_echo(), task_start_grade(), and task_start_reconcile().

2490 {
2491  GNUNET_assert (GNUNET_NO == task->is_finished);
2492  task->is_finished = GNUNET_YES;
2493  task->step->finished_tasks++;
2495  "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
2496  task->step->session->local_peer_idx,
2497  debug_str_task_key (&task->key),
2498  (unsigned int) task->step->finished_tasks,
2499  (unsigned int) task->step->tasks_len);
2500 
2501  if (task->step->finished_tasks == task->step->tasks_len)
2502  finish_step (task->step);
2503 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
unsigned int tasks_len
static void finish_step(struct Step *step)
struct TaskKey key
unsigned int finished_tasks
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_ready_steps()

static void run_ready_steps ( struct ConsensusSession session)
static

Definition at line 2448 of file gnunet-service-consensus.c.

References Step::debug_name, finish_step(), Step::finished_tasks, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, Step::is_finished, Step::is_running, ConsensusSession::local_peer_idx, Step::next, Step::pending_prereq, Step::round, start_task(), ConsensusSession::steps_head, Step::subordinates_len, Step::tasks, and Step::tasks_len.

Referenced by finish_step(), handle_client_conclude(), and try_finish_step_early().

2449 {
2450  struct Step *step;
2451 
2452  step = session->steps_head;
2453 
2454  while (NULL != step)
2455  {
2456  if ((GNUNET_NO == step->is_running) && (0 == step->pending_prereq) &&
2457  (GNUNET_NO == step->is_finished))
2458  {
2459  GNUNET_assert (0 == step->finished_tasks);
2460 
2461 #ifdef GNUNET_EXTRA_LOGGING
2463  "P%u: Running step `%s' of round %d with %d tasks and %d subordinates\n",
2464  session->local_peer_idx,
2465  step->debug_name,
2466  step->round, step->tasks_len, step->subordinates_len);
2467 #endif
2468 
2469  step->is_running = GNUNET_YES;
2470  for (size_t i = 0; i < step->tasks_len; i++)
2471  start_task (session, step->tasks[i]);
2472 
2473  /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
2474  if ((step->finished_tasks == step->tasks_len) && (GNUNET_NO ==
2475  step->is_finished))
2476  finish_step (step);
2477 
2478  /* Running the next ready steps will be triggered by task completion */
2479  return;
2480  }
2481  step = step->next;
2482  }
2483 
2484  return;
2485 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int tasks_len
struct Step * next
All steps of one session are in a linked list for easier deallocation.
size_t pending_prereq
Counter for the prerequisites of this step.
static void finish_step(struct Step *step)
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskEntry ** tasks
Tasks that this step is composed of.
unsigned int is_finished
unsigned int round
Synchrony round of the task.
unsigned int finished_tasks
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
unsigned int is_running
static void start_task(struct ConsensusSession *session, struct TaskEntry *task)
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ phasename()

static const char* phasename ( uint16_t  phase)
static

Definition at line 551 of file gnunet-service-consensus.c.

References PHASE_KIND_ALL_TO_ALL, PHASE_KIND_ALL_TO_ALL_2, PHASE_KIND_APPLY_REP, PHASE_KIND_FINISH, PHASE_KIND_GRADECAST_CONFIRM, PHASE_KIND_GRADECAST_CONFIRM_GRADE, PHASE_KIND_GRADECAST_ECHO, PHASE_KIND_GRADECAST_ECHO_GRADE, and PHASE_KIND_GRADECAST_LEADER.

Referenced by diffname().

552 {
553  switch (phase)
554  {
555  case PHASE_KIND_ALL_TO_ALL: return "ALL_TO_ALL";
556 
557  case PHASE_KIND_ALL_TO_ALL_2: return "ALL_TO_ALL_2";
558 
559  case PHASE_KIND_FINISH: return "FINISH";
560 
561  case PHASE_KIND_GRADECAST_LEADER: return "GRADECAST_LEADER";
562 
563  case PHASE_KIND_GRADECAST_ECHO: return "GRADECAST_ECHO";
564 
565  case PHASE_KIND_GRADECAST_ECHO_GRADE: return "GRADECAST_ECHO_GRADE";
566 
567  case PHASE_KIND_GRADECAST_CONFIRM: return "GRADECAST_CONFIRM";
568 
569  case PHASE_KIND_GRADECAST_CONFIRM_GRADE: return "GRADECAST_CONFIRM_GRADE";
570 
571  case PHASE_KIND_APPLY_REP: return "APPLY_REP";
572 
573  default: return "(unknown)";
574  }
575 }
static unsigned int phase
Processing stage that we are in.
Definition: gnunet-arm.c:114
Apply a repetition of the all-to-all gradecast to the current set.
Here is the caller graph for this function:

◆ setname()

static const char* setname ( uint16_t  kind)
static

Definition at line 579 of file gnunet-service-consensus.c.

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

Referenced by diffname().

580 {
581  switch (kind)
582  {
583  case SET_KIND_CURRENT: return "CURRENT";
584 
585  case SET_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
586 
587  case SET_KIND_NONE: return "NONE";
588 
589  default: return "(unknown)";
590  }
591 }
Here is the caller graph for this function:

◆ rfnname()

static const char* rfnname ( uint16_t  kind)
static

Definition at line 595 of file gnunet-service-consensus.c.

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

Referenced by diffname().

596 {
597  switch (kind)
598  {
599  case RFN_KIND_NONE: return "NONE";
600 
601  case RFN_KIND_ECHO: return "ECHO";
602 
603  case RFN_KIND_CONFIRM: return "CONFIRM";
604 
605  default: return "(unknown)";
606  }
607 }
Here is the caller graph for this function:

◆ diffname()

static const char* diffname ( uint16_t  kind)
static

Definition at line 611 of file gnunet-service-consensus.c.

References buf, DiffKey::diff_kind, DIFF_KIND_GRADECAST_RESULT, DIFF_KIND_LEADER_CONSENSUS, DIFF_KIND_LEADER_PROPOSAL, DIFF_KIND_NONE, el, GNUNET_h2s(), GNUNET_SET_element_hash(), SetKey::k1, DiffKey::k1, RfnKey::k1, SetKey::k2, DiffKey::k2, RfnKey::k2, TaskKey::kind, TaskKey::leader, TaskKey::peer1, TaskKey::peer2, phasename(), TaskKey::repetition, RfnKey::rfn_kind, rfnname(), SetKey::set_kind, and setname().

612 {
613  switch (kind)
614  {
615  case DIFF_KIND_NONE: return "NONE";
616 
617  case DIFF_KIND_LEADER_CONSENSUS: return "LEADER_CONSENSUS";
618 
619  case DIFF_KIND_GRADECAST_RESULT: return "GRADECAST_RESULT";
620 
621  case DIFF_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
622 
623  default: return "(unknown)";
624  }
625 }
Here is the call graph for this function:

◆ send_to_client_iter()

static int send_to_client_iter ( void *  cls,
const struct GNUNET_SET_Element element 
)
static

Send the final result set of the consensus to the client, element by element.

Parameters
clsclosure
elementthe current element, NULL if all elements have been iterated over
Returns
GNUNET_YES to continue iterating, GNUNET_NO to stop.

Definition at line 710 of file gnunet-service-consensus.c.

References ConsensusSession::client_mq, GNUNET_SET_Element::data, GNUNET_CONSENSUS_ElementMessage::element_type, GNUNET_SET_Element::element_type, GNUNET_assert, GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT, GNUNET_MQ_msg_extra, GNUNET_MQ_msg_header, GNUNET_MQ_send(), GNUNET_YES, ConsensusSession::local_peer_idx, m, ConsensusElement::marker, ConsensusElement::payload_type, Step::session, GNUNET_SET_Element::size, and TaskEntry::step.

Referenced by task_start_finish().

712 {
713  struct TaskEntry *task = (struct TaskEntry *) cls;
714  struct ConsensusSession *session = task->step->session;
715  struct GNUNET_MQ_Envelope *ev;
716 
717  if (NULL != element)
718  {
720  const struct ConsensusElement *ce;
721 
723  element->element_type);
724  ce = element->data;
725 
726  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "marker is %u\n",
727  (unsigned) ce->marker);
728 
729  if (0 != ce->marker)
730  return GNUNET_YES;
731 
733  "P%d: sending element %s to client\n",
734  session->local_peer_idx,
735  debug_str_element (element));
736 
737  ev = GNUNET_MQ_msg_extra (m,
738  element->size - sizeof(struct ConsensusElement),
740  m->element_type = ce->payload_type;
741  GNUNET_memcpy (&m[1],
742  &ce[1],
743  element->size - sizeof(struct ConsensusElement));
744  GNUNET_MQ_send (session->client_mq,
745  ev);
746  }
747  else
748  {
750  "P%d: finished iterating elements for client\n",
751  session->local_peer_idx);
752  ev = GNUNET_MQ_msg_header (
754  GNUNET_MQ_send (session->client_mq,
755  ev);
756  }
757  return GNUNET_YES;
758 }
Consensus element, either marker or payload.
uint16_t payload_type
Payload element_type, only valid if this is not a marker element.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
const void * data
Actual data of the element.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
Message with an element.
Definition: consensus.h:72
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT
Sent by service when a new element is added.
struct GNUNET_MQ_Handle * client_mq
Queued messages to the client.
A consensus session consists of one local client and the remote authorities.
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:76
uint8_t marker
Is this a marker element?
uint16_t element_type
Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_NEW_ELEMENT.
Definition: consensus.h:84
Block type for consensus elements.
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE
Sent by service to client in order to signal a completed consensus conclusion.
uint16_t size
Number of bytes in the buffer pointed to by data.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:355
union TaskFuncCls cls
uint16_t element_type
Application-specific element type.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_set()

static struct SetEntry* lookup_set ( struct ConsensusSession session,
const struct SetKey key 
)
static

Definition at line 762 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, ConsensusSession::local_peer_idx, SetKey::set_kind, SET_KIND_NONE, and ConsensusSession::setmap.

Referenced by commit_set(), create_set_copy_for_task(), handle_client_insert(), set_result_cb(), task_start_apply_round(), task_start_eval_echo(), task_start_finish(), and task_start_reconcile().

764 {
765  struct GNUNET_HashCode hash;
766 
768  "P%u: looking up set {%s}\n",
769  session->local_peer_idx,
770  debug_str_set_key (key));
771 
773  GNUNET_CRYPTO_hash (key,
774  sizeof(struct SetKey),
775  &hash);
776  return GNUNET_CONTAINER_multihashmap_get (session->setmap,
777  &hash);
778 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CONTAINER_MultiHashMap * setmap
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
enum SetKind set_kind
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_diff()

static struct DiffEntry* lookup_diff ( struct ConsensusSession session,
const struct DiffKey key 
)
static

Definition at line 782 of file gnunet-service-consensus.c.

References DiffKey::diff_kind, DIFF_KIND_NONE, ConsensusSession::diffmap, GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and ConsensusSession::local_peer_idx.

Referenced by set_result_cb(), task_start_grade(), and task_start_reconcile().

784 {
785  struct GNUNET_HashCode hash;
786 
788  "P%u: looking up diff {%s}\n",
789  session->local_peer_idx,
790  debug_str_diff_key (key));
792  GNUNET_CRYPTO_hash (key,
793  sizeof(struct DiffKey),
794  &hash);
796  &hash);
797 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
enum DiffKind diff_kind
struct GNUNET_CONTAINER_MultiHashMap * diffmap
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_rfn()

static struct ReferendumEntry* lookup_rfn ( struct ConsensusSession session,
const struct RfnKey key 
)
static

Definition at line 801 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, ConsensusSession::local_peer_idx, RfnKey::rfn_kind, RFN_KIND_NONE, and ConsensusSession::rfnmap.

Referenced by set_result_cb(), task_start_apply_round(), task_start_eval_echo(), task_start_grade(), and task_start_reconcile().

803 {
804  struct GNUNET_HashCode hash;
805 
807  "P%u: looking up rfn {%s}\n",
808  session->local_peer_idx,
809  debug_str_rfn_key (key));
811  GNUNET_CRYPTO_hash (key,
812  sizeof(struct RfnKey),
813  &hash);
814  return GNUNET_CONTAINER_multihashmap_get (session->rfnmap,
815  &hash);
816 }
struct GNUNET_CONTAINER_MultiHashMap * rfnmap
enum RfnKind rfn_kind
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_insert()

static void diff_insert ( struct DiffEntry diff,
int  weight,
const struct GNUNET_SET_Element element 
)
static

Definition at line 820 of file gnunet-service-consensus.c.

References DiffEntry::changes, DiffElementInfo::element, GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_SET_element_dup(), GNUNET_SET_element_hash(), GNUNET_SET_Element::size, and DiffElementInfo::weight.

Referenced by diff_create(), and set_result_cb().

823 {
824  struct DiffElementInfo *di;
825  struct GNUNET_HashCode hash;
826 
827  GNUNET_assert ((1 == weight) || (-1 == weight));
828 
830  "diff_insert with element size %u\n",
831  element->size);
832 
834  "hashing element\n");
835 
836  GNUNET_SET_element_hash (element, &hash);
837 
839  "hashed element\n");
840 
841  di = GNUNET_CONTAINER_multihashmap_get (diff->changes, &hash);
842 
843  if (NULL == di)
844  {
845  di = GNUNET_new (struct DiffElementInfo);
846  di->element = GNUNET_SET_element_dup (element);
849  &hash,
850  di,
852  }
853 
854  di->weight = weight;
855 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
const struct GNUNET_SET_Element * element
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1246
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
struct GNUNET_CONTAINER_MultiHashMap * changes
int weight
Positive weight for &#39;add&#39;, negative weights for &#39;remove&#39;.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
uint16_t size
Number of bytes in the buffer pointed to by data.
#define GNUNET_log(kind,...)
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1223
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_commit()

static void rfn_commit ( struct ReferendumEntry rfn,
uint16_t  commit_peer 
)
static

Definition at line 859 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_YES, num_peers, and ReferendumEntry::peer_commited.

Referenced by set_result_cb(), and task_start_grade().

861 {
862  GNUNET_assert (commit_peer < rfn->num_peers);
863 
864  rfn->peer_commited[commit_peer] = GNUNET_YES;
865 }
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static unsigned int num_peers
Here is the caller graph for this function:

◆ rfn_contest()

static void rfn_contest ( struct ReferendumEntry rfn,
uint16_t  contested_peer 
)
static

Definition at line 869 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_YES, num_peers, and ReferendumEntry::peer_contested.

Referenced by set_result_cb().

871 {
872  GNUNET_assert (contested_peer < rfn->num_peers);
873 
874  rfn->peer_contested[contested_peer] = GNUNET_YES;
875 }
int * peer_contested
Contestation state of the peer.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static unsigned int num_peers
Here is the caller graph for this function:

◆ rfn_noncontested()

static uint16_t rfn_noncontested ( struct ReferendumEntry rfn)
static

Definition at line 879 of file gnunet-service-consensus.c.

References GNUNET_NO, GNUNET_YES, ReferendumEntry::num_peers, ReferendumEntry::peer_commited, ReferendumEntry::peer_contested, and ret.

Referenced by task_start_grade().

880 {
881  uint16_t ret;
882 
883  ret = 0;
884  for (uint16_t i = 0; i < rfn->num_peers; i++)
885  if ((GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO ==
886  rfn->peer_contested[i]))
887  ret++;
888 
889  return ret;
890 }
int * peer_contested
Contestation state of the peer.
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
Here is the caller graph for this function:

◆ rfn_vote()

static void rfn_vote ( struct ReferendumEntry rfn,
uint16_t  voting_peer,
enum ReferendumVote  vote,
const struct GNUNET_SET_Element element 
)
static

Definition at line 894 of file gnunet-service-consensus.c.

References RfnElementInfo::element, GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_new, GNUNET_new_array, GNUNET_OK, GNUNET_SET_element_dup(), GNUNET_SET_element_hash(), GNUNET_YES, num_peers, ReferendumEntry::num_peers, RfnElementInfo::proposal, ReferendumEntry::rfn_elements, VOTE_ADD, VOTE_REMOVE, and RfnElementInfo::votes.

Referenced by apply_diff_to_rfn(), set_result_cb(), and task_start_grade().

898 {
899  struct RfnElementInfo *ri;
900  struct GNUNET_HashCode hash;
901 
902  GNUNET_assert (voting_peer < rfn->num_peers);
903 
904  /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
905  since VOTE_KEEP is implicit in not voting. */
906  GNUNET_assert ((VOTE_ADD == vote) || (VOTE_REMOVE == vote));
907 
908  GNUNET_SET_element_hash (element, &hash);
910 
911  if (NULL == ri)
912  {
913  ri = GNUNET_new (struct RfnElementInfo);
914  ri->element = GNUNET_SET_element_dup (element);
915  ri->votes = GNUNET_new_array (rfn->num_peers, int);
918  &hash, ri,
920  }
921 
922  ri->votes[voting_peer] = GNUNET_YES;
923  ri->proposal = vote;
924 }
Vote that an element should be removed.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1246
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static unsigned int num_peers
Vote that an element should be added.
const struct GNUNET_SET_Element * element
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1223
int * votes
GNUNET_YES if the peer votes for the proposal.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_other_peer()

static uint16_t task_other_peer ( struct TaskEntry task)
static

Definition at line 928 of file gnunet-service-consensus.c.

References TaskEntry::key, ConsensusSession::local_peer_idx, me, TaskKey::peer1, TaskKey::peer2, Step::session, and TaskEntry::step.

Referenced by commit_set(), and set_result_cb().

929 {
930  uint16_t me = task->step->session->local_peer_idx;
931 
932  if (task->key.peer1 == me)
933  return task->key.peer2;
934  return task->key.peer1;
935 }
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
struct ConsensusSession * session
struct TaskKey key
struct Step * step
unsigned int local_peer_idx
Index of the local peer in the peers array.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
Here is the caller graph for this function:

◆ cmp_uint64_t()

static int cmp_uint64_t ( const void *  pa,
const void *  pb 
)
static

Definition at line 939 of file gnunet-service-consensus.c.

References testconfigure::b.

Referenced by set_result_cb().

940 {
941  uint64_t a = *(uint64_t *) pa;
942  uint64_t b = *(uint64_t *) pb;
943 
944  if (a == b)
945  return 0;
946  if (a < b)
947  return -1;
948  return 1;
949 }
Here is the caller graph for this function:

◆ set_result_cb()

static void set_result_cb ( void *  cls,
const struct GNUNET_SET_Element element,
uint64_t  current_size,
enum GNUNET_SET_Status  status 
)
static

Callback for set operation results.

Called for each element in the result set.

Parameters
clsclosure
elementa result element, only valid if status is GNUNET_SET_STATUS_OK
current_sizecurrent set size
statussee enum GNUNET_SET_Status

Definition at line 962 of file gnunet-service-consensus.c.

References cleanup(), TaskEntry::cls, cmp_uint64_t(), CONSENSUS_MARKER_CONTESTED, CONSENSUS_MARKER_SIZE, GNUNET_SET_Element::data, diff_insert(), DiffKey::diff_kind, DIFF_KIND_NONE, SetOpCls::do_not_remove, GNUNET_SET_Element::element_type, finish_task(), Step::finished_tasks, ConsensusSession::first_size, ConsensusSession::first_sizes_received, GNUNET_assert, GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, GNUNET_break_op, GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_memdup, GNUNET_new_array, GNUNET_NO, GNUNET_ntohll(), GNUNET_OK, GNUNET_SET_add_element(), GNUNET_SET_remove_element(), GNUNET_SET_STATUS_ADD_LOCAL, GNUNET_SET_STATUS_ADD_REMOTE, GNUNET_SET_STATUS_DONE, GNUNET_SET_STATUS_FAILURE, GNUNET_SYSERR, GNUNET_YES, SetEntry::h, TaskEntry::is_finished, TaskEntry::is_started, TaskEntry::key, TaskKey::kind, ConsensusSession::local_peer_idx, lookup_diff(), lookup_rfn(), lookup_set(), ConsensusSession::lower_bound, ConsensusElement::marker, ConsensusSession::num_peers, SetOpCls::output_diff, SetOpCls::output_rfn, SetOpCls::output_set, ConsensusSession::peers_blacklisted, PHASE_KIND_ALL_TO_ALL, ret, rfn_commit(), rfn_contest(), RfnKey::rfn_kind, RFN_KIND_NONE, rfn_vote(), ConsensusSizeElement::sender_index, Step::session, SetKey::set_kind, SET_KIND_NONE, TaskFuncCls::setop, ConsensusSizeElement::size, TaskEntry::step, task_other_peer(), Step::tasks_len, SetOpCls::transceive_contested, type, VOTE_ADD, and VOTE_REMOVE.

Referenced by set_listen_cb(), and task_start_reconcile().

966 {
967  struct TaskEntry *task = cls;
968  struct ConsensusSession *session = task->step->session;
969  struct SetEntry *output_set = NULL;
970  struct DiffEntry *output_diff = NULL;
971  struct ReferendumEntry *output_rfn = NULL;
972  unsigned int other_idx;
973  struct SetOpCls *setop;
974  const struct ConsensusElement *consensus_element = NULL;
975 
976  if (NULL != element)
977  {
979  "P%u: got element of type %u, status %u\n",
980  session->local_peer_idx,
981  (unsigned) element->element_type,
982  (unsigned) status);
984  element->element_type);
985  consensus_element = element->data;
986  }
987 
988  setop = &task->cls.setop;
989 
990 
992  "P%u: got set result for {%s}, status %u\n",
993  session->local_peer_idx,
994  debug_str_task_key (&task->key),
995  status);
996 
997  if (GNUNET_NO == task->is_started)
998  {
999  GNUNET_break_op (0);
1000  return;
1001  }
1002 
1003  if (GNUNET_YES == task->is_finished)
1004  {
1005  GNUNET_break_op (0);
1006  return;
1007  }
1008 
1009  other_idx = task_other_peer (task);
1010 
1011  if (SET_KIND_NONE != setop->output_set.set_kind)
1012  {
1013  output_set = lookup_set (session,
1014  &setop->output_set);
1015  GNUNET_assert (NULL != output_set);
1016  }
1017 
1018  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
1019  {
1020  output_diff = lookup_diff (session, &setop->output_diff);
1021  GNUNET_assert (NULL != output_diff);
1022  }
1023 
1024  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
1025  {
1026  output_rfn = lookup_rfn (session, &setop->output_rfn);
1027  GNUNET_assert (NULL != output_rfn);
1028  }
1029 
1030  if (GNUNET_YES == session->peers_blacklisted[other_idx])
1031  {
1032  /* Peer might have been blacklisted
1033  by a gradecast running in parallel, ignore elements from now */
1035  return;
1037  return;
1038  }
1039 
1040  if ((NULL != consensus_element) && (0 != consensus_element->marker))
1041  {
1043  "P%u: got some marker\n",
1044  session->local_peer_idx);
1045  if ((GNUNET_YES == setop->transceive_contested) &&
1046  (CONSENSUS_MARKER_CONTESTED == consensus_element->marker))
1047  {
1048  GNUNET_assert (NULL != output_rfn);
1049  rfn_contest (output_rfn, task_other_peer (task));
1050  return;
1051  }
1052 
1053  if (CONSENSUS_MARKER_SIZE == consensus_element->marker)
1054  {
1056  "P%u: got size marker\n",
1057  session->local_peer_idx);
1058 
1059 
1060  struct ConsensusSizeElement *cse = (void *) consensus_element;
1061 
1062  if (cse->sender_index == other_idx)
1063  {
1064  if (NULL == session->first_sizes_received)
1065  session->first_sizes_received = GNUNET_new_array (session->num_peers,
1066  uint64_t);
1067  session->first_sizes_received[other_idx] = GNUNET_ntohll (cse->size);
1068 
1069  uint64_t *copy = GNUNET_memdup (session->first_sizes_received,
1070  sizeof(uint64_t) * session->num_peers);
1071  qsort (copy, session->num_peers, sizeof(uint64_t), cmp_uint64_t);
1072  session->lower_bound = copy[session->num_peers / 3 + 1];
1074  "P%u: lower bound %llu\n",
1075  session->local_peer_idx,
1076  (long long) session->lower_bound);
1077  GNUNET_free (copy);
1078  }
1079  return;
1080  }
1081 
1082  return;
1083  }
1084 
1085  switch (status)
1086  {
1088  GNUNET_assert (NULL != consensus_element);
1090  "Adding element in Task {%s}\n",
1091  debug_str_task_key (&task->key));
1092  if (NULL != output_set)
1093  {
1094  // FIXME: record pending adds, use callback
1095  GNUNET_SET_add_element (output_set->h,
1096  element,
1097  NULL,
1098  NULL);
1099 #ifdef GNUNET_EXTRA_LOGGING
1101  "P%u: adding element %s into set {%s} of task {%s}\n",
1102  session->local_peer_idx,
1103  debug_str_element (element),
1104  debug_str_set_key (&setop->output_set),
1105  debug_str_task_key (&task->key));
1106 #endif
1107  }
1108  if (NULL != output_diff)
1109  {
1110  diff_insert (output_diff, 1, element);
1111 #ifdef GNUNET_EXTRA_LOGGING
1113  "P%u: adding element %s into diff {%s} of task {%s}\n",
1114  session->local_peer_idx,
1115  debug_str_element (element),
1116  debug_str_diff_key (&setop->output_diff),
1117  debug_str_task_key (&task->key));
1118 #endif
1119  }
1120  if (NULL != output_rfn)
1121  {
1122  rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element);
1123 #ifdef GNUNET_EXTRA_LOGGING
1125  "P%u: adding element %s into rfn {%s} of task {%s}\n",
1126  session->local_peer_idx,
1127  debug_str_element (element),
1128  debug_str_rfn_key (&setop->output_rfn),
1129  debug_str_task_key (&task->key));
1130 #endif
1131  }
1132  // XXX: add result to structures in task
1133  break;
1134 
1136  GNUNET_assert (NULL != consensus_element);
1137  if (GNUNET_YES == setop->do_not_remove)
1138  break;
1139  if (CONSENSUS_MARKER_CONTESTED == consensus_element->marker)
1140  break;
1142  "Removing element in Task {%s}\n",
1143  debug_str_task_key (&task->key));
1144  if (NULL != output_set)
1145  {
1146  // FIXME: record pending adds, use callback
1147  GNUNET_SET_remove_element (output_set->h,
1148  element,
1149  NULL,
1150  NULL);
1151 #ifdef GNUNET_EXTRA_LOGGING
1153  "P%u: removing element %s from set {%s} of task {%s}\n",
1154  session->local_peer_idx,
1155  debug_str_element (element),
1156  debug_str_set_key (&setop->output_set),
1157  debug_str_task_key (&task->key));
1158 #endif
1159  }
1160  if (NULL != output_diff)
1161  {
1162  diff_insert (output_diff, -1, element);
1163 #ifdef GNUNET_EXTRA_LOGGING
1165  "P%u: removing element %s from diff {%s} of task {%s}\n",
1166  session->local_peer_idx,
1167  debug_str_element (element),
1168  debug_str_diff_key (&setop->output_diff),
1169  debug_str_task_key (&task->key));
1170 #endif
1171  }
1172  if (NULL != output_rfn)
1173  {
1174  rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element);
1175 #ifdef GNUNET_EXTRA_LOGGING
1177  "P%u: removing element %s from rfn {%s} of task {%s}\n",
1178  session->local_peer_idx,
1179  debug_str_element (element),
1180  debug_str_rfn_key (&setop->output_rfn),
1181  debug_str_task_key (&task->key));
1182 #endif
1183  }
1184  break;
1185 
1187  // XXX: check first if any changes to the underlying
1188  // set are still pending
1190  "P%u: Finishing setop in Task {%s} (%u/%u)\n",
1191  session->local_peer_idx,
1192  debug_str_task_key (&task->key),
1193  (unsigned int) task->step->finished_tasks,
1194  (unsigned int) task->step->tasks_len);
1195  if (NULL != output_rfn)
1196  {
1197  rfn_commit (output_rfn, task_other_peer (task));
1198  }
1199  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1200  {
1201  session->first_size = current_size;
1202  }
1203  finish_task (task);
1204  break;
1205 
1207  // XXX: cleanup
1208  GNUNET_break_op (0);
1209  finish_task (task);
1210  return;
1211 
1212  default:
1213  /* not reached */
1214  GNUNET_assert (0);
1215  }
1216 }
uint64_t first_size
Our set size from the first round.
Vote that an element should be removed.
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, const struct RfnKey *key)
static int cmp_uint64_t(const void *pa, const void *pb)
int GNUNET_SET_remove_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Remove an element to the given set.
Definition: set_api.c:734
Weighted diff.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
Consensus element, either marker or payload.
Element should be added to the result set of the remote peer, i.e.
static void rfn_contest(struct ReferendumEntry *rfn, uint16_t contested_peer)
enum RfnKind rfn_kind
Element should be added to the result set of the local peer, i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
unsigned int tasks_len
Success, all elements have been sent (and received).
const void * data
Actual data of the element.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
The other peer refused to to the operation with us, or something went wrong.
static void diff_insert(struct DiffEntry *diff, int weight, const struct GNUNET_SET_Element *element)
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, const struct DiffKey *key)
uint64_t lower_bound
Bounded Eppstein lower bound.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static uint16_t task_other_peer(struct TaskEntry *task)
enum DiffKind diff_kind
struct TaskKey key
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
struct DiffKey output_diff
A consensus session consists of one local client and the remote authorities.
uint8_t marker
Is this a marker element?
Vote that an element should be added.
unsigned int finished_tasks
Block type for consensus elements.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
static void rfn_commit(struct ReferendumEntry *rfn, uint16_t commit_peer)
struct RfnKey output_rfn
union TaskFuncCls cls
struct SetKey output_set
enum SetKind set_kind
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ commit_set()

static void commit_set ( struct ConsensusSession session,
struct TaskEntry task 
)
static

Commit the appropriate set for a task.

Definition at line 1384 of file gnunet-service-consensus.c.

References ConsensusSizeElement::ce, ConsensusStuffedElement::ce, TaskEntry::cls, CONSENSUS_MARKER_CONTESTED, CONSENSUS_MARKER_SIZE, GNUNET_SET_Element::data, GNUNET_SET_Element::element_type, finish_task(), ConsensusSession::first_size, GNUNET_assert, GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_create_random(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_ERROR_TYPE_DEBUG, GNUNET_htonll(), GNUNET_log, GNUNET_NO, GNUNET_SET_add_element(), GNUNET_SET_commit(), GNUNET_SET_create(), GNUNET_SET_destroy(), GNUNET_SET_operation_cancel(), GNUNET_SET_OPERATION_UNION, GNUNET_STATISTICS_set(), GNUNET_STATISTICS_update(), GNUNET_YES, SetOpCls::input_set, TaskEntry::key, TaskKey::kind, ConsensusSession::local_peer_idx, lookup_set(), ConsensusElement::marker, SetOpCls::op, ConsensusElement::payload_type, ConsensusSession::peers_blacklisted, PHASE_KIND_ALL_TO_ALL, PHASE_KIND_ALL_TO_ALL_2, PHASE_KIND_GRADECAST_ECHO, PHASE_KIND_GRADECAST_LEADER, ConsensusStuffedElement::rand, ConsensusSizeElement::sender_index, SET_KIND_CURRENT, TaskFuncCls::setop, ConsensusSizeElement::size, GNUNET_SET_Element::size, task_other_peer(), and SetOpCls::transceive_contested.

Referenced by set_listen_cb(), and task_start_reconcile().

1386 {
1387  struct SetEntry *set;
1388  struct SetOpCls *setop = &task->cls.setop;
1389 
1390  GNUNET_assert (NULL != setop->op);
1391  set = lookup_set (session, &setop->input_set);
1392  GNUNET_assert (NULL != set);
1393 
1394  if ((GNUNET_YES == setop->transceive_contested) && (GNUNET_YES ==
1395  set->is_contested))
1396  {
1397  struct GNUNET_SET_Element element;
1398  struct ConsensusElement ce = { 0 };
1399 
1401  element.data = &ce;
1402  element.size = sizeof(struct ConsensusElement);
1403  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1404  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1405  }
1406 
1407  if (PHASE_KIND_ALL_TO_ALL_2 == task->key.kind)
1408  {
1409  struct GNUNET_SET_Element element;
1410  struct ConsensusSizeElement cse = {
1411  .size = 0,
1412  .sender_index = 0
1413  };
1414  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inserting size marker\n");
1416  cse.size = GNUNET_htonll (session->first_size);
1417  cse.sender_index = session->local_peer_idx;
1418  element.data = &cse;
1419  element.size = sizeof(struct ConsensusSizeElement);
1420  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1421  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1422  }
1423 
1424 #ifdef EVIL
1425  {
1426  struct Evilness evil;
1427 
1428  get_evilness (session, &evil);
1429  if (EVILNESS_NONE != evil.type)
1430  {
1431  /* Useful for evaluation */
1433  "is evil",
1434  1,
1435  GNUNET_NO);
1436  }
1437  switch (evil.type)
1438  {
1439  case EVILNESS_CRAM_ALL:
1440  case EVILNESS_CRAM_LEAD:
1441  case EVILNESS_CRAM_ECHO:
1442  /* We're not cramming elements in the
1443  all-to-all round, since that would just
1444  add more elements to the result set, but
1445  wouldn't test robustness. */
1446  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1447  {
1448  GNUNET_SET_commit (setop->op, set->h);
1449  break;
1450  }
1451  if ((EVILNESS_CRAM_LEAD == evil.type) &&
1452  ((PHASE_KIND_GRADECAST_LEADER != task->key.kind) ||
1453  (SET_KIND_CURRENT != set->key.set_kind) ))
1454  {
1455  GNUNET_SET_commit (setop->op, set->h);
1456  break;
1457  }
1458  if ((EVILNESS_CRAM_ECHO == evil.type) && (PHASE_KIND_GRADECAST_ECHO !=
1459  task->key.kind))
1460  {
1461  GNUNET_SET_commit (setop->op, set->h);
1462  break;
1463  }
1464  for (unsigned int i = 0; i < evil.num; i++)
1465  {
1466  struct GNUNET_SET_Element element;
1467  struct ConsensusStuffedElement se = {
1468  .ce.payload_type = 0,
1469  .ce.marker = 0,
1470  };
1471  element.data = &se;
1472  element.size = sizeof(struct ConsensusStuffedElement);
1473  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1474 
1475  if (EVILNESS_SUB_REPLACEMENT == evil.subtype)
1476  {
1477  /* Always generate a new element. */
1479  &se.rand);
1480  }
1481  else if (EVILNESS_SUB_NO_REPLACEMENT == evil.subtype)
1482  {
1483  /* Always cram the same elements, derived from counter. */
1484  GNUNET_CRYPTO_hash (&i, sizeof(i), &se.rand);
1485  }
1486  else
1487  {
1488  GNUNET_assert (0);
1489  }
1490  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1491 #ifdef GNUNET_EXTRA_LOGGING
1493  "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n",
1494  session->local_peer_idx,
1495  debug_str_element (&element),
1496  debug_str_set_key (&setop->input_set),
1497  debug_str_task_key (&task->key));
1498 #endif
1499  }
1501  "# stuffed elements",
1502  evil.num,
1503  GNUNET_NO);
1504  GNUNET_SET_commit (setop->op, set->h);
1505  break;
1506 
1507  case EVILNESS_SLACK:
1509  "P%u: evil peer: slacking\n",
1510  (unsigned int) session->local_peer_idx);
1511 
1512  /* Do nothing. */
1513  case EVILNESS_SLACK_A2A:
1514  if ((PHASE_KIND_ALL_TO_ALL_2 == task->key.kind) ||
1515  (PHASE_KIND_ALL_TO_ALL == task->key.kind))
1516  {
1517  struct GNUNET_SET_Handle *empty_set;
1519  GNUNET_SET_commit (setop->op, empty_set);
1520  GNUNET_SET_destroy (empty_set);
1521  }
1522  else
1523  {
1524  GNUNET_SET_commit (setop->op,
1525  set->h);
1526  }
1527  break;
1528 
1529  case EVILNESS_NONE:
1530  GNUNET_SET_commit (setop->op,
1531  set->h);
1532  break;
1533  }
1534  }
1535 #else
1536  if (GNUNET_NO == session->peers_blacklisted[task_other_peer (task)])
1537  {
1538  GNUNET_SET_commit (setop->op, set->h);
1539  }
1540  else
1541  {
1542  /* For our testcases, we don't want the blacklisted
1543  peers to wait. */
1545  setop->op = NULL;
1546  finish_task (task);
1547  }
1548 #endif
1549 }
uint64_t first_size
Our set size from the first round.
struct GNUNET_STATISTICS_Handle * statistics
Statistics handle.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
Consensus element, either marker or payload.
uint16_t payload_type
Payload element_type, only valid if this is not a marker element.
Element stored in a set.
struct GNUNET_SET_Handle * GNUNET_SET_create(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op)
Create an empty set, supporting the specified operation.
Definition: set_api.c:657
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void finish_task(struct TaskEntry *task)
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:772
struct ConsensusElement ce
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:144
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
static uint16_t task_other_peer(struct TaskEntry *task)
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of the consensus service.
struct SetKey input_set
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
Opaque handle to a set.
Definition: set_api.c:49
struct TaskKey key
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:36
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
struct GNUNET_HashCode rand
int GNUNET_SET_commit(struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set)
Commit a set to be used with a set operation.
Definition: set_api.c:1128
uint8_t marker
Is this a marker element?
Block type for consensus elements.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:516
struct GNUNET_SET_OperationHandle * op
union TaskFuncCls cls
struct ConsensusElement ce
Set union, return all elements that are in at least one of the sets.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_diff()

static void put_diff ( struct ConsensusSession session,
struct DiffEntry diff 
)
static

Definition at line 1553 of file gnunet-service-consensus.c.

References ConsensusSession::diffmap, GNUNET_assert, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_OK, and DiffEntry::key.

Referenced by task_start_reconcile().

1555 {
1556  struct GNUNET_HashCode hash;
1557 
1558  GNUNET_CRYPTO_hash (&diff->key,
1559  sizeof(struct DiffKey),
1560  &hash);
1563  &hash,
1564  diff,
1566 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
struct DiffKey key
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_CONTAINER_MultiHashMap * diffmap
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_set()

static void put_set ( struct ConsensusSession session,
struct SetEntry set 
)
static

Definition at line 1570 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SYSERR, and ConsensusSession::setmap.

Referenced by handle_client_join(), set_copy_cb(), and task_start_eval_echo().

1572 {
1573  struct GNUNET_HashCode hash;
1574 
1575  GNUNET_assert (NULL != set->h);
1577  "Putting set %s\n",
1578  debug_str_set_key (&set->key));
1579  GNUNET_CRYPTO_hash (&set->key,
1580  sizeof(struct SetKey),
1581  &hash);
1584  &hash,
1585  set,
1587 }
If a value with the given key exists, replace it.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct GNUNET_CONTAINER_MultiHashMap * setmap
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_log(kind,...)
struct SetKey key
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_rfn()

static void put_rfn ( struct ConsensusSession session,
struct ReferendumEntry rfn 
)
static

Definition at line 1591 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_OK, ReferendumEntry::key, and ConsensusSession::rfnmap.

Referenced by task_start_grade(), and task_start_reconcile().

1593 {
1594  struct GNUNET_HashCode hash;
1595 
1596  GNUNET_CRYPTO_hash (&rfn->key, sizeof(struct RfnKey), &hash);
1599  &hash,
1600  rfn,
1602 }
struct GNUNET_CONTAINER_MultiHashMap * rfnmap
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_cancel_reconcile()

static void task_cancel_reconcile ( struct TaskEntry task)
static

Definition at line 1606 of file gnunet-service-consensus.c.

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

1607 {
1608  /* not implemented yet */
1609  GNUNET_assert (0);
1610 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Here is the caller graph for this function:

◆ apply_diff_to_rfn()

static void apply_diff_to_rfn ( struct DiffEntry diff,
struct ReferendumEntry rfn,
uint16_t  voting_peer,
uint16_t  num_peers 
)
static

Definition at line 1614 of file gnunet-service-consensus.c.

References DiffEntry::changes, GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_YES, rfn_vote(), VOTE_ADD, and VOTE_REMOVE.

Referenced by task_start_grade().

1618 {
1620  struct DiffElementInfo *di;
1621 
1623 
1624  while (GNUNET_YES ==
1626  NULL,
1627  (const void **) &di))
1628  {
1629  if (di->weight > 0)
1630  {
1631  rfn_vote (rfn, voting_peer, VOTE_ADD, di->element);
1632  }
1633  if (di->weight < 0)
1634  {
1635  rfn_vote (rfn, voting_peer, VOTE_REMOVE, di->element);
1636  }
1637  }
1638 
1640 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct GNUNET_CONTAINER_MultiHashMap * changes
Vote that an element should be added.
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_create()

static struct DiffEntry* diff_create ( void  )
static

Definition at line 1644 of file gnunet-service-consensus.c.

References DiffEntry::changes, diff_insert(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_new, GNUNET_NO, and GNUNET_YES.

Referenced by task_start_reconcile().

1645 {
1646  struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1647 
1649  GNUNET_NO);
1650 
1651  return d;
1652 }
Weighted diff.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_CONTAINER_MultiHashMap * changes
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_create()

struct ReferendumEntry* rfn_create ( uint16_t  size)

Definition at line 1698 of file gnunet-service-consensus.c.

References DiffEntry::changes, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_free, GNUNET_new, GNUNET_new_array, GNUNET_NO, ReferendumEntry::num_peers, ReferendumEntry::peer_commited, ReferendumEntry::peer_contested, ReferendumEntry::rfn_elements, and size.

Referenced by task_start_grade(), and task_start_reconcile().

1699 {
1700  struct ReferendumEntry *rfn;
1701 
1702  rfn = GNUNET_new (struct ReferendumEntry);
1704  rfn->peer_commited = GNUNET_new_array (size, int);
1705  rfn->peer_contested = GNUNET_new_array (size, int);
1706  rfn->num_peers = size;
1707 
1708  return rfn;
1709 }
int * peer_contested
Contestation state of the peer.
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_majority()

static void rfn_majority ( const struct ReferendumEntry rfn,
const struct RfnElementInfo ri,
uint16_t *  ret_majority,
enum ReferendumVote ret_vote 
)
static

For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that voted for this outcome.

Definition at line 1730 of file gnunet-service-consensus.c.

References RfnElementInfo::element, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, ReferendumEntry::key, ReferendumEntry::num_peers, ReferendumEntry::peer_commited, RfnElementInfo::proposal, VOTE_STAY, and RfnElementInfo::votes.

Referenced by task_start_apply_round(), task_start_eval_echo(), and task_start_grade().

1734 {
1735  uint16_t votes_yes = 0;
1736  uint16_t num_commited = 0;
1737 
1739  "Computing rfn majority for element %s of rfn {%s}\n",
1740  debug_str_element (ri->element),
1741  debug_str_rfn_key (&rfn->key));
1742 
1743  for (uint16_t i = 0; i < rfn->num_peers; i++)
1744  {
1745  if (GNUNET_NO == rfn->peer_commited[i])
1746  continue;
1747  num_commited++;
1748 
1749  if (GNUNET_YES == ri->votes[i])
1750  votes_yes++;
1751  }
1752 
1753  if (votes_yes > (num_commited) / 2)
1754  {
1755  *ret_vote = ri->proposal;
1756  *ret_majority = votes_yes;
1757  }
1758  else
1759  {
1760  *ret_vote = VOTE_STAY;
1761  *ret_majority = num_commited - votes_yes;
1762  }
1763 }
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
Vote that nothing should change.
const struct GNUNET_SET_Element * element
#define GNUNET_log(kind,...)
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
int * votes
GNUNET_YES if the peer votes for the proposal.
Here is the caller graph for this function:

◆ set_copy_cb()

static void set_copy_cb ( void *  cls,
struct GNUNET_SET_Handle copy 
)
static

Definition at line 1774 of file gnunet-service-consensus.c.

References SetCopyCls::dst_set_key, GNUNET_CONTAINER_DLL_insert, GNUNET_free, GNUNET_new, SetHandle::h, put_set(), Step::session, ConsensusSession::set_handles_head, ConsensusSession::set_handles_tail, sh, TaskEntry::start, TaskEntry::step, and SetCopyCls::task.

Referenced by create_set_copy_for_task().

1776 {
1777  struct SetCopyCls *scc = cls;
1778  struct TaskEntry *task = scc->task;
1779  struct SetKey dst_set_key = scc->dst_set_key;
1780  struct SetEntry *set;
1781  struct SetHandle *sh = GNUNET_new (struct SetHandle);
1782 
1783  sh->h = copy;
1785  task->step->session->set_handles_tail,
1786  sh);
1787 
1788  GNUNET_free (scc);
1789  set = GNUNET_new (struct SetEntry);
1790  set->h = copy;
1791  set->key = dst_set_key;
1792  put_set (task->step->session, set);
1793 
1794  task->start (task);
1795 }
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct SetHandle * set_handles_head
struct ConsensusSession * session
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct SetHandle * set_handles_tail
static struct SolverHandle * sh
struct SetKey dst_set_key
struct GNUNET_SET_Handle * h
struct Step * step
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
struct TaskEntry * task
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_set_copy_for_task()

static void create_set_copy_for_task ( struct TaskEntry task,
struct SetKey src_set_key,
struct SetKey dst_set_key 
)
static

Call the start function of the given task again after we created a copy of the given set.

Definition at line 1803 of file gnunet-service-consensus.c.

References SetCopyCls::dst_set_key, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_SET_copy_lazy(), SetEntry::h, TaskEntry::key, lookup_set(), Step::session, set_copy_cb(), TaskEntry::step, and SetCopyCls::task.

Referenced by task_start_apply_round(), task_start_eval_echo(), and task_start_reconcile().

1806 {
1807  struct SetEntry *src_set;
1808  struct SetCopyCls *scc = GNUNET_new (struct SetCopyCls);
1809 
1811  "Copying set {%s} to {%s} for task {%s}\n",
1812  debug_str_set_key (src_set_key),
1813  debug_str_set_key (dst_set_key),
1814  debug_str_task_key (&task->key));
1815 
1816  scc->task = task;
1817  scc->dst_set_key = *dst_set_key;
1818  src_set = lookup_set (task->step->session, src_set_key);
1819  GNUNET_assert (NULL != src_set);
1820  GNUNET_SET_copy_lazy (src_set->h,
1821  set_copy_cb,
1822  scc);
1823 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1194
static void set_copy_cb(void *cls, struct GNUNET_SET_Handle *copy)
struct SetKey dst_set_key
struct TaskKey key
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
struct Step * step
#define GNUNET_log(kind,...)
struct TaskEntry * task
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_mutation_done()

static void set_mutation_done ( void *  cls)
static

Definition at line 1837 of file gnunet-service-consensus.c.

References finish_task(), GNUNET_assert, GNUNET_free, SetMutationProgressCls::num_pending, pc, and SetMutationProgressCls::task.

Referenced by task_start_apply_round(), and task_start_eval_echo().

1838 {
1839  struct SetMutationProgressCls *pc = cls;
1840 
1841  GNUNET_assert (pc->num_pending > 0);
1842 
1843  pc->num_pending--;
1844 
1845  if (0 == pc->num_pending)
1846  {
1847  struct TaskEntry *task = pc->task;
1848  GNUNET_free (pc);
1849  finish_task (task);
1850  }
1851 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void finish_task(struct TaskEntry *task)
struct TaskEntry * task
Task to finish once all changes are through.
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_finish_step_early()

static void try_finish_step_early ( struct Step step)
static

Definition at line 1855 of file gnunet-service-consensus.c.

References Step::debug_name, Step::early_finishable, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, Step::is_finished, Step::is_running, Step::pending_prereq, run_ready_steps(), Step::session, Step::subordinates, and Step::subordinates_len.

Referenced by task_start_apply_round().

1856 {
1857  if (GNUNET_YES == step->is_running)
1858  return;
1859  if (GNUNET_YES == step->is_finished)
1860  return;
1861  if (GNUNET_NO == step->early_finishable)
1862  return;
1863 
1864  step->is_finished = GNUNET_YES;
1865 
1866 #ifdef GNUNET_EXTRA_LOGGING
1868  "Finishing step `%s' early.\n",
1869  step->debug_name);
1870 #endif
1871 
1872  for (unsigned int i = 0; i < step->subordinates_len; i++)
1873  {
1874  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1875  step->subordinates[i]->pending_prereq--;
1876 #ifdef GNUNET_EXTRA_LOGGING
1878  "Decreased pending_prereq to %u for step `%s'.\n",
1879  (unsigned int) step->subordinates[i]->pending_prereq,
1880  step->subordinates[i]->debug_name);
1881 #endif
1883  }
1884 
1885  // XXX: maybe schedule as task to avoid recursion?
1886  run_ready_steps (step->session);
1887 }
static void try_finish_step_early(struct Step *step)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
size_t pending_prereq
Counter for the prerequisites of this step.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
int early_finishable
When we&#39;re doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
unsigned int is_finished
static void run_ready_steps(struct ConsensusSession *session)
#define GNUNET_log(kind,...)
unsigned int is_running
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_step()

static void finish_step ( struct Step step)
static

Definition at line 1891 of file gnunet-service-consensus.c.

References Step::debug_name, Step::finished_tasks, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, Step::is_finished, Step::is_running, Step::pending_prereq, run_ready_steps(), Step::session, Step::subordinates, Step::subordinates_len, and Step::tasks_len.

Referenced by finish_task(), and run_ready_steps().

1892 {
1893  GNUNET_assert (step->finished_tasks == step->tasks_len);
1894  GNUNET_assert (GNUNET_YES == step->is_running);
1895  GNUNET_assert (GNUNET_NO == step->is_finished);
1896 
1897 #ifdef GNUNET_EXTRA_LOGGING
1899  "All tasks of step `%s' with %u subordinates finished.\n",
1900  step->debug_name,
1901  step->subordinates_len);
1902 #endif
1903 
1904  for (unsigned int i = 0; i < step->subordinates_len; i++)
1905  {
1906  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1907  step->subordinates[i]->pending_prereq--;
1908 #ifdef GNUNET_EXTRA_LOGGING
1910  "Decreased pending_prereq to %u for step `%s'.\n",
1911  (unsigned int) step->subordinates[i]->pending_prereq,
1912  step->subordinates[i]->debug_name);
1913 #endif
1914  }
1915 
1916  step->is_finished = GNUNET_YES;
1917 
1918  // XXX: maybe schedule as task to avoid recursion?
1919  run_ready_steps (step->session);
1920 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
unsigned int tasks_len
size_t pending_prereq
Counter for the prerequisites of this step.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
unsigned int is_finished
static void run_ready_steps(struct ConsensusSession *session)
unsigned int finished_tasks
#define GNUNET_log(kind,...)
unsigned int is_running
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_apply_round()

static void task_start_apply_round ( struct TaskEntry task)
static

Apply the result from one round of gradecasts (i.e.

every peer should have gradecasted) to the peer's current set.

Parameters
taskthe task with context information

Definition at line 1930 of file gnunet-service-consensus.c.

References create_set_copy_for_task(), ConsensusSession::early_stopping, EARLY_STOPPING_DONE, EARLY_STOPPING_NONE, EARLY_STOPPING_ONE_MORE, finish_task(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_SET_add_element(), GNUNET_SET_remove_element(), GNUNET_YES, SetEntry::h, TaskEntry::key, ConsensusSession::local_peer_idx, lookup_rfn(), lookup_set(), Step::next, ConsensusSession::num_peers, SetMutationProgressCls::num_pending, TaskKey::repetition, ReferendumEntry::rfn_elements, RFN_KIND_GRADECAST_RESULT, rfn_majority(), Step::session, SET_KIND_CURRENT, set_mutation_done(), TaskEntry::step, ConsensusSession::steps_head, SetMutationProgressCls::task, try_finish_step_early(), VOTE_ADD, VOTE_REMOVE, and VOTE_STAY.

Referenced by construct_task_graph().

1931 {
1932  struct ConsensusSession *session = task->step->session;
1933  struct SetKey sk_in;
1934  struct SetKey sk_out;
1935  struct RfnKey rk_in;
1936  struct SetEntry *set_out;
1937  struct ReferendumEntry *rfn_in;
1939  struct RfnElementInfo *ri;
1940  struct SetMutationProgressCls *progress_cls;
1941  uint16_t worst_majority = UINT16_MAX;
1942 
1943  sk_in = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition };
1944  rk_in = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1945  sk_out = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition + 1 };
1946 
1947  set_out = lookup_set (session, &sk_out);
1948  if (NULL == set_out)
1949  {
1951  &sk_in,
1952  &sk_out);
1953  return;
1954  }
1955 
1956  rfn_in = lookup_rfn (session, &rk_in);
1957  GNUNET_assert (NULL != rfn_in);
1958 
1959  progress_cls = GNUNET_new (struct SetMutationProgressCls);
1960  progress_cls->task = task;
1961 
1963 
1964  while (GNUNET_YES ==
1966  NULL,
1967  (const void **) &ri))
1968  {
1969  uint16_t majority_num;
1970  enum ReferendumVote majority_vote;
1971 
1972  rfn_majority (rfn_in, ri, &majority_num, &majority_vote);
1973 
1974  if (worst_majority > majority_num)
1975  worst_majority = majority_num;
1976 
1977  switch (majority_vote)
1978  {
1979  case VOTE_ADD:
1980  progress_cls->num_pending++;
1982  GNUNET_SET_add_element (set_out->h,
1983  ri->element,
1985  progress_cls));
1987  "P%u: apply round: adding element %s with %u-majority.\n",
1988  session->local_peer_idx,
1989  debug_str_element (ri->element), majority_num);
1990  break;
1991 
1992  case VOTE_REMOVE:
1993  progress_cls->num_pending++;
1995  GNUNET_SET_remove_element (set_out->h,
1996  ri->element,
1998  progress_cls));
2000  "P%u: apply round: deleting element %s with %u-majority.\n",
2001  session->local_peer_idx,
2002  debug_str_element (ri->element), majority_num);
2003  break;
2004 
2005  case VOTE_STAY:
2007  "P%u: apply round: keeping element %s with %u-majority.\n",
2008  session->local_peer_idx,
2009  debug_str_element (ri->element), majority_num);
2010  // do nothing
2011  break;
2012 
2013  default:
2014  GNUNET_assert (0);
2015  break;
2016  }
2017  }
2018 
2019  if (0 == progress_cls->num_pending)
2020  {
2021  // call closure right now, no pending ops
2022  GNUNET_free (progress_cls);
2023  finish_task (task);
2024  }
2025 
2026  {
2027  uint16_t thresh = (session->num_peers / 3) * 2;
2028 
2029  if (worst_majority >= thresh)
2030  {
2031  switch (session->early_stopping)
2032  {
2033  case EARLY_STOPPING_NONE:
2036  "P%u: Stopping early (after one more superround)\n",
2037  session->local_peer_idx);
2038  break;
2039 
2042  "P%u: finishing steps due to early finish\n",
2043  session->local_peer_idx);
2045  {
2046  struct Step *step;
2047  for (step = session->steps_head; NULL != step; step = step->next)
2048  try_finish_step_early (step);
2049  }
2050  break;
2051 
2052  case EARLY_STOPPING_DONE:
2053  /* We shouldn't be here anymore after early stopping */
2054  GNUNET_break (0);
2055  break;
2056 
2057  default:
2058  GNUNET_assert (0);
2059  break;
2060  }
2061  }
2062  else if (EARLY_STOPPING_NONE != session->early_stopping)
2063  {
2064  // Our assumption about the number of bad peers
2065  // has been broken.
2066  GNUNET_break_op (0);
2067  }
2068  else
2069  {
2071  "P%u: NOT finishing early (majority not good enough)\n",
2072  session->local_peer_idx);
2073  }
2074  }
2076 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, const struct RfnKey *key)
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
int GNUNET_SET_remove_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Remove an element to the given set.
Definition: set_api.c:734
static void try_finish_step_early(struct Step *step)
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct Step * next
All steps of one session are in a linked list for easier deallocation.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct TaskEntry * task
Task to finish once all changes are through.
Vote that nothing should change.
struct TaskKey key
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
static void set_mutation_done(void *cls)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
int early_stopping
State of our early stopping scheme.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_grade()

static void task_start_grade ( struct TaskEntry task)
static

Definition at line 2080 of file gnunet-service-consensus.c.

References apply_diff_to_rfn(), DIFF_KIND_LEADER_PROPOSAL, finish_task(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_MIN, GNUNET_YES, TaskEntry::key, ReferendumEntry::key, TaskKey::leader, lookup_diff(), lookup_rfn(), num_peers, ConsensusSession::num_peers, ConsensusSession::peers_blacklisted, put_rfn(), TaskKey::repetition, rfn_commit(), rfn_create(), ReferendumEntry::rfn_elements, RFN_KIND_ECHO, RFN_KIND_GRADECAST_RESULT, rfn_majority(), rfn_noncontested(), rfn_vote(), Step::session, TaskEntry::step, VOTE_ADD, VOTE_REMOVE, and VOTE_STAY.

Referenced by construct_task_graph_gradecast().

2081 {
2082  struct ConsensusSession *session = task->step->session;
2083  struct ReferendumEntry *output_rfn;
2084  struct ReferendumEntry *input_rfn;
2085  struct DiffEntry *input_diff;
2086  struct RfnKey rfn_key;
2087  struct DiffKey diff_key;
2089  struct RfnElementInfo *ri;
2090  unsigned int gradecast_confidence = 2;
2091 
2092  rfn_key = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
2093  output_rfn = lookup_rfn (session, &rfn_key);
2094  if (NULL == output_rfn)
2095  {
2096  output_rfn = rfn_create (session->num_peers);
2097  output_rfn->key = rfn_key;
2098  put_rfn (session, output_rfn);
2099  }
2100 
2101  diff_key = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, task->key.repetition,
2102  task->key.leader };
2103  input_diff = lookup_diff (session, &diff_key);
2104  GNUNET_assert (NULL != input_diff);
2105 
2106  rfn_key = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2107  task->key.leader };
2108  input_rfn = lookup_rfn (session, &rfn_key);
2109  GNUNET_assert (NULL != input_rfn);
2110 
2112  input_rfn->rfn_elements);
2113 
2114  apply_diff_to_rfn (input_diff, output_rfn, task->key.leader,
2115  session->num_peers);
2116 
2117  while (GNUNET_YES ==
2119  NULL,
2120  (const void **) &ri))
2121  {
2122  uint16_t majority_num;
2123  enum ReferendumVote majority_vote;
2124 
2125  // XXX: we need contested votes and non-contested votes here
2126  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2127 
2128  if (majority_num <= session->num_peers / 3)
2129  majority_vote = VOTE_REMOVE;
2130 
2131  switch (majority_vote)
2132  {
2133  case VOTE_STAY:
2134  break;
2135 
2136  case VOTE_ADD:
2137  rfn_vote (output_rfn, task->key.leader, VOTE_ADD, ri->element);
2138  break;
2139 
2140  case VOTE_REMOVE:
2141  rfn_vote (output_rfn, task->key.leader, VOTE_REMOVE, ri->element);
2142  break;
2143 
2144  default:
2145  GNUNET_assert (0);
2146  break;
2147  }
2148  }
2150 
2151  {
2152  uint16_t noncontested;
2153  noncontested = rfn_noncontested (input_rfn);
2154  if (noncontested < (session->num_peers / 3) * 2)
2155  {
2156  gradecast_confidence = GNUNET_MIN (1, gradecast_confidence);
2157  }
2158  if (noncontested < (session->num_peers / 3) + 1)
2159  {
2160  gradecast_confidence = 0;
2161  }
2162  }
2163 
2164  if (gradecast_confidence >= 1)
2165  rfn_commit (output_rfn, task->key.leader);
2166 
2167  if (gradecast_confidence <= 1)
2168  session->peers_blacklisted[task->key.leader] = GNUNET_YES;
2169 
2170  finish_task (task);
2171 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, const struct RfnKey *key)
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
Weighted diff.
static void apply_diff_to_rfn(struct DiffEntry *diff, struct ReferendumEntry *rfn, uint16_t voting_peer, uint16_t num_peers)
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct ReferendumEntry * rfn_create(uint16_t size)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, const struct DiffKey *key)
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:93
Vote that nothing should change.
struct TaskKey key
static uint16_t rfn_noncontested(struct ReferendumEntry *rfn)
static unsigned int num_peers
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
int16_t leader
Leader in the gradecast phase.
struct Step * step
static void rfn_commit(struct ReferendumEntry *rfn, uint16_t commit_peer)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_reconcile()

static void task_start_reconcile ( struct TaskEntry task)
static

Definition at line 2175 of file gnunet-service-consensus.c.

References TaskEntry::cls, commit_set(), create_set_copy_for_task(), diff_create(), DiffKey::diff_kind, DIFF_KIND_NONE, finish_task(), ConsensusSession::global_id, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT, GNUNET_SET_OPTION_BYZANTINE, GNUNET_SET_OPTION_END, GNUNET_SET_prepare(), GNUNET_SET_RESULT_SYMMETRIC, SetEntry::h, GNUNET_CONSENSUS_RoundContextMessage::header, SetOpCls::input_set, GNUNET_CONSENSUS_RoundContextMessage::is_contested, TaskEntry::key, ReferendumEntry::key, DiffEntry::key, GNUNET_CONSENSUS_RoundContextMessage::kind, TaskKey::kind, GNUNET_CONSENSUS_RoundContextMessage::leader, TaskKey::leader, ConsensusSession::local_peer_idx, lookup_diff(), lookup_rfn(), lookup_set(), ConsensusSession::lower_bound, ConsensusSession::num_peers, SetOpCls::op, SetOpCls::output_diff, SetOpCls::output_rfn, SetOpCls::output_set, GNUNET_CONSENSUS_RoundContextMessage::peer1, TaskKey::peer1, GNUNET_CONSENSUS_RoundContextMessage::peer2, TaskKey::peer2, ConsensusSession::peers, put_diff(), put_rfn(), GNUNET_CONSENSUS_RoundContextMessage::repetition, TaskKey::repetition, rfn_create(), RfnKey::rfn_kind, RFN_KIND_NONE, Step::session, SetKey::set_kind, SET_KIND_NONE, set_result_cb(), TaskFuncCls::setop, GNUNET_MessageHeader::size, TaskEntry::step, and GNUNET_MessageHeader::type.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2176 {
2177  struct SetEntry *input;
2178  struct SetOpCls *setop = &task->cls.setop;
2179  struct ConsensusSession *session = task->step->session;
2180 
2181  input = lookup_set (session, &setop->input_set);
2182  GNUNET_assert (NULL != input);
2183  GNUNET_assert (NULL != input->h);
2184 
2185  /* We create the outputs for the operation here
2186  (rather than in the set operation callback)
2187  because we want something valid in there, even
2188  if the other peer doesn't talk to us */
2189 
2190  if (SET_KIND_NONE != setop->output_set.set_kind)
2191  {
2192  /* If we don't have an existing output set,
2193  we clone the input set. */
2194  if (NULL == lookup_set (session, &setop->output_set))
2195  {
2197  &setop->input_set,
2198  &setop->output_set);
2199  return;
2200  }
2201  }
2202 
2203  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
2204  {
2205  if (NULL == lookup_rfn (session, &setop->output_rfn))
2206  {
2207  struct ReferendumEntry *rfn;
2208 
2210  "P%u: output rfn <%s> missing, creating.\n",
2211  session->local_peer_idx,
2212  debug_str_rfn_key (&setop->output_rfn));
2213 
2214  rfn = rfn_create (session->num_peers);
2215  rfn->key = setop->output_rfn;
2216  put_rfn (session, rfn);
2217  }
2218  }
2219 
2220  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
2221  {
2222  if (NULL == lookup_diff (session, &setop->output_diff))
2223  {
2224  struct DiffEntry *diff;
2225 
2226  diff = diff_create ();
2227  diff->key = setop->output_diff;
2228  put_diff (session, diff);
2229  }
2230  }
2231 
2232  if ((task->key.peer1 == session->local_peer_idx) && (task->key.peer2 ==
2233  session->local_peer_idx))
2234  {
2235  /* XXX: mark the corresponding rfn as commited if necessary */
2236  finish_task (task);
2237  return;
2238  }
2239 
2240  if (task->key.peer1 == session->local_peer_idx)
2241  {
2243 
2245  "P%u: Looking up set {%s} to run remote union\n",
2246  session->local_peer_idx,
2247  debug_str_set_key (&setop->input_set));
2248  rcm.header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
2249  rcm.header.size = htons (sizeof(rcm));
2250  rcm.kind = htons (task->key.kind);
2251  rcm.peer1 = htons (task->key.peer1);
2252  rcm.peer2 = htons (task->key.peer2);
2253  rcm.leader = htons (task->key.leader);
2254  rcm.repetition = htons (task->key.repetition);
2255  rcm.is_contested = htons (0);
2256 
2257  GNUNET_assert (NULL == setop->op);
2259  "P%u: initiating set op with P%u, our set is %s\n",
2260  session->local_peer_idx,
2261  task->key.peer2,
2262  debug_str_set_key (&setop->input_set));
2263 
2264  struct GNUNET_SET_Option opts[] = {
2265  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2267  };
2268 
2269  // XXX: maybe this should be done while
2270  // setting up tasks alreays?
2271  setop->op = GNUNET_SET_prepare (&session->peers[task->key.peer2],
2272  &session->global_id,
2273  &rcm.header,
2275  opts,
2276  set_result_cb,
2277  task);
2278 
2279  commit_set (session, task);
2280  }
2281  else if (task->key.peer2 == session->local_peer_idx)
2282  {
2283  /* Wait for the other peer to contact us */
2284  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting set op with P%u\n",
2285  session->local_peer_idx, task->key.peer1);
2286 
2287  if (NULL != setop->op)
2288  {
2289  commit_set (session, task);
2290  }
2291  }
2292  else
2293  {
2294  /* We made an error while constructing the task graph. */
2295  GNUNET_assert (0);
2296  }
2297 }
#define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT
Provide context for a consensus round.
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, const struct RfnKey *key)
static struct DiffEntry * diff_create(void)
Weighted diff.
static void commit_set(struct ConsensusSession *session, struct TaskEntry *task)
Commit the appropriate set for a task.
int16_t repetition
Repetition of the gradecast phase.
static void put_diff(struct ConsensusSession *session, struct DiffEntry *diff)
struct ReferendumEntry * rfn_create(uint16_t size)
enum RfnKind rfn_kind
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: set_api.c:813
Sent as context message for set reconciliation.
struct GNUNET_PeerIdentity * peers
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, const struct DiffKey *key)
uint64_t lower_bound
Bounded Eppstein lower bound.
struct DiffKey key
struct SetKey input_set
Client gets notified of the required changes for both the local and the remote set.
enum DiffKind diff_kind
struct TaskKey key
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
struct GNUNET_HashCode global_id
Global consensus identification, computed from the session id and participating authorities.
Option for set operations.
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
struct DiffKey output_diff
A consensus session consists of one local client and the remote authorities.
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
int16_t leader
Leader in the gradecast phase.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
struct GNUNET_SET_OperationHandle * op
struct RfnKey output_rfn
union TaskFuncCls cls
struct SetKey output_set
enum SetKind set_kind
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_eval_echo()

static void task_start_eval_echo ( struct TaskEntry task)
static

Definition at line 2301 of file gnunet-service-consensus.c.

References create_set_copy_for_task(), finish_task(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_SET_add_element(), GNUNET_SET_remove_element(), GNUNET_YES, SetEntry::h, SetEntry::is_contested, SetEntry::key, TaskEntry::key, TaskKey::leader, lookup_rfn(), lookup_set(), num_peers, SetMutationProgressCls::num_pending, put_set(), TaskKey::repetition, ReferendumEntry::rfn_elements, RFN_KIND_ECHO, rfn_majority(), Step::session, SET_KIND_ECHO_RESULT, SET_KIND_LAST_GRADECAST, SET_KIND_LEADER_PROPOSAL, set_mutation_done(), TaskEntry::step, SetMutationProgressCls::task, VOTE_ADD, VOTE_REMOVE, and VOTE_STAY.

Referenced by construct_task_graph_gradecast().

2302 {
2304  struct ReferendumEntry *input_rfn;
2305  struct RfnElementInfo *ri;
2306  struct SetEntry *output_set;
2307  struct SetMutationProgressCls *progress_cls;
2308  struct ConsensusSession *session = task->step->session;
2309  struct SetKey sk_in;
2310  struct SetKey sk_out;
2311  struct RfnKey rk_in;
2312 
2313  sk_in = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, task->key.repetition,
2314  task->key.leader };
2315  sk_out = (struct SetKey) { SET_KIND_ECHO_RESULT, task->key.repetition,
2316  task->key.leader };
2317  output_set = lookup_set (session, &sk_out);
2318  if (NULL == output_set)
2319  {
2321  &sk_in,
2322  &sk_out);
2323  return;
2324  }
2325 
2326  {
2327  // FIXME: should be marked as a shallow copy, so
2328  // we can destroy everything correctly
2329  struct SetEntry *last_set = GNUNET_new (struct SetEntry);
2330 
2331  last_set->h = output_set->h;
2332  last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
2333  put_set (session, last_set);
2334  }
2335 
2337  "Evaluating referendum in Task {%s}\n",
2338  debug_str_task_key (&task->key));
2339 
2340  progress_cls = GNUNET_new (struct SetMutationProgressCls);
2341  progress_cls->task = task;
2342  rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2343  task->key.leader };
2344  input_rfn = lookup_rfn (session, &rk_in);
2345  GNUNET_assert (NULL != input_rfn);
2347  input_rfn->rfn_elements);
2348  GNUNET_assert (NULL != iter);
2349 
2350  while (GNUNET_YES ==
2352  NULL,
2353  (const void **) &ri))
2354  {
2355  enum ReferendumVote majority_vote;
2356  uint16_t majority_num;
2357 
2358  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2359 
2360  if (majority_num < session->num_peers / 3)
2361  {
2362  /* It is not the case that all nonfaulty peers
2363  echoed the same value. Since we're doing a set reconciliation, we
2364  can't simply send "nothing" for the value. Thus we mark our 'confirm'
2365  reconciliation as contested. Other peers might not know that the
2366  leader is faulty, thus we still re-distribute in the confirmation
2367  round. *///
2368  output_set->is_contested = GNUNET_YES;
2369  }
2370 
2371  switch (majority_vote)
2372  {
2373  case VOTE_ADD:
2374  progress_cls->num_pending++;
2376  GNUNET_SET_add_element (output_set->h,
2377  ri->element,
2379  progress_cls));
2380  break;
2381 
2382  case VOTE_REMOVE:
2383  progress_cls->num_pending++;
2385  GNUNET_SET_remove_element (output_set->h,
2386  ri->element,
2388  progress_cls));
2389  break;
2390 
2391  case VOTE_STAY:
2392  /* Nothing to do. */
2393  break;
2394 
2395  default:
2396  /* not reached */
2397  GNUNET_assert (0);
2398  }
2399  }
2400 
2402 
2403  if (0 == progress_cls->num_pending)
2404  {
2405  // call closure right now, no pending ops
2406  GNUNET_free (progress_cls);
2407  finish_task (task);
2408  }
2409 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, const struct RfnKey *key)
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
int GNUNET_SET_remove_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Remove an element to the given set.
Definition: set_api.c:734
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static void finish_task(struct TaskEntry *task)
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Last result set from a gradecast.
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
struct TaskEntry * task
Task to finish once all changes are through.
Vote that nothing should change.
struct TaskKey key
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
int is_contested
GNUNET_YES if the set resulted from applying a referendum with contested elements.
static unsigned int num_peers
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
int16_t leader
Leader in the gradecast phase.
struct Step * step
#define GNUNET_log(kind,...)
static void set_mutation_done(void *cls)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
struct SetKey key
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_finish()

static void task_start_finish ( struct TaskEntry task)
static

Definition at line 2413 of file gnunet-service-consensus.c.

References TaskEntry::cls, TaskFuncCls::finish, GNUNET_assert, GNUNET_SET_iterate(), SetEntry::h, FinishCls::input_set, lookup_set(), send_to_client_iter(), Step::session, and TaskEntry::step.

Referenced by construct_task_graph().

2414 {
2415  struct SetEntry *final_set;
2416  struct ConsensusSession *session = task->step->session;
2417 
2418  final_set = lookup_set (session,
2419  &task->cls.finish.input_set);
2420  GNUNET_assert (NULL != final_set);
2421  GNUNET_SET_iterate (final_set->h,
2423  task);
2424 }
struct FinishCls finish
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
struct SetKey input_set
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
A consensus session consists of one local client and the remote authorities.
struct Step * step
static int send_to_client_iter(void *cls, const struct GNUNET_SET_Element *element)
Send the final result set of the consensus to the client, element by element.
union TaskFuncCls cls
int GNUNET_SET_iterate(struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *iter_cls)
Iterate over all elements in the given set.
Definition: set_api.c:1172
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_task()

static void start_task ( struct ConsensusSession session,
struct TaskEntry task 
)
static

Definition at line 2428 of file gnunet-service-consensus.c.

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, TaskEntry::is_finished, TaskEntry::is_started, TaskEntry::key, ConsensusSession::local_peer_idx, and TaskEntry::start.

Referenced by run_ready_steps().

2430 {
2432  "P%u: starting task {%s}\n",
2433  session->local_peer_idx,
2434  debug_str_task_key (&task->key));
2435  GNUNET_assert (GNUNET_NO == task->is_started);
2436  GNUNET_assert (GNUNET_NO == task->is_finished);
2437  GNUNET_assert (NULL != task->start);
2438  task->start (task);
2439  task->is_started = GNUNET_YES;
2440 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct TaskKey key
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the caller graph for this function:

◆ get_peer_idx()

static int get_peer_idx ( const struct GNUNET_PeerIdentity peer,
const struct ConsensusSession session 
)
static

Search peer in the list of peers in session.

Parameters
peerpeer to find
sessionsession with peer
Returns
index of peer, -1 if peer is not in session

Definition at line 2514 of file gnunet-service-consensus.c.

References GNUNET_memcmp, ConsensusSession::num_peers, and ConsensusSession::peers.

Referenced by handle_client_join().

2516 {
2517  for (int i = 0; i < session->num_peers; i++)
2518  if (0 == GNUNET_memcmp (peer, &session->peers[i]))
2519  return i;
2520  return -1;
2521 }
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_PeerIdentity * peers
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
Here is the caller graph for this function:

◆ compute_global_id()

static void compute_global_id ( struct ConsensusSession session,
const struct GNUNET_HashCode local_session_id 
)
static

Compute a global, (hopefully) unique consensus session id, from the local id of the consensus session, and the identities of all participants.

Thus, if the local id of two consensus sessions coincide, but are not comprised of exactly the same peers, the global id will be different.

Parameters
sessionsession to generate the global id for
local_session_idlocal id of the consensus session

Definition at line 2534 of file gnunet-service-consensus.c.

References ConsensusSession::global_id, GNUNET_assert, GNUNET_CRYPTO_kdf(), GNUNET_YES, ConsensusSession::num_peers, ConsensusSession::peers, and salt.

Referenced by handle_client_join().

2536 {
2537  const char *salt = "gnunet-service-consensus/session_id";
2538 
2540  GNUNET_CRYPTO_kdf (&session->global_id,
2541  sizeof(struct GNUNET_HashCode),
2542  salt,
2543  strlen (salt),
2544  session->peers,
2545  session->num_peers * sizeof(struct
2547  local_session_id,
2548  sizeof(struct GNUNET_HashCode),
2549  NULL));
2550 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_PeerIdentity * peers
A 512-bit hashcode.
struct GNUNET_HashCode global_id
Global consensus identification, computed from the session id and participating authorities.
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
The identity of the host (wraps the signing key of the peer).
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:90
Here is the call graph for this function:
Here is the caller graph for this function:

◆ peer_id_cmp()

static int peer_id_cmp ( const void *  h1,
const void *  h2 
)
static

Compare two peer identities (for qsort()).

Parameters
h1some peer identity
h2some peer identity
Returns
1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.

Definition at line 2561 of file gnunet-service-consensus.c.

Referenced by initialize_session_peer_list().

2563 {
2564  return memcmp (h1, h2, sizeof(struct GNUNET_PeerIdentity));
2565 }
The identity of the host (wraps the signing key of the peer).
Here is the caller graph for this function:

◆ initialize_session_peer_list()

static void initialize_session_peer_list ( struct ConsensusSession session,
const struct GNUNET_CONSENSUS_JoinMessage join_msg 
)
static

Create the sorted list of peers for the session, add the local peer if not in the join message.

Parameters
sessionsession to initialize
join_msgjoin message with the list of peers participating at the end

Definition at line 2576 of file gnunet-service-consensus.c.

References GNUNET_memcmp, GNUNET_memcpy, GNUNET_new_array, GNUNET_NO, GNUNET_YES, my_peer, GNUNET_CONSENSUS_JoinMessage::num_peers, ConsensusSession::num_peers, peer_id_cmp(), and ConsensusSession::peers.

Referenced by handle_client_join().

2579 {
2580  const struct GNUNET_PeerIdentity *msg_peers
2581  = (const struct GNUNET_PeerIdentity *) &join_msg[1];
2582  int local_peer_in_list;
2583 
2584  session->num_peers = ntohl (join_msg->num_peers);
2585 
2586  /* Peers in the join message, may or may not include the local peer,
2587  Add it if it is missing. */
2588  local_peer_in_list = GNUNET_NO;
2589  for (unsigned int i = 0; i < session->num_peers; i++)
2590  {
2591  if (0 == GNUNET_memcmp (&msg_peers[i],
2592  &my_peer))
2593  {
2594  local_peer_in_list = GNUNET_YES;
2595  break;
2596  }
2597  }
2598  if (GNUNET_NO == local_peer_in_list)
2599  session->num_peers++;
2600 
2601  session->peers = GNUNET_new_array (session->num_peers,
2602  struct GNUNET_PeerIdentity);
2603  if (GNUNET_NO == local_peer_in_list)
2604  session->peers[session->num_peers - 1] = my_peer;
2605  GNUNET_memcpy (session->peers,
2606  msg_peers,
2607  ntohl (join_msg->num_peers)
2608  * sizeof(struct GNUNET_PeerIdentity));
2609  qsort (session->peers,
2610  session->num_peers,
2611  sizeof (struct GNUNET_PeerIdentity),
2612  &peer_id_cmp);
2613 }
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int peer_id_cmp(const void *h1, const void *h2)
Compare two peer identities (for qsort()).
unsigned int num_peers
Number of other peers in the consensus.
static struct GNUNET_PeerIdentity my_peer
Peer that runs this service.
uint32_t num_peers
Number of peers (at the end of this message) that want to participate in the consensus.
Definition: consensus.h:48
struct GNUNET_PeerIdentity * peers
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
The identity of the host (wraps the signing key of the peer).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_task()

static struct TaskEntry* lookup_task ( const struct ConsensusSession session,
const struct TaskKey key 
)
static

Definition at line 2617 of file gnunet-service-consensus.c.

References GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, and ConsensusSession::taskmap.

Referenced by set_listen_cb().

2619 {
2620  struct GNUNET_HashCode hash;
2621 
2622  GNUNET_CRYPTO_hash (key,
2623  sizeof(struct TaskKey),
2624  &hash);
2626  "Looking up task hash %s\n",
2627  GNUNET_h2s (&hash));
2628  return GNUNET_CONTAINER_multihashmap_get (session->taskmap,
2629  &hash);
2630 }
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
struct GNUNET_CONTAINER_MultiHashMap * taskmap
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
Tuple of integers that together identify a task uniquely.
#define GNUNET_log(kind,...)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_listen_cb()

static void set_listen_cb ( void *  cls,
const struct GNUNET_PeerIdentity other_peer,
const struct GNUNET_MessageHeader context_msg,
struct GNUNET_SET_Request request 
)
static

Called when another peer wants to do a set operation with the local peer.

Parameters
clsclosure
other_peerthe other peer
context_msgmessage with application specific information from the other peer
requestrequest from the other peer, use GNUNET_SET_accept to accept it, otherwise the request will be refused Note that we don't use a return value here, as it is also necessary to specify the set we want to do the operation with, whith sometimes can be derived from the context message. Also necessary to specify the timeout.

Definition at line 2649 of file gnunet-service-consensus.c.

References TaskEntry::cls, commit_set(), GNUNET_assert, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT, GNUNET_SET_accept(), GNUNET_SET_OPTION_BYZANTINE, GNUNET_SET_OPTION_END, GNUNET_SET_RESULT_SYMMETRIC, GNUNET_YES, TaskEntry::is_finished, TaskEntry::is_started, TaskEntry::key, GNUNET_CONSENSUS_RoundContextMessage::kind, GNUNET_CONSENSUS_RoundContextMessage::leader, ConsensusSession::local_peer_idx, lookup_task(), ConsensusSession::lower_bound, SetOpCls::op, GNUNET_CONSENSUS_RoundContextMessage::peer1, TaskKey::peer1, GNUNET_CONSENSUS_RoundContextMessage::peer2, TaskKey::peer2, GNUNET_CONSENSUS_RoundContextMessage::repetition, set_result_cb(), TaskFuncCls::setop, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by handle_client_join().

2653 {
2654  struct ConsensusSession *session = cls;
2655  struct TaskKey tk;
2656  struct TaskEntry *task;
2658 
2659  if (NULL == context_msg)
2660  {
2661  GNUNET_break_op (0);
2662  return;
2663  }
2664 
2666  context_msg->type))
2667  {
2668  GNUNET_break_op (0);
2669  return;
2670  }
2671 
2672  if (sizeof(struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs (
2673  context_msg->size))
2674  {
2675  GNUNET_break_op (0);
2676  return;
2677  }
2678 
2679  cm = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg;
2680 
2681  tk = ((struct TaskKey) {
2682  .kind = ntohs (cm->kind),
2683  .peer1 = ntohs (cm->peer1),
2684  .peer2 = ntohs (cm->peer2),
2685  .repetition = ntohs (cm->repetition),
2686  .leader = ntohs (cm->leader),
2687  });
2688 
2689  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2690  session->local_peer_idx, debug_str_task_key (&tk));
2691 
2692  task = lookup_task (session, &tk);
2693 
2694  if (NULL == task)
2695  {
2696  GNUNET_break_op (0);
2697  return;
2698  }
2699 
2700  if (GNUNET_YES == task->is_finished)
2701  {
2702  GNUNET_break_op (0);
2703  return;
2704  }
2705 
2706  if (task->key.peer2 != session->local_peer_idx)
2707  {
2708  /* We're being asked, so we must be thne 2nd peer. */
2709  GNUNET_break_op (0);
2710  return;
2711  }
2712 
2713  GNUNET_assert (! ((task->key.peer1 == session->local_peer_idx) &&
2714  (task->key.peer2 == session->local_peer_idx)));
2715 
2716  struct GNUNET_SET_Option opts[] = {
2717  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2719  };
2720 
2721  task->cls.setop.op = GNUNET_SET_accept (request,
2723  opts,
2724  &set_result_cb,
2725  task);
2726 
2727  /* If the task hasn't been started yet,
2728  we wait for that until we commit. */
2729 
2730  if (GNUNET_YES == task->is_started)
2731  {
2732  commit_set (session, task);
2733  }
2734 }
#define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT
Provide context for a consensus round.
static void commit_set(struct ConsensusSession *session, struct TaskEntry *task)
Commit the appropriate set for a task.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
Sent as context message for set reconciliation.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
int16_t peer2
Number of the second peer in canonical order.
uint64_t lower_bound
Bounded Eppstein lower bound.
static struct TaskEntry * lookup_task(const struct ConsensusSession *session, const struct TaskKey *key)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
Client gets notified of the required changes for both the local and the remote set.
struct TaskKey key
Option for set operations.
int16_t leader
Leader in the gradecast phase.
A consensus session consists of one local client and the remote authorities.
Tuple of integers that together identify a task uniquely.
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
struct GNUNET_SET_OperationHandle * op
union TaskFuncCls cls
int16_t peer1
Number of the first peer in canonical order.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen().
Definition: set_api.c:1085
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_task()

static void put_task ( struct GNUNET_CONTAINER_MultiHashMap taskmap,
struct TaskEntry t 
)
static

Definition at line 2738 of file gnunet-service-consensus.c.

References Step::debug_name, GNUNET_array_grow, GNUNET_assert, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memdup, GNUNET_OK, TaskEntry::key, TaskEntry::step, t, Step::tasks, Step::tasks_cap, and Step::tasks_len.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2740 {
2741  struct GNUNET_HashCode round_hash;
2742  struct Step *s;
2743 
2744  GNUNET_assert (NULL != t->step);
2745  t = GNUNET_memdup (t, sizeof(struct TaskEntry));
2746  s = t->step;
2747  if (s->tasks_len == s->tasks_cap)
2748  {
2749  unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2751  s->tasks_cap,
2752  target_size);
2753  }
2754 
2755 #ifdef GNUNET_EXTRA_LOGGING
2756  GNUNET_assert (NULL != s->debug_name);
2757  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2758  debug_str_task_key (&t->key),
2759  s->debug_name);
2760 #endif
2761 
2762  s->tasks[s->tasks_len] = t;
2763  s->tasks_len++;
2764 
2765  GNUNET_CRYPTO_hash (&t->key,
2766  sizeof(struct TaskKey),
2767  &round_hash);
2770  &round_hash,
2771  t,
2773 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
unsigned int tasks_len
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskKey key
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct TaskEntry ** tasks
Tasks that this step is composed of.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Tuple of integers that together identify a task uniquely.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int tasks_cap
Here is the call graph for this function:
Here is the caller graph for this function:

◆ install_step_timeouts()

static void install_step_timeouts ( struct ConsensusSession session)
static

Definition at line 2777 of file gnunet-service-consensus.c.

Referenced by handle_client_conclude().

2778 {
2779  /* Given the fully constructed task graph
2780  with rounds for tasks, we can give the tasks timeouts. */
2781 
2782  // unsigned int max_round;
2783 
2784  /* XXX: implement! */
2785 }
Here is the caller graph for this function:

◆ arrange_peers()

static void arrange_peers ( uint16_t *  p1,
uint16_t *  p2,
uint16_t  n 
)
static

Definition at line 2792 of file gnunet-service-consensus.c.

References testconfigure::b, and GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2795 {
2796  uint16_t a;
2797  uint16_t b;
2798 
2799  GNUNET_assert (*p1 < n);
2800  GNUNET_assert (*p2 < n);
2801 
2802  if (*p1 < *p2)
2803  {
2804  a = *p1;
2805  b = *p2;
2806  }
2807  else
2808  {
2809  a = *p2;
2810  b = *p1;
2811  }
2812 
2813  /* For uniformly random *p1, *p2,
2814  this condition is true with 50% chance */
2815  if (((b - a) + n) % n <= n / 2)
2816  {
2817  *p1 = a;
2818  *p2 = b;
2819  }
2820  else
2821  {
2822  *p1 = b;
2823  *p2 = a;
2824  }
2825 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Here is the caller graph for this function:

◆ step_depend_on()

static void step_depend_on ( struct Step step,
struct Step dep 
)
static

Record dep as a dependency of step.

Definition at line 2832 of file gnunet-service-consensus.c.

References Step::debug_name, GNUNET_array_grow, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, Step::pending_prereq, Step::round, Step::subordinates, Step::subordinates_cap, and Step::subordinates_len.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2834 {
2835  /* We're not checking for cyclic dependencies,
2836  but this is a cheap sanity check. */
2837  GNUNET_assert (step != dep);
2838  GNUNET_assert (NULL != step);
2839  GNUNET_assert (NULL != dep);
2840  GNUNET_assert (dep->round <= step->round);
2841 
2842 #ifdef GNUNET_EXTRA_LOGGING
2843  /* Make sure we have complete debugging information.
2844  Also checks that we don't screw up too badly
2845  constructing the task graph. */
2846  GNUNET_assert (NULL != step->debug_name);
2847  GNUNET_assert (NULL != dep->debug_name);
2849  "Making step `%s' depend on `%s'\n",
2850  step->debug_name,
2851  dep->debug_name);
2852 #endif
2853 
2854  if (dep->subordinates_cap == dep->subordinates_len)
2855  {
2856  unsigned int target_size = 3 * (dep->subordinates_cap + 1) / 2;
2858  dep->subordinates_cap,
2859  target_size);
2860  }
2861 
2863 
2864  dep->subordinates[dep->subordinates_len] = step;
2865  dep->subordinates_len++;
2866 
2867  step->pending_prereq++;
2868 }
unsigned int subordinates_cap
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
size_t pending_prereq
Counter for the prerequisites of this step.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
unsigned int round
Synchrony round of the task.
#define GNUNET_log(kind,...)
unsigned int subordinates_len
Here is the caller graph for this function:

◆ create_step()

static struct Step* create_step ( struct ConsensusSession session,
int  round,
int  early_finishable 
)
static

Definition at line 2872 of file gnunet-service-consensus.c.

References Step::early_finishable, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_new, Step::round, Step::session, ConsensusSession::steps_head, and ConsensusSession::steps_tail.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2875 {
2876  struct Step *step;
2877 
2878  step = GNUNET_new (struct Step);
2879  step->session = session;
2880  step->round = round;
2883  session->steps_tail,
2884  step);
2885  return step;
2886 }
struct ConsensusSession * session
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int early_finishable
When we&#39;re doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
unsigned int round
Synchrony round of the task.
Here is the caller graph for this function:

◆ construct_task_graph_gradecast()

static void construct_task_graph_gradecast ( struct ConsensusSession session,
uint16_t  rep,
uint16_t  lead,
struct Step step_before,
struct Step step_after 
)
static

Construct the task graph for a single gradecast.

Definition at line 2893 of file gnunet-service-consensus.c.

References arrange_peers(), TaskEntry::cls, create_step(), Step::debug_name, DIFF_KIND_LEADER_PROPOSAL, GNUNET_asprintf(), GNUNET_YES, SetOpCls::input_set, ConsensusSession::local_peer_idx, me, ConsensusSession::num_peers, SetOpCls::output_diff, SetOpCls::output_rfn, SetOpCls::output_set, PHASE_KIND_GRADECAST_CONFIRM, PHASE_KIND_GRADECAST_CONFIRM_GRADE, PHASE_KIND_GRADECAST_ECHO, PHASE_KIND_GRADECAST_ECHO_GRADE, PHASE_KIND_GRADECAST_LEADER, put_task(), RFN_KIND_CONFIRM, RFN_KIND_ECHO, Step::round, SET_KIND_CURRENT, SET_KIND_ECHO_RESULT, SET_KIND_LEADER_PROPOSAL, TaskFuncCls::setop, step_depend_on(), task_cancel_reconcile(), task_start_eval_echo(), task_start_grade(), task_start_reconcile(), ConsensusSession::taskmap, and SetOpCls::transceive_contested.

Referenced by construct_task_graph().

2898 {
2899  uint16_t n = session->num_peers;
2900  uint16_t me = session->local_peer_idx;
2901  uint16_t p1;
2902  uint16_t p2;
2903  /* The task we're currently setting up. */
2904  struct TaskEntry task;
2905  struct Step *step;
2906  struct Step *prev_step;
2907  uint16_t round;
2908 
2909  round = step_before->round + 1;
2910 
2911  /* gcast step 1: leader disseminates */
2912  step = create_step (session,
2913  round,
2914  GNUNET_YES);
2915 #ifdef GNUNET_EXTRA_LOGGING
2916  GNUNET_asprintf (&step->debug_name,
2917  "disseminate leader %u rep %u",
2918  lead,
2919  rep);
2920 #endif
2921  step_depend_on (step,
2922  step_before);
2923 
2924  if (lead == me)
2925  {
2926  for (unsigned int k = 0; k < n; k++)
2927  {
2928  if (k == me)
2929  continue;
2930  p1 = me;
2931  p2 = k;
2932  arrange_peers (&p1, &p2, n);
2933  task = ((struct TaskEntry) {
2934  .step = step,
2935  .start = task_start_reconcile,
2936  .cancel = task_cancel_reconcile,
2937  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep,
2938  me },
2939  });
2940  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2941  put_task (session->taskmap, &task);
2942  }
2943  /* We run this task to make sure that the leader
2944  has the stored the SET_KIND_LEADER set of himself,
2945  so it can participate in the rest of the gradecast
2946  without the code having to handle any special cases. */
2947  task = ((struct TaskEntry) {
2948  .step = step,
2949  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, me, me, rep, me },
2950  .start = task_start_reconcile,
2951  .cancel = task_cancel_reconcile,
2952  });
2953  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2954  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
2955  me };
2956  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL,
2957  rep, me };
2958  put_task (session->taskmap, &task);
2959  }
2960  else
2961  {
2962  p1 = me;
2963  p2 = lead;
2964  arrange_peers (&p1, &p2, n);
2965  task = ((struct TaskEntry) {
2966  .step = step,
2967  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep,
2968  lead },
2969  .start = task_start_reconcile,
2970  .cancel = task_cancel_reconcile,
2971  });
2972  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2973  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
2974  lead };
2975  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL,
2976  rep, lead };
2977  put_task (session->taskmap, &task);
2978  }
2979 
2980  /* gcast phase 2: echo */
2981  prev_step = step;
2982  round += 1;
2983  step = create_step (session,
2984  round,
2985  GNUNET_YES);
2986 #ifdef GNUNET_EXTRA_LOGGING
2987  GNUNET_asprintf (&step->debug_name,
2988  "echo leader %u rep %u",
2989  lead,
2990  rep);
2991 #endif
2992  step_depend_on (step,
2993  prev_step);
2994 
2995  for (unsigned int k = 0; k < n; k++)
2996  {
2997  p1 = k;
2998  p2 = me;
2999  arrange_peers (&p1, &p2, n);
3000  task = ((struct TaskEntry) {
3001  .step = step,
3002  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO, p1, p2, rep, lead },
3003  .start = task_start_reconcile,
3004  .cancel = task_cancel_reconcile,
3005  });
3006  task.cls.setop.input_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
3007  lead };
3008  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_ECHO, rep, lead };
3009  put_task (session->taskmap, &task);
3010  }
3011 
3012  prev_step = step;
3013  /* Same round, since step only has local tasks */
3014  step = create_step (session, round, GNUNET_YES);
3015 #ifdef GNUNET_EXTRA_LOGGING
3016  GNUNET_asprintf (&step->debug_name, "echo grade leader %u rep %u", lead, rep);
3017 #endif
3018  step_depend_on (step, prev_step);
3019 
3020  arrange_peers (&p1, &p2, n);
3021  task = ((struct TaskEntry) {
3022  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO_GRADE, -1, -1, rep,
3023  lead },
3024  .step = step,
3025  .start = task_start_eval_echo
3026  });
3027  put_task (session->taskmap, &task);
3028 
3029  prev_step = step;
3030  round += 1;
3031  step = create_step (session, round, GNUNET_YES);
3032 #ifdef GNUNET_EXTRA_LOGGING
3033  GNUNET_asprintf (&step->debug_name, "confirm leader %u rep %u", lead, rep);
3034 #endif
3035  step_depend_on (step, prev_step);
3036 
3037  /* gcast phase 3: confirmation and grading */
3038  for (unsigned int k = 0; k < n; k++)
3039  {
3040  p1 = k;
3041  p2 = me;
3042  arrange_peers (&p1, &p2, n);
3043  task = ((struct TaskEntry) {
3044  .step = step,
3045  .start = task_start_reconcile,
3046  .cancel = task_cancel_reconcile,
3047  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM, p1, p2, rep,
3048  lead },
3049  });
3050  task.cls.setop.input_set = (struct SetKey) { SET_KIND_ECHO_RESULT, rep,
3051  lead };
3052  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_CONFIRM, rep, lead };
3053  /* If there was at least one element in the echo round that was
3054  contested (i.e. it had no n-t majority), then we let the other peers
3055  know, and other peers let us know. The contested flag for each peer is
3056  stored in the rfn. */
3057  task.cls.setop.transceive_contested = GNUNET_YES;
3058  put_task (session->taskmap, &task);
3059  }
3060 
3061  prev_step = step;
3062  /* Same round, since step only has local tasks */
3063  step = create_step (session, round, GNUNET_YES);
3064 #ifdef GNUNET_EXTRA_LOGGING
3065  GNUNET_asprintf (&step->debug_name, "confirm grade leader %u rep %u", lead,
3066  rep);
3067 #endif
3068  step_depend_on (step, prev_step);
3069 
3070  task = ((struct TaskEntry) {
3071  .step = step,
3072  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM_GRADE, -1, -1, rep,
3073  lead },
3074  .start = task_start_grade,
3075  });
3076  put_task (session->taskmap, &task);
3077 
3078  step_depend_on (step_after, step);
3079 }
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static void task_start_reconcile(struct TaskEntry *task)
static void task_start_grade(struct TaskEntry *task)
static void arrange_peers(uint16_t *p1, uint16_t *p2, uint16_t n)
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_CONTAINER_MultiHashMap * taskmap
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
static struct Step * create_step(struct ConsensusSession *session, int round, int early_finishable)
char * debug_name
Human-readable name for the task, used for debugging.
static void task_start_eval_echo(struct TaskEntry *task)
static void step_depend_on(struct Step *step, struct Step *dep)
Record dep as a dependency of step.
Tuple of integers that together identify a task uniquely.
unsigned int round
Synchrony round of the task.
static void task_cancel_reconcile(struct TaskEntry *task)
struct Step * step
unsigned int local_peer_idx
Index of the local peer in the peers array.
static void put_task(struct GNUNET_CONTAINER_MultiHashMap *taskmap, struct TaskEntry *t)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ construct_task_graph()

static void construct_task_graph ( struct ConsensusSession session)
static

Definition at line 3083 of file gnunet-service-consensus.c.

References arrange_peers(), TaskEntry::cls, construct_task_graph_gradecast(), create_step(), Step::debug_name, SetOpCls::do_not_remove, TaskFuncCls::finish, GNUNET_asprintf(), GNUNET_NO, GNUNET_strdup, GNUNET_YES, SetOpCls::input_set, FinishCls::input_set, ConsensusSession::local_peer_idx, me, ConsensusSession::num_peers, SetOpCls::output_set, PHASE_KIND_ALL_TO_ALL, PHASE_KIND_ALL_TO_ALL_2, PHASE_KIND_APPLY_REP, PHASE_KIND_FINISH, put_task(), Step::round, SET_KIND_CURRENT, SET_KIND_LAST_GRADECAST, TaskFuncCls::setop, step_depend_on(), t, task_cancel_reconcile(), task_start_apply_round(), task_start_finish(), task_start_reconcile(), and ConsensusSession::taskmap.

Referenced by handle_client_join().

3084 {
3085  uint16_t n = session->num_peers;
3086  uint16_t t = n / 3;
3087  uint16_t me = session->local_peer_idx;
3088  /* The task we're currently setting up. */
3089  struct TaskEntry task;
3090  /* Current leader */
3091  unsigned int lead;
3092  struct Step *step;
3093  struct Step *prev_step;
3094  unsigned int round = 0;
3095 
3096  // XXX: introduce first step,
3097  // where we wait for all insert acks
3098  // from the set service
3099 
3100  /* faster but brittle all-to-all */
3101 
3102  // XXX: Not implemented yet
3103 
3104  /* all-to-all step */
3105 
3106  step = create_step (session, round, GNUNET_NO);
3107 
3108 #ifdef GNUNET_EXTRA_LOGGING
3109  step->debug_name = GNUNET_strdup ("all to all");
3110 #endif
3111 
3112  for (unsigned int i = 0; i < n; i++)
3113  {
3114  uint16_t p1;
3115  uint16_t p2;
3116 
3117  p1 = me;
3118  p2 = i;
3119  arrange_peers (&p1, &p2, n);
3120  task = ((struct TaskEntry) {
3121  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL, p1, p2, -1, -1 },
3122  .step = step,
3123  .start = task_start_reconcile,
3124  .cancel = task_cancel_reconcile,
3125  });
3126  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3127  task.cls.setop.output_set = task.cls.setop.input_set;
3128  task.cls.setop.do_not_remove = GNUNET_YES;
3129  put_task (session->taskmap, &task);
3130  }
3131 
3132  round += 1;
3133  prev_step = step;
3134  step = create_step (session, round, GNUNET_NO);;
3135 #ifdef GNUNET_EXTRA_LOGGING
3136  step->debug_name = GNUNET_strdup ("all to all 2");
3137 #endif
3138  step_depend_on (step, prev_step);
3139 
3140 
3141  for (unsigned int i = 0; i < n; i++)
3142  {
3143  uint16_t p1;
3144  uint16_t p2;
3145 
3146  p1 = me;
3147  p2 = i;
3148  arrange_peers (&p1, &p2, n);
3149  task = ((struct TaskEntry) {
3150  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL_2, p1, p2, -1, -1 },
3151  .step = step,
3152  .start = task_start_reconcile,
3153  .cancel = task_cancel_reconcile,
3154  });
3155  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3156  task.cls.setop.output_set = task.cls.setop.input_set;
3157  task.cls.setop.do_not_remove = GNUNET_YES;
3158  put_task (session->taskmap, &task);
3159  }
3160 
3161  round += 1;
3162 
3163  prev_step = step;
3164  step = NULL;
3165 
3166 
3167  /* Byzantine union */
3168 
3169  /* sequential repetitions of the gradecasts */
3170  for (unsigned int i = 0; i < t + 1; i++)
3171  {
3172  struct Step *step_rep_start;
3173  struct Step *step_rep_end;
3174 
3175  /* Every repetition is in a separate round. */
3176  step_rep_start = create_step (session, round, GNUNET_YES);
3177 #ifdef GNUNET_EXTRA_LOGGING
3178  GNUNET_asprintf (&step_rep_start->debug_name, "gradecast start rep %u", i);
3179 #endif
3180 
3181  step_depend_on (step_rep_start, prev_step);
3182 
3183  /* gradecast has three rounds */
3184  round += 3;
3185  step_rep_end = create_step (session, round, GNUNET_YES);
3186 #ifdef GNUNET_EXTRA_LOGGING
3187  GNUNET_asprintf (&step_rep_end->debug_name, "gradecast end rep %u", i);
3188 #endif
3189 
3190  /* parallel gradecasts */
3191  for (lead = 0; lead < n; lead++)
3192  construct_task_graph_gradecast (session, i, lead, step_rep_start,
3193  step_rep_end);
3194 
3195  task = ((struct TaskEntry) {
3196  .step = step_rep_end,
3197  .key = (struct TaskKey) { PHASE_KIND_APPLY_REP, -1, -1, i, -1 },
3198  .start = task_start_apply_round,
3199  });
3200  put_task (session->taskmap, &task);
3201 
3202  prev_step = step_rep_end;
3203  }
3204 
3205  /* There is no next gradecast round, thus the final