GNUnet  0.20.0
gnunet-service-consensus.c File Reference

multi-peer set reconciliation More...

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 229 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_ADD
Vote that an element should be added.
@ VOTE_REMOVE
Vote that an element should be removed.
@ VOTE_STAY
Vote that nothing should change.

◆ EarlyStoppingPhase

Enumerator
EARLY_STOPPING_NONE 
EARLY_STOPPING_ONE_MORE 
EARLY_STOPPING_DONE 

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

56 {
60 };
@ EARLY_STOPPING_DONE
@ EARLY_STOPPING_NONE
@ EARLY_STOPPING_ONE_MORE

◆ 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.

64 {
78 };
@ PHASE_KIND_FINISH
@ PHASE_KIND_GRADECAST_CONFIRM
@ PHASE_KIND_GRADECAST_ECHO
@ PHASE_KIND_ALL_TO_ALL_2
@ PHASE_KIND_APPLY_REP
Apply a repetition of the all-to-all gradecast to the current set.
@ PHASE_KIND_GRADECAST_LEADER
@ PHASE_KIND_GRADECAST_ECHO_GRADE
@ PHASE_KIND_GRADECAST_CONFIRM_GRADE
@ PHASE_KIND_ALL_TO_ALL

◆ 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.

82 {
83  SET_KIND_NONE = 0,
91 };
@ SET_KIND_ECHO_RESULT
@ SET_KIND_LEADER_PROPOSAL
@ SET_KIND_CURRENT
@ SET_KIND_LAST_GRADECAST
Last result set from a gradecast.

◆ 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.

102 {
103  RFN_KIND_NONE = 0,
107 };
@ RFN_KIND_GRADECAST_RESULT

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

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

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 }
static void finish_step(struct Step *step)
#define GNUNET_log(kind,...)
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_INFO
unsigned int local_peer_idx
Index of the local peer in the peers array.
unsigned int tasks_len
struct ConsensusSession * session
unsigned int finished_tasks
struct TaskKey key
struct Step * step

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().

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.

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",
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 }
static void start_task(struct ConsensusSession *session, struct TaskEntry *task)
@ GNUNET_ERROR_TYPE_DEBUG
unsigned int round
Synchrony round of the task.
unsigned int is_finished
size_t pending_prereq
Counter for the prerequisites of this step.
char * debug_name
Human-readable name for the task, used for debugging.
struct Step * next
All steps of one session are in a linked list for easier deallocation.
struct TaskEntry ** tasks
Tasks that this step is composed of.
unsigned int is_running
unsigned int subordinates_len

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, Step::session, 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().

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.

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

References phase, 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.

◆ setname()

static const char* setname ( uint16_t  kind)
static

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

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 }

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

◆ rfnname()

static const char* rfnname ( uint16_t  kind)
static

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

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 }

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

◆ diffname()

static const char* diffname ( uint16_t  kind)
static

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

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 }

References DIFF_KIND_GRADECAST_RESULT, DIFF_KIND_LEADER_CONSENSUS, DIFF_KIND_LEADER_PROPOSAL, and DIFF_KIND_NONE.

◆ 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.

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 }
@ GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT
Block type for consensus elements.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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:304
#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:63
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:87
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE
Sent by service to client in order to signal a completed consensus conclusion.
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT
Sent by service when a new element is added.
Consensus element, either marker or payload.
uint16_t payload_type
Payload element_type, only valid if this is not a marker element.
uint8_t marker
Is this a marker element?
A consensus session consists of one local client and the remote authorities.
struct GNUNET_MQ_Handle * client_mq
Queued messages to the client.
Message with an element.
Definition: consensus.h:73
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.
union TaskFuncCls cls

References ConsensusSession::client_mq, TaskEntry::cls, GNUNET_SET_Element::data, 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().

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.

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 
772  GNUNET_assert (SET_KIND_NONE != key->set_kind);
774  sizeof(struct SetKey),
775  &hash);
776  return GNUNET_CONTAINER_multihashmap_get (session->setmap,
777  &hash);
778 }
struct GNUNET_HashCode key
The key used in the DHT.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
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.
struct GNUNET_CONTAINER_MultiHashMap * setmap
A 512-bit hashcode.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, key, ConsensusSession::local_peer_idx, 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().

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.

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));
791  GNUNET_assert (DIFF_KIND_NONE != key->diff_kind);
793  sizeof(struct DiffKey),
794  &hash);
796  &hash);
797 }
struct GNUNET_CONTAINER_MultiHashMap * diffmap

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

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

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.

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));
810  GNUNET_assert (RFN_KIND_NONE != key->rfn_kind);
812  sizeof(struct RfnKey),
813  &hash);
814  return GNUNET_CONTAINER_multihashmap_get (session->rfnmap,
815  &hash);
816 }
struct GNUNET_CONTAINER_MultiHashMap * rfnmap

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, key, ConsensusSession::local_peer_idx, 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().

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.

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 }
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
@ GNUNET_OK
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1168
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1184
int weight
Positive weight for 'add', negative weights for 'remove'.
const struct GNUNET_SET_Element * element
struct GNUNET_CONTAINER_MultiHashMap * changes

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 set_result_cb().

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.

861 {
862  GNUNET_assert (commit_peer < rfn->num_peers);
863 
864  rfn->peer_commited[commit_peer] = GNUNET_YES;
865 }
static unsigned int num_peers
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.

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

Referenced by set_result_cb(), and task_start_grade().

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.

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.

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

Referenced by set_result_cb().

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.

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 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81

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

Referenced by task_start_grade().

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.

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 }
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
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.
const struct GNUNET_SET_Element * element

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().

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.

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.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.

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().

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.

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 }

Referenced by set_result_cb().

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.

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 }
@ CONSENSUS_MARKER_CONTESTED
@ CONSENSUS_MARKER_SIZE
uint16_t status
See PRISM_STATUS_*-constants.
static void rfn_contest(struct ReferendumEntry *rfn, uint16_t contested_peer)
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 struct ReferendumEntry * lookup_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 finish_task(struct TaskEntry *task)
static struct SetEntry * lookup_set(struct ConsensusSession *session, const struct SetKey *key)
static int cmp_uint64_t(const void *pa, const void *pb)
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, const struct DiffKey *key)
static void rfn_commit(struct ReferendumEntry *rfn, uint16_t commit_peer)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
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:707
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:673
@ GNUNET_SET_STATUS_FAILURE
The other peer refused to to the operation with us, or something went wrong.
@ GNUNET_SET_STATUS_ADD_REMOTE
Element should be added to the result set of the remote peer, i.e.
@ GNUNET_SET_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SET_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
unsigned int num_peers
Number of other peers in the consensus.
uint64_t first_size
Our set size from the first round.
int * peers_blacklisted
Array of peers with length 'num_peers'.
uint64_t lower_bound
Bounded Eppstein lower bound.
Weighted diff.
enum DiffKind diff_kind
enum RfnKind rfn_kind
struct GNUNET_SET_Handle * h
enum SetKind set_kind
struct SetKey output_set
struct DiffKey output_diff
struct RfnKey output_rfn
uint16_t kind
A value from 'enum PhaseKind'.
struct SetOpCls setop

References 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_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_memdup, GNUNET_new_array, GNUNET_NO, GNUNET_ntohll(), 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_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, 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, status, TaskEntry::step, task_other_peer(), Step::tasks_len, SetOpCls::transceive_contested, VOTE_ADD, and VOTE_REMOVE.

Referenced by set_listen_cb(), and task_start_reconcile().

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.

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 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of the consensus service.
struct GNUNET_STATISTICS_Handle * statistics
Statistics handle.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:100
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:745
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:656
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:516
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:1073
@ GNUNET_SET_OPERATION_UNION
Set union, return all elements that are in at least one of the sets.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct ConsensusElement ce
struct GNUNET_HashCode rand
struct ConsensusElement ce
Element stored in a set.
Opaque handle to a set.
Definition: set_api.c:50
struct SetKey key
int is_contested
GNUNET_YES if the set resulted from applying a referendum with contested elements.
struct GNUNET_SET_OperationHandle * op
struct SetKey input_set

References ConsensusSizeElement::ce, ConsensusStuffedElement::ce, cfg, 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, SetEntry::h, SetOpCls::input_set, SetEntry::is_contested, SetEntry::key, 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, SetKey::set_kind, SET_KIND_CURRENT, TaskFuncCls::setop, ConsensusSizeElement::size, GNUNET_SET_Element::size, statistics, task_other_peer(), and SetOpCls::transceive_contested.

Referenced by set_listen_cb(), and task_start_reconcile().

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.

1555 {
1556  struct GNUNET_HashCode hash;
1557 
1558  GNUNET_CRYPTO_hash (&diff->key,
1559  sizeof(struct DiffKey),
1560  &hash);
1563  &hash,
1564  diff,
1566 }
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct DiffKey key

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().

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.

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 }
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
@ GNUNET_SYSERR

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

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

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.

1593 {
1594  struct GNUNET_HashCode hash;
1595 
1596  GNUNET_CRYPTO_hash (&rfn->key, sizeof(struct RfnKey), &hash);
1599  &hash,
1600  rfn,
1602 }

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().

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.

1607 {
1608  /* not implemented yet */
1609  GNUNET_assert (0);
1610 }

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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.

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 }
enum GNUNET_GenericReturnValue 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's position.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.

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

Referenced by task_start_grade().

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.

1645 {
1646  struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1647 
1649  GNUNET_NO);
1650 
1651  return d;
1652 }
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.

References DiffEntry::changes, GNUNET_CONTAINER_multihashmap_create(), GNUNET_new, and GNUNET_NO.

Referenced by task_start_reconcile().

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.

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 }
static unsigned int size
Size of the "table".
Definition: peer.c:68

References GNUNET_CONTAINER_multihashmap_create(), 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().

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.

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 }

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().

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.

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 }
static struct SolverHandle * sh
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct SetHandle * set_handles_tail
struct SetHandle * set_handles_head
struct SetKey dst_set_key
struct TaskEntry * task

References SetCopyCls::dst_set_key, GNUNET_CONTAINER_DLL_insert, GNUNET_free, GNUNET_new, SetEntry::h, SetEntry::key, 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().

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.

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 }
static void set_copy_cb(void *cls, struct GNUNET_SET_Handle *copy)
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1139

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().

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.

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 }
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.

References finish_task(), GNUNET_assert, GNUNET_free, and pc.

Referenced by task_start_apply_round(), and task_start_eval_echo().

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.

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)
static void run_ready_steps(struct ConsensusSession *session)
int early_finishable
When we're doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
struct Step ** subordinates

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, TaskEntry::step, Step::subordinates, and Step::subordinates_len.

Referenced by task_start_apply_round().

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.

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 }

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, TaskEntry::step, Step::subordinates, Step::subordinates_len, and Step::tasks_len.

Referenced by finish_task(), and run_ready_steps().

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.

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  }
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",
2073  }
2074  }
2076 }
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 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 void set_mutation_done(void *cls)
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
int early_stopping
State of our early stopping scheme.
struct TaskEntry * task
Task to finish once all changes are through.
int16_t repetition
Repetition of the gradecast phase.

References create_set_copy_for_task(), ConsensusSession::early_stopping, EARLY_STOPPING_DONE, EARLY_STOPPING_NONE, EARLY_STOPPING_ONE_MORE, RfnElementInfo::element, 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().

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.

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 }
static void apply_diff_to_rfn(struct DiffEntry *diff, struct ReferendumEntry *rfn, uint16_t voting_peer, uint16_t num_peers)
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
static uint16_t rfn_noncontested(struct ReferendumEntry *rfn)
struct ReferendumEntry * rfn_create(uint16_t size)
#define GNUNET_MIN(a, b)
int16_t leader
Leader in the gradecast phase.

References apply_diff_to_rfn(), DIFF_KIND_LEADER_PROPOSAL, RfnElementInfo::element, 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().

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.

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 committed 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 }
static struct DiffEntry * diff_create(void)
static void put_diff(struct ConsensusSession *session, struct DiffEntry *diff)
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.
static void commit_set(struct ConsensusSession *session, struct TaskEntry *task)
Commit the appropriate set for a task.
#define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT
Provide context for a consensus round.
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:772
@ GNUNET_SET_OPTION_END
List terminator.
@ GNUNET_SET_OPTION_BYZANTINE
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault.
@ GNUNET_SET_RESULT_SYMMETRIC
Client gets notified of the required changes for both the local and the remote set.
struct GNUNET_HashCode global_id
Global consensus identification, computed from the session id and participating authorities.
struct GNUNET_PeerIdentity * peers
Sent as context message for set reconciliation.
Option for set operations.

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, gnunet-chk::opts, 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().

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.

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 }

References create_set_copy_for_task(), RfnElementInfo::element, 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().

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.

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 }
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.
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:1117
struct SetKey input_set
struct FinishCls finish

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().

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.

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 }

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().

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.

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 }
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.

References GNUNET_memcmp, ConsensusSession::num_peers, peer, ConsensusSession::peers, and Step::session.

Referenced by handle_client_join().

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.

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 }
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
enum GNUNET_GenericReturnValue 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:70
The identity of the host (wraps the signing key of the peer).

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

Referenced by handle_client_join().

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.

2563 {
2564  return memcmp (h1, h2, sizeof(struct GNUNET_PeerIdentity));
2565 }

Referenced by initialize_session_peer_list().

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.

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 }
static int peer_id_cmp(const void *h1, const void *h2)
Compare two peer identities (for qsort()).
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

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().

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.

2619 {
2620  struct GNUNET_HashCode hash;
2621 
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
Tuple of integers that together identify a task uniquely.

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

Referenced by set_listen_cb().

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, which sometimes can be derived from the context message. Also necessary to specify the timeout.

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

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 the 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 
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 }
static struct TaskEntry * lookup_task(const struct ConsensusSession *session, const struct TaskKey *key)
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
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:1030
int16_t repetition
Repetition of the gradecast phase.
int16_t peer1
Number of the first peer in canonical order.
int16_t leader
Leader in the gradecast phase.
int16_t peer2
Number of the second peer in canonical order.
uint16_t kind
A value from 'enum PhaseKind'.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

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-chk::opts, GNUNET_CONSENSUS_RoundContextMessage::peer1, TaskKey::peer1, GNUNET_CONSENSUS_RoundContextMessage::peer2, TaskKey::peer2, GNUNET_CONSENSUS_RoundContextMessage::repetition, request, set_result_cb(), TaskFuncCls::setop, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by handle_client_join().

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.

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 }
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
unsigned int tasks_cap

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, t, Step::tasks, Step::tasks_cap, and Step::tasks_len.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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.

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 }

Referenced by handle_client_conclude().

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.

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 }

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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.

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

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().

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.

2875 {
2876  struct Step *step;
2877 
2878  step = GNUNET_new (struct Step);
2879  step->session = session;
2880  step->round = round;
2884  step);
2885  return step;
2886 }
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.

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().

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.

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 void task_start_grade(struct TaskEntry *task)
static void arrange_peers(uint16_t *p1, uint16_t *p2, uint16_t n)
static struct Step * create_step(struct ConsensusSession *session, int round, int early_finishable)
static void task_cancel_reconcile(struct TaskEntry *task)
static void put_task(struct GNUNET_CONTAINER_MultiHashMap *taskmap, struct TaskEntry *t)
static void task_start_reconcile(struct TaskEntry *task)
static void step_depend_on(struct Step *step, struct Step *dep)
Record dep as a dependency of step.
static void task_start_eval_echo(struct TaskEntry *task)
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.

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, Step::session, SET_KIND_CURRENT, SET_KIND_ECHO_RESULT, SET_KIND_LEADER_PROPOSAL, TaskFuncCls::setop, TaskEntry::step, 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().

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.

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
3206  start step is the overall end step of the gradecasts */
3207  round += 1;
3208  step = create_step (session, round, GNUNET_NO);
3209 #ifdef GNUNET_EXTRA_LOGGING
3210  GNUNET_asprintf (&step->debug_name, "finish");
3211 #endif
3212  step_depend_on (step, prev_step);
3213 
3214  task = ((struct TaskEntry) {
3215  .step = step,
3216  .key = (struct TaskKey) { PHASE_KIND_FINISH, -1, -1, -1, -1 },
3217  .start = task_start_finish,
3218  });
3219  task.cls.finish.input_set = (struct SetKey) { SET_KIND_LAST_GRADECAST };
3220 
3221  put_task (session->taskmap, &task);
3222 }
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.
static void task_start_finish(struct TaskEntry *task)
static void task_start_apply_round(struct TaskEntry *task)
Apply the result from one round of gradecasts (i.e.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.

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, Step::session, SET_KIND_CURRENT, SET_KIND_LAST_GRADECAST, TaskFuncCls::setop, TaskEntry::step, 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().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_client_join()

static int check_client_join ( void *  cls,
const struct GNUNET_CONSENSUS_JoinMessage m 
)
static

Check join message.

Parameters
clssession of client that sent the message
mmessage sent by the client
Returns
GNUNET_OK if m is well-formed

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

3235 {
3236  uint32_t listed_peers = ntohl (m->num_peers);
3237 
3238  if ((ntohs (m->header.size) - sizeof(*m)) !=
3239  listed_peers * sizeof(struct GNUNET_PeerIdentity))
3240  {
3241  GNUNET_break (0);
3242  return GNUNET_SYSERR;
3243  }
3244  return GNUNET_OK;
3245 }

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, and m.

◆ handle_client_join()

static void handle_client_join ( void *  cls,
const struct GNUNET_CONSENSUS_JoinMessage m 
)
static

Called when a client wants to join a consensus session.

Parameters
clssession of client that sent the message
mmessage sent by the client

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

3257 {
3258  struct ConsensusSession *session = cls;
3259  struct ConsensusSession *other_session;
3260 
3262  m);
3263  compute_global_id (session,
3264  &m->session_id);
3265 
3266  /* Check if some local client already owns the session.
3267  It is only legal to have a session with an existing global id
3268  if all other sessions with this global id are finished.*/
3269  for (other_session = sessions_head;
3270  NULL != other_session;
3271  other_session = other_session->next)
3272  {
3273  if ( (other_session != session) &&
3274  (0 == GNUNET_CRYPTO_hash_cmp (&session->global_id,
3275  &other_session->global_id)) )
3276  break;
3277  }
3278 
3279  session->conclude_deadline
3280  = GNUNET_TIME_absolute_ntoh (m->deadline);
3281  session->conclude_start
3282  = GNUNET_TIME_absolute_ntoh (m->start);
3283  session->local_peer_idx = get_peer_idx (&my_peer,
3284  session);
3285  GNUNET_assert (-1 != session->local_peer_idx);
3286 
3288  "Joining consensus session %s containing %u peers as %u with timeout %s\n",
3289  GNUNET_h2s (&m->session_id),
3290  session->num_peers,
3291  session->local_peer_idx,
3294  session->conclude_deadline),
3295  GNUNET_YES));
3296 
3297  session->set_listener
3300  &session->global_id,
3301  &set_listen_cb,
3302  session);
3303 
3305  GNUNET_NO);
3307  GNUNET_NO);
3309  GNUNET_NO);
3311  GNUNET_NO);
3312 
3313  {
3314  struct SetEntry *client_set;
3315 
3316  client_set = GNUNET_new (struct SetEntry);
3317  client_set->h = GNUNET_SET_create (cfg,
3319  struct SetHandle *sh = GNUNET_new (struct SetHandle);
3320  sh->h = client_set->h;
3322  session->set_handles_tail,
3323  sh);
3324  client_set->key = ((struct SetKey) { SET_KIND_CURRENT, 0, 0 });
3325  put_set (session,
3326  client_set);
3327  }
3328 
3329  session->peers_blacklisted = GNUNET_new_array (session->num_peers,
3330  int);
3331 
3332  /* Just construct the task graph,
3333  but don't run anything until the client calls conclude. */
3334  construct_task_graph (session);
3336 }
static int get_peer_idx(const struct GNUNET_PeerIdentity *peer, const struct ConsensusSession *session)
Search peer in the list of peers in session.
static struct ConsensusSession * sessions_head
Linked list of sessions this peer participates in.
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.
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...
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.
static void construct_task_graph(struct ConsensusSession *session)
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:221
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
struct GNUNET_SET_ListenHandle * GNUNET_SET_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op_type, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: set_api.c:976
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:421
struct GNUNET_TIME_Absolute conclude_start
Time when the conclusion of the consensus should begin.
struct GNUNET_TIME_Absolute conclude_deadline
Timeout for all rounds together, single rounds will schedule a timeout task with a fraction of the co...
struct GNUNET_SERVICE_Client * client
Client that inhabits the session.
struct GNUNET_SET_ListenHandle * set_listener
Listener for requests from other peers.
struct ConsensusSession * next
Consensus sessions are kept in a DLL.

References cfg, ConsensusSession::client, compute_global_id(), ConsensusSession::conclude_deadline, ConsensusSession::conclude_start, construct_task_graph(), ConsensusSession::diffmap, get_peer_idx(), ConsensusSession::global_id, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CRYPTO_hash_cmp(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_new, GNUNET_new_array, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SET_create(), GNUNET_SET_listen(), GNUNET_SET_OPERATION_UNION, GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_difference(), GNUNET_TIME_absolute_ntoh(), GNUNET_YES, SetEntry::h, initialize_session_peer_list(), SetEntry::key, ConsensusSession::local_peer_idx, m, my_peer, ConsensusSession::next, ConsensusSession::num_peers, ConsensusSession::peers_blacklisted, put_set(), ConsensusSession::rfnmap, sessions_head, ConsensusSession::set_handles_head, ConsensusSession::set_handles_tail, SET_KIND_CURRENT, set_listen_cb(), ConsensusSession::set_listener, ConsensusSession::setmap, sh, and ConsensusSession::taskmap.

Here is the call graph for this function:

◆ check_client_insert()

static int check_client_insert ( void *  cls,
const struct GNUNET_CONSENSUS_ElementMessage msg 
)
static

Called when a client performs an insert operation.

Parameters
clsclient handle
msgmessage sent by the client
Returns
GNUNET_OK (always well-formed)

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

3349 {
3350  return GNUNET_OK;
3351 }

References GNUNET_OK.

◆ handle_client_insert()

static void handle_client_insert ( void *  cls,
const struct GNUNET_CONSENSUS_ElementMessage msg 
)
static

Called when a client performs an insert operation.

Parameters
clsclient handle
msgmessage sent by the client

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

3363 {
3364  struct ConsensusSession *session = cls;
3365  ssize_t element_size;
3366  struct GNUNET_SET_Handle *initial_set;
3367  struct ConsensusElement *ce;
3368 
3369  if (GNUNET_YES == session->conclude_started)
3370  {
3371  GNUNET_break (0);
3373  return;
3374  }
3375  element_size = ntohs (msg->header.size) - sizeof(*msg);
3376  ce = GNUNET_malloc (sizeof(struct ConsensusElement) + element_size);
3377  GNUNET_memcpy (&ce[1],
3378  &msg[1],
3379  element_size);
3380  ce->payload_type = msg->element_type;
3381 
3382  {
3383  struct SetKey key = { SET_KIND_CURRENT, 0, 0 };
3384  struct SetEntry *entry;
3385 
3386  entry = lookup_set (session,
3387  &key);
3388  GNUNET_assert (NULL != entry);
3389  initial_set = entry->h;
3390  }
3391 
3392  session->num_client_insert_pending++;
3393 
3394  {
3395  struct GNUNET_SET_Element element = {
3397  .size = sizeof(struct ConsensusElement) + element_size,
3398  .data = ce,
3399  };
3400 
3401  GNUNET_SET_add_element (initial_set,
3402  &element,
3403  NULL,
3404  NULL);
3405 #ifdef GNUNET_EXTRA_LOGGING
3407  "P%u: element %s added\n",
3408  session->local_peer_idx,
3409  debug_str_element (&element));
3410 #endif
3411  }
3412  GNUNET_free (ce);
3414 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
uint32_t data
The data value.
static unsigned int element_size
#define GNUNET_malloc(size)
Wrapper around malloc.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2330
unsigned int num_client_insert_pending

References ConsensusSession::client, ConsensusSession::conclude_started, data, element_size, GNUNET_SET_Element::element_type, GNUNET_assert, GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SET_add_element(), GNUNET_YES, SetEntry::h, key, ConsensusSession::local_peer_idx, lookup_set(), msg, ConsensusSession::num_client_insert_pending, ConsensusElement::payload_type, SET_KIND_CURRENT, and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ handle_client_conclude()

static void handle_client_conclude ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Called when a client performs the conclude operation.

Parameters
clsclient handle
messagemessage sent by the client

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

3426 {
3427  struct ConsensusSession *session = cls;
3428 
3429  if (GNUNET_YES == session->conclude_started)
3430  {
3431  /* conclude started twice */
3432  GNUNET_break (0);
3434  return;
3435  }
3437  "conclude requested\n");
3438  session->conclude_started = GNUNET_YES;
3439  install_step_timeouts (session);
3440  run_ready_steps (session);
3442 }
static void install_step_timeouts(struct ConsensusSession *session)

References ConsensusSession::client, ConsensusSession::conclude_started, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, install_step_timeouts(), and run_ready_steps().

Here is the call graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Called to clean up, after a shutdown has been requested.

Parameters
clsclosure

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

3452 {
3454  "shutting down\n");
3456  GNUNET_NO);
3457  statistics = NULL;
3458 }
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

References GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_destroy(), and statistics.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Start processing consensus requests.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

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

3472 {
3473  cfg = c;
3474  if (GNUNET_OK !=
3476  &my_peer))
3477  {
3479  "Could not retrieve host identity\n");
3481  return;
3482  }
3483  statistics = GNUNET_STATISTICS_create ("consensus",
3484  cfg);
3486  NULL);
3487 }
static void shutdown_task(void *cls)
Called to clean up, after a shutdown has been requested.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host's peer.
@ GNUNET_ERROR_TYPE_ERROR
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1334
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.

References cfg, GNUNET_CRYPTO_get_peer_identity(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), my_peer, shutdown_task(), and statistics.

Here is the call graph for this function:

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
struct GNUNET_MQ_Handle mq 
)
static

Callback called when a client connects to the service.

Parameters
clsclosure for the service
cthe new client that connected to the service
mqthe message queue used to send messages to the client
Returns
c

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

3502 {
3503  struct ConsensusSession *session = GNUNET_new (struct ConsensusSession);
3504 
3505  session->client = c;
3506  session->client_mq = mq;
3508  sessions_tail,
3509  session);
3510  return session;
3511 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static struct ConsensusSession * sessions_tail
Linked list of sessions this peer participates in.

References ConsensusSession::client, ConsensusSession::client_mq, GNUNET_CONTAINER_DLL_insert, GNUNET_new, mq, sessions_head, and sessions_tail.

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
void *  internal_cls 
)
static

Callback called when a client disconnected from the service.

Parameters
clsclosure for the service
cthe client that disconnected
internal_clsshould be equal to c

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

3525 {
3526  struct ConsensusSession *session = internal_cls;
3527 
3528  if (NULL != session->set_listener)
3529  {
3531  session->set_listener = NULL;
3532  }
3534  sessions_tail,
3535  session);
3536  while (session->set_handles_head)
3537  {
3538  struct SetHandle *sh = session->set_handles_head;
3539 
3540  session->set_handles_head = sh->next;
3541  GNUNET_SET_destroy (sh->h);
3542  GNUNET_free (sh);
3543  }
3544  GNUNET_free (session);
3545 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1010

References GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_SET_destroy(), GNUNET_SET_listen_cancel(), sessions_head, sessions_tail, ConsensusSession::set_handles_head, ConsensusSession::set_listener, and sh.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

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.

Variable Documentation

◆ sessions_head

struct ConsensusSession* sessions_head
static

Linked list of sessions this peer participates in.

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

Referenced by client_connect_cb(), client_disconnect_cb(), and handle_client_join().

◆ sessions_tail

struct ConsensusSession* sessions_tail
static

Linked list of sessions this peer participates in.

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

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Configuration of the consensus service.

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

Referenced by commit_set(), handle_client_join(), and run().

◆ my_peer

struct GNUNET_PeerIdentity my_peer
static

Peer that runs this service.

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

Referenced by handle_client_join(), initialize_session_peer_list(), and run().

◆ statistics

struct GNUNET_STATISTICS_Handle* statistics

Statistics handle.

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

Referenced by commit_set(), run(), and shutdown_task().