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

multi-peer set reconciliation More...

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

Go to the source code of this file.

Data Structures

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

Typedefs

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

Enumerations

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

Functions

static void finish_task (struct TaskEntry *task)
 
static void run_ready_steps (struct ConsensusSession *session)
 
static const char * phasename (uint16_t phase)
 
static const char * setname (uint16_t kind)
 
static const char * rfnname (uint16_t kind)
 
static const char * diffname (uint16_t kind)
 
static int send_to_client_iter (void *cls, const struct GNUNET_SET_Element *element)
 Send the final result set of the consensus to the client, element by element. More...
 
static struct SetEntrylookup_set (struct ConsensusSession *session, struct SetKey *key)
 
static struct DiffEntrylookup_diff (struct ConsensusSession *session, struct DiffKey *key)
 
static struct ReferendumEntrylookup_rfn (struct ConsensusSession *session, 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)
 
struct DiffEntrydiff_create ()
 
struct DiffEntrydiff_compose (struct DiffEntry *diff_1, struct DiffEntry *diff_2)
 
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. 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 (struct ConsensusSession *session, 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 void client_insert_done (void *cls)
 
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 208 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 39 of file gnunet-service-consensus.c.

39  {
44  VOTE_STAY = 0,
48  VOTE_ADD = 1,
52  VOTE_REMOVE = 2,
53 };
Vote that an element should be removed.
Vote that nothing should change.
Vote that an element should be added.

◆ EarlyStoppingPhase

Enumerator
EARLY_STOPPING_NONE 
EARLY_STOPPING_ONE_MORE 
EARLY_STOPPING_DONE 

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

◆ PhaseKind

enum PhaseKind
Enumerator
PHASE_KIND_ALL_TO_ALL 
PHASE_KIND_ALL_TO_ALL_2 
PHASE_KIND_GRADECAST_LEADER 
PHASE_KIND_GRADECAST_ECHO 
PHASE_KIND_GRADECAST_ECHO_GRADE 
PHASE_KIND_GRADECAST_CONFIRM 
PHASE_KIND_GRADECAST_CONFIRM_GRADE 
PHASE_KIND_APPLY_REP 

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

PHASE_KIND_FINISH 

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

◆ SetKind

enum SetKind
Enumerator
SET_KIND_NONE 
SET_KIND_CURRENT 
SET_KIND_LAST_GRADECAST 

Last result set from a gradecast.

SET_KIND_LEADER_PROPOSAL 
SET_KIND_ECHO_RESULT 

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

◆ DiffKind

enum DiffKind
Enumerator
DIFF_KIND_NONE 
DIFF_KIND_LEADER_PROPOSAL 
DIFF_KIND_LEADER_CONSENSUS 
DIFF_KIND_GRADECAST_RESULT 

Definition at line 163 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 170 of file gnunet-service-consensus.c.

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

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

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

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

2389 {
2391  task->is_finished = GNUNET_YES;
2392 
2393  task->step->finished_tasks++;
2394 
2396  "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
2397  task->step->session->local_peer_idx,
2398  debug_str_task_key(&task->key),
2399  (unsigned int)task->step->finished_tasks,
2400  (unsigned int)task->step->tasks_len);
2401 
2402  if (task->step->finished_tasks == task->step->tasks_len)
2403  finish_step(task->step);
2404 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int tasks_len
static void finish_step(struct Step *step)
struct TaskKey key
unsigned int finished_tasks
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
#define GNUNET_YES
Definition: gnunet_common.h:77
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 2347 of file gnunet-service-consensus.c.

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

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

2348 {
2349  struct Step *step;
2350 
2351  step = session->steps_head;
2352 
2353  while (NULL != step)
2354  {
2355  if ((GNUNET_NO == step->is_running) && (0 == step->pending_prereq) && (GNUNET_NO == step->is_finished))
2356  {
2357  size_t i;
2358 
2359  GNUNET_assert(0 == step->finished_tasks);
2360 
2361 #ifdef GNUNET_EXTRA_LOGGING
2362  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "P%u: Running step `%s' of round %d with %d tasks and %d subordinates\n",
2363  session->local_peer_idx,
2364  step->debug_name,
2365  step->round, step->tasks_len, step->subordinates_len);
2366 #endif
2367 
2368  step->is_running = GNUNET_YES;
2369  for (i = 0; i < step->tasks_len; i++)
2370  start_task(session, step->tasks[i]);
2371 
2372  /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
2373  if ((step->finished_tasks == step->tasks_len) && (GNUNET_NO == step->is_finished))
2374  finish_step(step);
2375 
2376  /* Running the next ready steps will be triggered by task completion */
2377  return;
2378  }
2379  step = step->next;
2380  }
2381 
2382  return;
2383 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int tasks_len
struct Step * next
All steps of one session are in a linked list for easier deallocation.
size_t pending_prereq
Counter for the prerequisites of this step.
static void finish_step(struct Step *step)
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskEntry ** tasks
Tasks that this step is composed of.
unsigned int is_finished
unsigned int round
unsigned int finished_tasks
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
unsigned int is_running
#define GNUNET_YES
Definition: gnunet_common.h:77
static void start_task(struct ConsensusSession *session, struct TaskEntry *task)
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ phasename()

static const char* phasename ( uint16_t  phase)
static

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

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

Referenced by diffname().

530 {
531  switch (phase)
532  {
533  case PHASE_KIND_ALL_TO_ALL: return "ALL_TO_ALL";
534 
535  case PHASE_KIND_ALL_TO_ALL_2: return "ALL_TO_ALL_2";
536 
537  case PHASE_KIND_FINISH: return "FINISH";
538 
539  case PHASE_KIND_GRADECAST_LEADER: return "GRADECAST_LEADER";
540 
541  case PHASE_KIND_GRADECAST_ECHO: return "GRADECAST_ECHO";
542 
543  case PHASE_KIND_GRADECAST_ECHO_GRADE: return "GRADECAST_ECHO_GRADE";
544 
545  case PHASE_KIND_GRADECAST_CONFIRM: return "GRADECAST_CONFIRM";
546 
547  case PHASE_KIND_GRADECAST_CONFIRM_GRADE: return "GRADECAST_CONFIRM_GRADE";
548 
549  case PHASE_KIND_APPLY_REP: return "APPLY_REP";
550 
551  default: return "(unknown)";
552  }
553 }
static unsigned int phase
Processing stage that we are in.
Definition: gnunet-arm.c:109
Apply a repetition of the all-to-all gradecast to the current set.
Here is the caller graph for this function:

◆ setname()

static const char* setname ( uint16_t  kind)
static

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

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

Referenced by diffname().

558 {
559  switch (kind)
560  {
561  case SET_KIND_CURRENT: return "CURRENT";
562 
563  case SET_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
564 
565  case SET_KIND_NONE: return "NONE";
566 
567  default: return "(unknown)";
568  }
569 }
Here is the caller graph for this function:

◆ rfnname()

static const char* rfnname ( uint16_t  kind)
static

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

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

Referenced by diffname().

573 {
574  switch (kind)
575  {
576  case RFN_KIND_NONE: return "NONE";
577 
578  case RFN_KIND_ECHO: return "ECHO";
579 
580  case RFN_KIND_CONFIRM: return "CONFIRM";
581 
582  default: return "(unknown)";
583  }
584 }
Here is the caller graph for this function:

◆ diffname()

static const char* diffname ( uint16_t  kind)
static

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

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

588 {
589  switch (kind)
590  {
591  case DIFF_KIND_NONE: return "NONE";
592 
593  case DIFF_KIND_LEADER_CONSENSUS: return "LEADER_CONSENSUS";
594 
595  case DIFF_KIND_GRADECAST_RESULT: return "GRADECAST_RESULT";
596 
597  case DIFF_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
598 
599  default: return "(unknown)";
600  }
601 }
Here is the call graph for this function:

◆ send_to_client_iter()

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

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

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

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

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

Referenced by task_start_finish().

681 {
682  struct TaskEntry *task = (struct TaskEntry *)cls;
683  struct ConsensusSession *session = task->step->session;
684  struct GNUNET_MQ_Envelope *ev;
685 
686  if (NULL != element)
687  {
689  const struct ConsensusElement *ce;
690 
692  ce = element->data;
693 
694  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "marker is %u\n", (unsigned)ce->marker);
695 
696  if (0 != ce->marker)
697  return GNUNET_YES;
698 
700  "P%d: sending element %s to client\n",
701  session->local_peer_idx,
702  debug_str_element(element));
703 
704  ev = GNUNET_MQ_msg_extra(m, element->size - sizeof(struct ConsensusElement),
706  m->element_type = ce->payload_type;
707  GNUNET_memcpy(&m[1], &ce[1], element->size - sizeof(struct ConsensusElement));
708  GNUNET_MQ_send(session->client_mq, ev);
709  }
710  else
711  {
713  "P%d: finished iterating elements for client\n",
714  session->local_peer_idx);
716  GNUNET_MQ_send(session->client_mq, ev);
717  }
718  return GNUNET_YES;
719 }
Consensus element, either marker or payload.
uint16_t payload_type
Payload element_type, only valid if this is not a marker element.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
const void * data
Actual data of the element.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
Message with an element.
Definition: consensus.h:71
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT
Sent by service when a new element is added.
struct GNUNET_MQ_Handle * client_mq
Queued messages to the client.
A consensus session consists of one local client and the remote authorities.
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:76
uint8_t marker
Is this a marker element?
uint16_t element_type
Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_NEW_ELEMENT.
Definition: consensus.h:82
Block type for consensus elements.
#define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE
Sent by service to client in order to signal a completed consensus conclusion.
uint16_t size
Number of bytes in the buffer pointed to by data.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:351
union TaskFuncCls cls
uint16_t element_type
Application-specific element type.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_set()

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

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

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

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

724 {
725  struct GNUNET_HashCode hash;
726 
728  "P%u: looking up set {%s}\n",
729  session->local_peer_idx,
730  debug_str_set_key(key));
731 
733  GNUNET_CRYPTO_hash(key, sizeof(struct SetKey), &hash);
734  return GNUNET_CONTAINER_multihashmap_get(session->setmap, &hash);
735 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CONTAINER_MultiHashMap * setmap
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_diff()

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

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

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

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

740 {
741  struct GNUNET_HashCode hash;
742 
744  "P%u: looking up diff {%s}\n",
745  session->local_peer_idx,
746  debug_str_diff_key(key));
747 
749  GNUNET_CRYPTO_hash(key, sizeof(struct DiffKey), &hash);
750  return GNUNET_CONTAINER_multihashmap_get(session->diffmap, &hash);
751 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
struct GNUNET_CONTAINER_MultiHashMap * diffmap
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_rfn()

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

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

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

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

756 {
757  struct GNUNET_HashCode hash;
758 
760  "P%u: looking up rfn {%s}\n",
761  session->local_peer_idx,
762  debug_str_rfn_key(key));
763 
765  GNUNET_CRYPTO_hash(key, sizeof(struct RfnKey), &hash);
766  return GNUNET_CONTAINER_multihashmap_get(session->rfnmap, &hash);
767 }
struct GNUNET_CONTAINER_MultiHashMap * rfnmap
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_insert()

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

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

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

Referenced by diff_compose(), and set_result_cb().

774 {
775  struct DiffElementInfo *di;
776  struct GNUNET_HashCode hash;
777 
778  GNUNET_assert((1 == weight) || (-1 == weight));
779 
781  "diff_insert with element size %u\n",
782  element->size);
783 
785  "hashing element\n");
786 
787  GNUNET_SET_element_hash(element, &hash);
788 
790  "hashed element\n");
791 
792  di = GNUNET_CONTAINER_multihashmap_get(diff->changes, &hash);
793 
794  if (NULL == di)
795  {
796  di = GNUNET_new(struct DiffElementInfo);
797  di->element = GNUNET_SET_element_dup(element);
800  &hash, di,
802  }
803 
804  di->weight = weight;
805 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
const struct GNUNET_SET_Element * element
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1241
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
struct GNUNET_CONTAINER_MultiHashMap * changes
int weight
Positive weight for &#39;add&#39;, negative weights for &#39;remove&#39;.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
uint16_t size
Number of bytes in the buffer pointed to by data.
#define GNUNET_log(kind,...)
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1218
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 809 of file gnunet-service-consensus.c.

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

Referenced by set_result_cb(), and task_start_grade().

811 {
812  GNUNET_assert(commit_peer < rfn->num_peers);
813 
814  rfn->peer_commited[commit_peer] = GNUNET_YES;
815 }
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static unsigned int num_peers
#define GNUNET_YES
Definition: gnunet_common.h:77
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 819 of file gnunet-service-consensus.c.

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

Referenced by set_result_cb().

821 {
822  GNUNET_assert(contested_peer < rfn->num_peers);
823 
824  rfn->peer_contested[contested_peer] = GNUNET_YES;
825 }
int * peer_contested
Contestation state of the peer.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static unsigned int num_peers
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ rfn_noncontested()

static uint16_t rfn_noncontested ( struct ReferendumEntry rfn)
static

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

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

Referenced by task_start_grade().

830 {
831  uint16_t i;
832  uint16_t ret;
833 
834  ret = 0;
835  for (i = 0; i < rfn->num_peers; i++)
836  if ((GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO == rfn->peer_contested[i]))
837  ret++;
838 
839  return ret;
840 }
int * peer_contested
Contestation state of the peer.
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_NO
Definition: gnunet_common.h:78
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_YES
Definition: gnunet_common.h:77
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 844 of file gnunet-service-consensus.c.

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

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

848 {
849  struct RfnElementInfo *ri;
850  struct GNUNET_HashCode hash;
851 
852  GNUNET_assert(voting_peer < rfn->num_peers);
853 
854  /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
855  since VOTE_KEEP is implicit in not voting. */
856  GNUNET_assert((VOTE_ADD == vote) || (VOTE_REMOVE == vote));
857 
858  GNUNET_SET_element_hash(element, &hash);
860 
861  if (NULL == ri)
862  {
863  ri = GNUNET_new(struct RfnElementInfo);
864  ri->element = GNUNET_SET_element_dup(element);
865  ri->votes = GNUNET_new_array(rfn->num_peers, int);
868  &hash, ri,
870  }
871 
872  ri->votes[voting_peer] = GNUNET_YES;
873  ri->proposal = vote;
874 }
Vote that an element should be removed.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1241
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static unsigned int num_peers
Vote that an element should be added.
const struct GNUNET_SET_Element * element
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1218
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_other_peer()

static uint16_t task_other_peer ( struct TaskEntry task)
static

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

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

Referenced by commit_set(), and set_result_cb().

879 {
880  uint16_t me = task->step->session->local_peer_idx;
881 
882  if (task->key.peer1 == me)
883  return task->key.peer2;
884  return task->key.peer1;
885 }
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
struct ConsensusSession * session
struct TaskKey key
struct Step * step
unsigned int local_peer_idx
Index of the local peer in the peers array.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
Here is the caller graph for this function:

◆ cmp_uint64_t()

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

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

Referenced by set_result_cb().

890 {
891  uint64_t a = *(uint64_t *)pa;
892  uint64_t b = *(uint64_t *)pb;
893 
894  if (a == b)
895  return 0;
896  if (a < b)
897  return -1;
898  return 1;
899 }
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 912 of file gnunet-service-consensus.c.

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

Referenced by set_listen_cb(), and task_start_reconcile().

916 {
917  struct TaskEntry *task = cls;
918  struct ConsensusSession *session = task->step->session;
919  struct SetEntry *output_set = NULL;
920  struct DiffEntry *output_diff = NULL;
921  struct ReferendumEntry *output_rfn = NULL;
922  unsigned int other_idx;
923  struct SetOpCls *setop;
924  const struct ConsensusElement *consensus_element = NULL;
925 
926  if (NULL != element)
927  {
929  "P%u: got element of type %u, status %u\n",
930  session->local_peer_idx,
931  (unsigned)element->element_type,
932  (unsigned)status);
934  consensus_element = element->data;
935  }
936 
937  setop = &task->cls.setop;
938 
939 
941  "P%u: got set result for {%s}, status %u\n",
942  session->local_peer_idx,
943  debug_str_task_key(&task->key),
944  status);
945 
946  if (GNUNET_NO == task->is_started)
947  {
948  GNUNET_break_op(0);
949  return;
950  }
951 
952  if (GNUNET_YES == task->is_finished)
953  {
954  GNUNET_break_op(0);
955  return;
956  }
957 
958  other_idx = task_other_peer(task);
959 
960  if (SET_KIND_NONE != setop->output_set.set_kind)
961  {
962  output_set = lookup_set(session, &setop->output_set);
963  GNUNET_assert(NULL != output_set);
964  }
965 
966  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
967  {
968  output_diff = lookup_diff(session, &setop->output_diff);
969  GNUNET_assert(NULL != output_diff);
970  }
971 
972  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
973  {
974  output_rfn = lookup_rfn(session, &setop->output_rfn);
975  GNUNET_assert(NULL != output_rfn);
976  }
977 
978  if (GNUNET_YES == session->peers_blacklisted[other_idx])
979  {
980  /* Peer might have been blacklisted
981  by a gradecast running in parallel, ignore elements from now */
983  return;
985  return;
986  }
987 
988  if ((NULL != consensus_element) && (0 != consensus_element->marker))
989  {
991  "P%u: got some marker\n",
992  session->local_peer_idx);
993  if ((GNUNET_YES == setop->transceive_contested) &&
994  (CONSENSUS_MARKER_CONTESTED == consensus_element->marker))
995  {
996  GNUNET_assert(NULL != output_rfn);
997  rfn_contest(output_rfn, task_other_peer(task));
998  return;
999  }
1000 
1001  if (CONSENSUS_MARKER_SIZE == consensus_element->marker)
1002  {
1004  "P%u: got size marker\n",
1005  session->local_peer_idx);
1006 
1007 
1008  struct ConsensusSizeElement *cse = (void *)consensus_element;
1009 
1010  if (cse->sender_index == other_idx)
1011  {
1012  if (NULL == session->first_sizes_received)
1013  session->first_sizes_received = GNUNET_new_array(session->num_peers, uint64_t);
1014  session->first_sizes_received[other_idx] = GNUNET_ntohll(cse->size);
1015 
1016  uint64_t *copy = GNUNET_memdup(session->first_sizes_received, sizeof(uint64_t) * session->num_peers);
1017  qsort(copy, session->num_peers, sizeof(uint64_t), cmp_uint64_t);
1018  session->lower_bound = copy[session->num_peers / 3 + 1];
1020  "P%u: lower bound %llu\n",
1021  session->local_peer_idx,
1022  (long long)session->lower_bound);
1023  GNUNET_free(copy);
1024  }
1025  return;
1026  }
1027 
1028  return;
1029  }
1030 
1031  switch (status)
1032  {
1034  GNUNET_assert(NULL != consensus_element);
1036  "Adding element in Task {%s}\n",
1037  debug_str_task_key(&task->key));
1038  if (NULL != output_set)
1039  {
1040  // FIXME: record pending adds, use callback
1041  GNUNET_SET_add_element(output_set->h,
1042  element,
1043  NULL,
1044  NULL);
1045 #ifdef GNUNET_EXTRA_LOGGING
1047  "P%u: adding element %s into set {%s} of task {%s}\n",
1048  session->local_peer_idx,
1049  debug_str_element(element),
1050  debug_str_set_key(&setop->output_set),
1051  debug_str_task_key(&task->key));
1052 #endif
1053  }
1054  if (NULL != output_diff)
1055  {
1056  diff_insert(output_diff, 1, element);
1057 #ifdef GNUNET_EXTRA_LOGGING
1059  "P%u: adding element %s into diff {%s} of task {%s}\n",
1060  session->local_peer_idx,
1061  debug_str_element(element),
1062  debug_str_diff_key(&setop->output_diff),
1063  debug_str_task_key(&task->key));
1064 #endif
1065  }
1066  if (NULL != output_rfn)
1067  {
1068  rfn_vote(output_rfn, task_other_peer(task), VOTE_ADD, element);
1069 #ifdef GNUNET_EXTRA_LOGGING
1071  "P%u: adding element %s into rfn {%s} of task {%s}\n",
1072  session->local_peer_idx,
1073  debug_str_element(element),
1074  debug_str_rfn_key(&setop->output_rfn),
1075  debug_str_task_key(&task->key));
1076 #endif
1077  }
1078  // XXX: add result to structures in task
1079  break;
1080 
1082  GNUNET_assert(NULL != consensus_element);
1083  if (GNUNET_YES == setop->do_not_remove)
1084  break;
1085  if (CONSENSUS_MARKER_CONTESTED == consensus_element->marker)
1086  break;
1088  "Removing element in Task {%s}\n",
1089  debug_str_task_key(&task->key));
1090  if (NULL != output_set)
1091  {
1092  // FIXME: record pending adds, use callback
1093  GNUNET_SET_remove_element(output_set->h,
1094  element,
1095  NULL,
1096  NULL);
1097 #ifdef GNUNET_EXTRA_LOGGING
1099  "P%u: removing element %s from set {%s} of task {%s}\n",
1100  session->local_peer_idx,
1101  debug_str_element(element),
1102  debug_str_set_key(&setop->output_set),
1103  debug_str_task_key(&task->key));
1104 #endif
1105  }
1106  if (NULL != output_diff)
1107  {
1108  diff_insert(output_diff, -1, element);
1109 #ifdef GNUNET_EXTRA_LOGGING
1111  "P%u: removing element %s from diff {%s} of task {%s}\n",
1112  session->local_peer_idx,
1113  debug_str_element(element),
1114  debug_str_diff_key(&setop->output_diff),
1115  debug_str_task_key(&task->key));
1116 #endif
1117  }
1118  if (NULL != output_rfn)
1119  {
1120  rfn_vote(output_rfn, task_other_peer(task), VOTE_REMOVE, element);
1121 #ifdef GNUNET_EXTRA_LOGGING
1123  "P%u: removing element %s from rfn {%s} of task {%s}\n",
1124  session->local_peer_idx,
1125  debug_str_element(element),
1126  debug_str_rfn_key(&setop->output_rfn),
1127  debug_str_task_key(&task->key));
1128 #endif
1129  }
1130  break;
1131 
1133  // XXX: check first if any changes to the underlying
1134  // set are still pending
1136  "P%u: Finishing setop in Task {%s} (%u/%u)\n",
1137  session->local_peer_idx,
1138  debug_str_task_key(&task->key),
1139  (unsigned int)task->step->finished_tasks,
1140  (unsigned int)task->step->tasks_len);
1141  if (NULL != output_rfn)
1142  {
1143  rfn_commit(output_rfn, task_other_peer(task));
1144  }
1145  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1146  {
1147  session->first_size = current_size;
1148  }
1149  finish_task(task);
1150  break;
1151 
1153  // XXX: cleanup
1154  GNUNET_break_op(0);
1155  finish_task(task);
1156  return;
1157 
1158  default:
1159  /* not reached */
1160  GNUNET_assert(0);
1161  }
1162 }
uint64_t first_size
Our set size from the first round.
Vote that an element should be removed.
static int cmp_uint64_t(const void *pa, const void *pb)
int GNUNET_SET_remove_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Remove an element to the given set.
Definition: set_api.c:729
Weighted diff.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:682
Consensus element, either marker or payload.
Element should be added to the result set of the remote peer, i.e.
static void rfn_contest(struct ReferendumEntry *rfn, uint16_t contested_peer)
Element should be added to the result set of the local peer, i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, struct RfnKey *key)
static void finish_task(struct TaskEntry *task)
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int num_peers
Number of other peers in the consensus.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
unsigned int tasks_len
Success, all elements have been sent (and received).
const void * data
Actual data of the element.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, struct DiffKey *key)
The other peer refused to to the operation with us, or something went wrong.
static void diff_insert(struct DiffEntry *diff, int weight, const struct GNUNET_SET_Element *element)
uint64_t lower_bound
Bounded Eppstein lower bound.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static uint16_t task_other_peer(struct TaskEntry *task)
struct TaskKey key
struct DiffKey output_diff
A consensus session consists of one local client and the remote authorities.
uint8_t marker
Is this a marker element?
Vote that an element should be added.
unsigned int finished_tasks
Block type for consensus elements.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
#define GNUNET_YES
Definition: gnunet_common.h:77
static void rfn_commit(struct ReferendumEntry *rfn, uint16_t commit_peer)
struct RfnKey output_rfn
union TaskFuncCls cls
struct SetKey output_set
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ commit_set()

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

Commit the appropriate set for a task.

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

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

Referenced by set_listen_cb(), and task_start_reconcile().

1324 {
1325  struct SetEntry *set;
1326  struct SetOpCls *setop = &task->cls.setop;
1327 
1328  GNUNET_assert(NULL != setop->op);
1329  set = lookup_set(session, &setop->input_set);
1330  GNUNET_assert(NULL != set);
1331 
1332  if ((GNUNET_YES == setop->transceive_contested) && (GNUNET_YES == set->is_contested))
1333  {
1334  struct GNUNET_SET_Element element;
1335  struct ConsensusElement ce = { 0 };
1337  element.data = &ce;
1338  element.size = sizeof(struct ConsensusElement);
1339  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1340  GNUNET_SET_add_element(set->h, &element, NULL, NULL);
1341  }
1342 
1343  if (PHASE_KIND_ALL_TO_ALL_2 == task->key.kind)
1344  {
1345  struct GNUNET_SET_Element element;
1346  struct ConsensusSizeElement cse = {
1347  .size = 0,
1348  .sender_index = 0
1349  };
1350  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "inserting size marker\n");
1352  cse.size = GNUNET_htonll(session->first_size);
1353  cse.sender_index = session->local_peer_idx;
1354  element.data = &cse;
1355  element.size = sizeof(struct ConsensusSizeElement);
1356  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1357  GNUNET_SET_add_element(set->h, &element, NULL, NULL);
1358  }
1359 
1360 #ifdef EVIL
1361  {
1362  unsigned int i;
1363  struct Evilness evil;
1364 
1365  get_evilness(session, &evil);
1366  if (EVILNESS_NONE != evil.type)
1367  {
1368  /* Useful for evaluation */
1370  "is evil",
1371  1,
1372  GNUNET_NO);
1373  }
1374  switch (evil.type)
1375  {
1376  case EVILNESS_CRAM_ALL:
1377  case EVILNESS_CRAM_LEAD:
1378  case EVILNESS_CRAM_ECHO:
1379  /* We're not cramming elements in the
1380  all-to-all round, since that would just
1381  add more elements to the result set, but
1382  wouldn't test robustness. */
1383  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1384  {
1385  GNUNET_SET_commit(setop->op, set->h);
1386  break;
1387  }
1388  if ((EVILNESS_CRAM_LEAD == evil.type) &&
1389  ((PHASE_KIND_GRADECAST_LEADER != task->key.kind) || SET_KIND_CURRENT != set->key.set_kind))
1390  {
1391  GNUNET_SET_commit(setop->op, set->h);
1392  break;
1393  }
1394  if (EVILNESS_CRAM_ECHO == evil.type && (PHASE_KIND_GRADECAST_ECHO != task->key.kind))
1395  {
1396  GNUNET_SET_commit(setop->op, set->h);
1397  break;
1398  }
1399  for (i = 0; i < evil.num; i++)
1400  {
1401  struct GNUNET_SET_Element element;
1402  struct ConsensusStuffedElement se = {
1403  .ce.payload_type = 0,
1404  .ce.marker = 0,
1405  };
1406  element.data = &se;
1407  element.size = sizeof(struct ConsensusStuffedElement);
1408  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1409 
1410  if (EVILNESS_SUB_REPLACEMENT == evil.subtype)
1411  {
1412  /* Always generate a new element. */
1414  }
1415  else if (EVILNESS_SUB_NO_REPLACEMENT == evil.subtype)
1416  {
1417  /* Always cram the same elements, derived from counter. */
1418  GNUNET_CRYPTO_hash(&i, sizeof(i), &se.rand);
1419  }
1420  else
1421  {
1422  GNUNET_assert(0);
1423  }
1424  GNUNET_SET_add_element(set->h, &element, NULL, NULL);
1425 #ifdef GNUNET_EXTRA_LOGGING
1427  "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n",
1428  session->local_peer_idx,
1429  debug_str_element(&element),
1430  debug_str_set_key(&setop->input_set),
1431  debug_str_task_key(&task->key));
1432 #endif
1433  }
1435  "# stuffed elements",
1436  evil.num,
1437  GNUNET_NO);
1438  GNUNET_SET_commit(setop->op, set->h);
1439  break;
1440 
1441  case EVILNESS_SLACK:
1443  "P%u: evil peer: slacking\n",
1444  (unsigned int)session->local_peer_idx);
1445 
1446  /* Do nothing. */
1447  case EVILNESS_SLACK_A2A:
1448  if ((PHASE_KIND_ALL_TO_ALL_2 == task->key.kind) ||
1449  (PHASE_KIND_ALL_TO_ALL == task->key.kind))
1450  {
1451  struct GNUNET_SET_Handle *empty_set;
1453  GNUNET_SET_commit(setop->op, empty_set);
1454  GNUNET_SET_destroy(empty_set);
1455  }
1456  else
1457  {
1458  GNUNET_SET_commit(setop->op, set->h);
1459  }
1460  break;
1461 
1462  case EVILNESS_NONE:
1463  GNUNET_SET_commit(setop->op, set->h);
1464  break;
1465  }
1466  }
1467 #else
1468  if (GNUNET_NO == session->peers_blacklisted[task_other_peer(task)])
1469  {
1470  GNUNET_SET_commit(setop->op, set->h);
1471  }
1472  else
1473  {
1474  /* For our testcases, we don't want the blacklisted
1475  peers to wait. */
1477  setop->op = NULL;
1478  finish_task(task);
1479  }
1480 #endif
1481 }
uint64_t first_size
Our set size from the first round.
struct GNUNET_STATISTICS_Handle * statistics
Statistics handle.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:682
Consensus element, either marker or payload.
uint16_t payload_type
Payload element_type, only valid if this is not a marker element.
Element stored in a set.
struct GNUNET_SET_Handle * GNUNET_SET_create(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op)
Create an empty set, supporting the specified operation.
Definition: set_api.c:652
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
static void finish_task(struct TaskEntry *task)
#define GNUNET_NO
Definition: gnunet_common.h:78
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:767
struct ConsensusElement ce
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:138
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
static uint16_t task_other_peer(struct TaskEntry *task)
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of the consensus service.
struct SetKey input_set
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
Opaque handle to a set.
Definition: set_api.c:48
struct TaskKey key
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
struct GNUNET_HashCode rand
int GNUNET_SET_commit(struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set)
Commit a set to be used with a set operation.
Definition: set_api.c:1123
uint8_t marker
Is this a marker element?
Block type for consensus elements.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:511
struct GNUNET_SET_OperationHandle * op
#define GNUNET_YES
Definition: gnunet_common.h:77
union TaskFuncCls cls
struct ConsensusElement ce
Set union, return all elements that are in at least one of the sets.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_diff()

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

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

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

Referenced by task_start_reconcile().

1487 {
1488  struct GNUNET_HashCode hash;
1489 
1490  GNUNET_assert(NULL != diff);
1491 
1492  GNUNET_CRYPTO_hash(&diff->key, sizeof(struct DiffKey), &hash);
1494  GNUNET_CONTAINER_multihashmap_put(session->diffmap, &hash, diff,
1496 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
struct DiffKey key
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_CONTAINER_MultiHashMap * diffmap
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_set()

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

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

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

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

1501 {
1502  struct GNUNET_HashCode hash;
1503 
1504  GNUNET_assert(NULL != set->h);
1505 
1507  "Putting set %s\n",
1508  debug_str_set_key(&set->key));
1509 
1510  GNUNET_CRYPTO_hash(&set->key, sizeof(struct SetKey), &hash);
1512  GNUNET_CONTAINER_multihashmap_put(session->setmap, &hash, set,
1514 }
If a value with the given key exists, replace it.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct GNUNET_CONTAINER_MultiHashMap * setmap
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_log(kind,...)
struct SetKey key
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_rfn()

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

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

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

Referenced by task_start_grade(), and task_start_reconcile().

1520 {
1521  struct GNUNET_HashCode hash;
1522 
1523  GNUNET_CRYPTO_hash(&rfn->key, sizeof(struct RfnKey), &hash);
1525  GNUNET_CONTAINER_multihashmap_put(session->rfnmap, &hash, rfn,
1527 }
struct GNUNET_CONTAINER_MultiHashMap * rfnmap
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_cancel_reconcile()

static void task_cancel_reconcile ( struct TaskEntry task)
static

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

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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

◆ apply_diff_to_rfn()

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

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

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

Referenced by task_start_grade().

1544 {
1546  struct DiffElementInfo *di;
1547 
1549 
1550  while (GNUNET_YES ==
1552  NULL,
1553  (const void **)&di))
1554  {
1555  if (di->weight > 0)
1556  {
1557  rfn_vote(rfn, voting_peer, VOTE_ADD, di->element);
1558  }
1559  if (di->weight < 0)
1560  {
1561  rfn_vote(rfn, voting_peer, VOTE_REMOVE, di->element);
1562  }
1563  }
1564 
1566 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct GNUNET_CONTAINER_MultiHashMap * changes
Vote that an element should be added.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_create()

struct DiffEntry* diff_create ( )

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

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

Referenced by diff_compose(), and task_start_reconcile().

1571 {
1572  struct DiffEntry *d = GNUNET_new(struct DiffEntry);
1573 
1575 
1576  return d;
1577 }
Weighted diff.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_CONTAINER_MultiHashMap * changes
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_compose()

struct DiffEntry* diff_compose ( struct DiffEntry diff_1,
struct DiffEntry diff_2 
)

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

References DiffEntry::changes, diff_create(), diff_insert(), GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), and GNUNET_YES.

1583 {
1584  struct DiffEntry *diff_new;
1586  struct DiffElementInfo *di;
1587 
1588  diff_new = diff_create();
1589 
1591  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next(iter, NULL, (const void **)&di))
1592  {
1593  diff_insert(diff_new, di->weight, di->element);
1594  }
1596 
1598  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next(iter, NULL, (const void **)&di))
1599  {
1600  diff_insert(diff_new, di->weight, di->element);
1601  }
1603 
1604  return diff_new;
1605 }
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
Weighted diff.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct GNUNET_CONTAINER_MultiHashMap * changes
static void diff_insert(struct DiffEntry *diff, int weight, const struct GNUNET_SET_Element *element)
struct DiffEntry * diff_create()
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the call graph for this function:

◆ rfn_create()

struct ReferendumEntry* rfn_create ( uint16_t  size)

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

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

Referenced by task_start_grade(), and task_start_reconcile().

1610 {
1611  struct ReferendumEntry *rfn;
1612 
1613  rfn = GNUNET_new(struct ReferendumEntry);
1615  rfn->peer_commited = GNUNET_new_array(size, int);
1616  rfn->peer_contested = GNUNET_new_array(size, int);
1617  rfn->num_peers = size;
1618 
1619  return rfn;
1620 }
int * peer_contested
Contestation state of the peer.
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static unsigned int size
Size of the "table".
Definition: peer.c:66
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_majority()

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

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

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

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

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

1643 {
1644  uint16_t votes_yes = 0;
1645  uint16_t num_commited = 0;
1646  uint16_t i;
1647 
1649  "Computing rfn majority for element %s of rfn {%s}\n",
1650  debug_str_element(ri->element),
1651  debug_str_rfn_key(&rfn->key));
1652 
1653  for (i = 0; i < rfn->num_peers; i++)
1654  {
1655  if (GNUNET_NO == rfn->peer_commited[i])
1656  continue;
1657  num_commited++;
1658 
1659  if (GNUNET_YES == ri->votes[i])
1660  votes_yes++;
1661  }
1662 
1663  if (votes_yes > (num_commited) / 2)
1664  {
1665  *ret_vote = ri->proposal;
1666  *ret_majority = votes_yes;
1667  }
1668  else
1669  {
1670  *ret_vote = VOTE_STAY;
1671  *ret_majority = num_commited - votes_yes;
1672  }
1673 }
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_NO
Definition: gnunet_common.h:78
Vote that nothing should change.
const struct GNUNET_SET_Element * element
#define GNUNET_log(kind,...)
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
#define GNUNET_YES
Definition: gnunet_common.h:77
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 1683 of file gnunet-service-consensus.c.

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

Referenced by create_set_copy_for_task().

1684 {
1685  struct SetCopyCls *scc = cls;
1686  struct TaskEntry *task = scc->task;
1687  struct SetKey dst_set_key = scc->dst_set_key;
1688  struct SetEntry *set;
1689  struct SetHandle *sh = GNUNET_new(struct SetHandle);
1690 
1691  sh->h = copy;
1693  task->step->session->set_handles_tail,
1694  sh);
1695 
1696  GNUNET_free(scc);
1697  set = GNUNET_new(struct SetEntry);
1698  set->h = copy;
1699  set->key = dst_set_key;
1700  put_set(task->step->session, set);
1701 
1702  task->start(task);
1703 }
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct SetHandle * set_handles_head
struct ConsensusSession * session
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct SetHandle * set_handles_tail
static struct SolverHandle * sh
struct SetKey dst_set_key
struct GNUNET_SET_Handle * h
struct Step * step
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
struct TaskEntry * task
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_set_copy_for_task()

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

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

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

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

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

1714 {
1715  struct SetEntry *src_set;
1716  struct SetCopyCls *scc = GNUNET_new(struct SetCopyCls);
1717 
1719  "Copying set {%s} to {%s} for task {%s}\n",
1720  debug_str_set_key(src_set_key),
1721  debug_str_set_key(dst_set_key),
1722  debug_str_task_key(&task->key));
1723 
1724  scc->task = task;
1725  scc->dst_set_key = *dst_set_key;
1726  src_set = lookup_set(task->step->session, src_set_key);
1727  GNUNET_assert(NULL != src_set);
1728  GNUNET_SET_copy_lazy(src_set->h,
1729  set_copy_cb,
1730  scc);
1731 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1189
static void set_copy_cb(void *cls, struct GNUNET_SET_Handle *copy)
struct SetKey dst_set_key
struct TaskKey key
struct Step * step
#define GNUNET_log(kind,...)
struct TaskEntry * task
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_mutation_done()

static void set_mutation_done ( void *  cls)
static

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

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

Referenced by task_start_apply_round(), and task_start_eval_echo().

1745 {
1746  struct SetMutationProgressCls *pc = cls;
1747 
1748  GNUNET_assert(pc->num_pending > 0);
1749 
1750  pc->num_pending--;
1751 
1752  if (0 == pc->num_pending)
1753  {
1754  struct TaskEntry *task = pc->task;
1755  GNUNET_free(pc);
1756  finish_task(task);
1757  }
1758 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void finish_task(struct TaskEntry *task)
struct TaskEntry * task
Task to finish once all changes are through.
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_finish_step_early()

static void try_finish_step_early ( struct Step step)
static

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

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

Referenced by task_start_apply_round().

1763 {
1764  unsigned int i;
1765 
1766  if (GNUNET_YES == step->is_running)
1767  return;
1768  if (GNUNET_YES == step->is_finished)
1769  return;
1770  if (GNUNET_NO == step->early_finishable)
1771  return;
1772 
1773  step->is_finished = GNUNET_YES;
1774 
1775 #ifdef GNUNET_EXTRA_LOGGING
1777  "Finishing step `%s' early.\n",
1778  step->debug_name);
1779 #endif
1780 
1781  for (i = 0; i < step->subordinates_len; i++)
1782  {
1783  GNUNET_assert(step->subordinates[i]->pending_prereq > 0);
1784  step->subordinates[i]->pending_prereq--;
1785 #ifdef GNUNET_EXTRA_LOGGING
1787  "Decreased pending_prereq to %u for step `%s'.\n",
1788  (unsigned int)step->subordinates[i]->pending_prereq,
1789  step->subordinates[i]->debug_name);
1790 #endif
1792  }
1793 
1794  // XXX: maybe schedule as task to avoid recursion?
1795  run_ready_steps(step->session);
1796 }
static void try_finish_step_early(struct Step *step)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_NO
Definition: gnunet_common.h:78
size_t pending_prereq
Counter for the prerequisites of this step.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
int early_finishable
When we&#39;re doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
unsigned int is_finished
static void run_ready_steps(struct ConsensusSession *session)
#define GNUNET_log(kind,...)
unsigned int is_running
#define GNUNET_YES
Definition: gnunet_common.h:77
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_step()

static void finish_step ( struct Step step)
static

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

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

Referenced by finish_task(), and run_ready_steps().

1801 {
1802  unsigned int i;
1803 
1804  GNUNET_assert(step->finished_tasks == step->tasks_len);
1807 
1808 #ifdef GNUNET_EXTRA_LOGGING
1810  "All tasks of step `%s' with %u subordinates finished.\n",
1811  step->debug_name,
1812  step->subordinates_len);
1813 #endif
1814 
1815  for (i = 0; i < step->subordinates_len; i++)
1816  {
1817  GNUNET_assert(step->subordinates[i]->pending_prereq > 0);
1818  step->subordinates[i]->pending_prereq--;
1819 #ifdef GNUNET_EXTRA_LOGGING
1821  "Decreased pending_prereq to %u for step `%s'.\n",
1822  (unsigned int)step->subordinates[i]->pending_prereq,
1823  step->subordinates[i]->debug_name);
1824 #endif
1825  }
1826 
1827  step->is_finished = GNUNET_YES;
1828 
1829  // XXX: maybe schedule as task to avoid recursion?
1830  run_ready_steps(step->session);
1831 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int tasks_len
size_t pending_prereq
Counter for the prerequisites of this step.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
unsigned int is_finished
static void run_ready_steps(struct ConsensusSession *session)
unsigned int finished_tasks
#define GNUNET_log(kind,...)
unsigned int is_running
#define GNUNET_YES
Definition: gnunet_common.h:77
unsigned int subordinates_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_apply_round()

static void task_start_apply_round ( struct TaskEntry task)
static

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

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

Parameters
taskthe task with context information

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

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

Referenced by construct_task_graph().

1843 {
1844  struct ConsensusSession *session = task->step->session;
1845  struct SetKey sk_in;
1846  struct SetKey sk_out;
1847  struct RfnKey rk_in;
1848  struct SetEntry *set_out;
1849  struct ReferendumEntry *rfn_in;
1851  struct RfnElementInfo *ri;
1852  struct SetMutationProgressCls *progress_cls;
1853  uint16_t worst_majority = UINT16_MAX;
1854 
1855  sk_in = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition };
1856  rk_in = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1857  sk_out = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition + 1 };
1858 
1859  set_out = lookup_set(session, &sk_out);
1860  if (NULL == set_out)
1861  {
1862  create_set_copy_for_task(task, &sk_in, &sk_out);
1863  return;
1864  }
1865 
1866  rfn_in = lookup_rfn(session, &rk_in);
1867  GNUNET_assert(NULL != rfn_in);
1868 
1869  progress_cls = GNUNET_new(struct SetMutationProgressCls);
1870  progress_cls->task = task;
1871 
1873 
1874  while (GNUNET_YES ==
1876  NULL,
1877  (const void **)&ri))
1878  {
1879  uint16_t majority_num;
1880  enum ReferendumVote majority_vote;
1881 
1882  rfn_majority(rfn_in, ri, &majority_num, &majority_vote);
1883 
1884  if (worst_majority > majority_num)
1885  worst_majority = majority_num;
1886 
1887  switch (majority_vote)
1888  {
1889  case VOTE_ADD:
1890  progress_cls->num_pending++;
1892  GNUNET_SET_add_element(set_out->h,
1893  ri->element,
1895  progress_cls));
1897  "P%u: apply round: adding element %s with %u-majority.\n",
1898  session->local_peer_idx,
1899  debug_str_element(ri->element), majority_num);
1900  break;
1901 
1902  case VOTE_REMOVE:
1903  progress_cls->num_pending++;
1905  GNUNET_SET_remove_element(set_out->h,
1906  ri->element,
1908  progress_cls));
1910  "P%u: apply round: deleting element %s with %u-majority.\n",
1911  session->local_peer_idx,
1912  debug_str_element(ri->element), majority_num);
1913  break;
1914 
1915  case VOTE_STAY:
1917  "P%u: apply round: keeping element %s with %u-majority.\n",
1918  session->local_peer_idx,
1919  debug_str_element(ri->element), majority_num);
1920  // do nothing
1921  break;
1922 
1923  default:
1924  GNUNET_assert(0);
1925  break;
1926  }
1927  }
1928 
1929  if (0 == progress_cls->num_pending)
1930  {
1931  // call closure right now, no pending ops
1932  GNUNET_free(progress_cls);
1933  finish_task(task);
1934  }
1935 
1936  {
1937  uint16_t thresh = (session->num_peers / 3) * 2;
1938 
1939  if (worst_majority >= thresh)
1940  {
1941  switch (session->early_stopping)
1942  {
1943  case EARLY_STOPPING_NONE:
1946  "P%u: Stopping early (after one more superround)\n",
1947  session->local_peer_idx);
1948  break;
1949 
1951  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "P%u: finishing steps due to early finish\n",
1952  session->local_peer_idx);
1954  {
1955  struct Step *step;
1956  for (step = session->steps_head; NULL != step; step = step->next)
1957  try_finish_step_early(step);
1958  }
1959  break;
1960 
1961  case EARLY_STOPPING_DONE:
1962  /* We shouldn't be here anymore after early stopping */
1963  GNUNET_break(0);
1964  break;
1965 
1966  default:
1967  GNUNET_assert(0);
1968  break;
1969  }
1970  }
1971  else if (EARLY_STOPPING_NONE != session->early_stopping)
1972  {
1973  // Our assumption about the number of bad peers
1974  // has been broken.
1975  GNUNET_break_op(0);
1976  }
1977  else
1978  {
1979  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "P%u: NOT finishing early (majority not good enough)\n",
1980  session->local_peer_idx);
1981  }
1982  }
1984 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
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:729
static void try_finish_step_early(struct Step *step)
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:682
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, struct RfnKey *key)
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct Step * next
All steps of one session are in a linked list for easier deallocation.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct TaskEntry * task
Task to finish once all changes are through.
Vote that nothing should change.
struct TaskKey key
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void set_mutation_done(void *cls)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
int early_stopping
State of our early stopping scheme.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_grade()

static void task_start_grade ( struct TaskEntry task)
static

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

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

Referenced by construct_task_graph_gradecast().

1989 {
1990  struct ConsensusSession *session = task->step->session;
1991  struct ReferendumEntry *output_rfn;
1992  struct ReferendumEntry *input_rfn;
1993  struct DiffEntry *input_diff;
1994  struct RfnKey rfn_key;
1995  struct DiffKey diff_key;
1997  struct RfnElementInfo *ri;
1998  unsigned int gradecast_confidence = 2;
1999 
2000  rfn_key = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
2001  output_rfn = lookup_rfn(session, &rfn_key);
2002  if (NULL == output_rfn)
2003  {
2004  output_rfn = rfn_create(session->num_peers);
2005  output_rfn->key = rfn_key;
2006  put_rfn(session, output_rfn);
2007  }
2008 
2009  diff_key = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, task->key.repetition, task->key.leader };
2010  input_diff = lookup_diff(session, &diff_key);
2011  GNUNET_assert(NULL != input_diff);
2012 
2013  rfn_key = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition, task->key.leader };
2014  input_rfn = lookup_rfn(session, &rfn_key);
2015  GNUNET_assert(NULL != input_rfn);
2016 
2018 
2019  apply_diff_to_rfn(input_diff, output_rfn, task->key.leader, session->num_peers);
2020 
2021  while (GNUNET_YES ==
2023  NULL,
2024  (const void **)&ri))
2025  {
2026  uint16_t majority_num;
2027  enum ReferendumVote majority_vote;
2028 
2029  // XXX: we need contested votes and non-contested votes here
2030  rfn_majority(input_rfn, ri, &majority_num, &majority_vote);
2031 
2032  if (majority_num <= session->num_peers / 3)
2033  majority_vote = VOTE_REMOVE;
2034 
2035  switch (majority_vote)
2036  {
2037  case VOTE_STAY:
2038  break;
2039 
2040  case VOTE_ADD:
2041  rfn_vote(output_rfn, task->key.leader, VOTE_ADD, ri->element);
2042  break;
2043 
2044  case VOTE_REMOVE:
2045  rfn_vote(output_rfn, task->key.leader, VOTE_REMOVE, ri->element);
2046  break;
2047 
2048  default:
2049  GNUNET_assert(0);
2050  break;
2051  }
2052  }
2054 
2055  {
2056  uint16_t noncontested;
2057  noncontested = rfn_noncontested(input_rfn);
2058  if (noncontested < (session->num_peers / 3) * 2)
2059  {
2060  gradecast_confidence = GNUNET_MIN(1, gradecast_confidence);
2061  }
2062  if (noncontested < (session->num_peers / 3) + 1)
2063  {
2064  gradecast_confidence = 0;
2065  }
2066  }
2067 
2068  if (gradecast_confidence >= 1)
2069  rfn_commit(output_rfn, task->key.leader);
2070 
2071  if (gradecast_confidence <= 1)
2072  session->peers_blacklisted[task->key.leader] = GNUNET_YES;
2073 
2074  finish_task(task);
2075 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
Weighted diff.
static void apply_diff_to_rfn(struct DiffEntry *diff, struct ReferendumEntry *rfn, uint16_t voting_peer, uint16_t num_peers)
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
struct ReferendumEntry * rfn_create(uint16_t size)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, struct RfnKey *key)
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
int * peers_blacklisted
Array of peers with length &#39;num_peers&#39;.
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, struct DiffKey *key)
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
Vote that nothing should change.
struct TaskKey key
static uint16_t rfn_noncontested(struct ReferendumEntry *rfn)
static unsigned int num_peers
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
int16_t leader
Leader in the gradecast phase.
struct Step * step
#define GNUNET_YES
Definition: gnunet_common.h:77
static void rfn_commit(struct ReferendumEntry *rfn, uint16_t commit_peer)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
static void rfn_vote(struct ReferendumEntry *rfn, uint16_t voting_peer, enum ReferendumVote vote, const struct GNUNET_SET_Element *element)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_reconcile()

static void task_start_reconcile ( struct TaskEntry task)
static

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2080 {
2081  struct SetEntry *input;
2082  struct SetOpCls *setop = &task->cls.setop;
2083  struct ConsensusSession *session = task->step->session;
2084 
2085  input = lookup_set(session, &setop->input_set);
2086  GNUNET_assert(NULL != input);
2087  GNUNET_assert(NULL != input->h);
2088 
2089  /* We create the outputs for the operation here
2090  (rather than in the set operation callback)
2091  because we want something valid in there, even
2092  if the other peer doesn't talk to us */
2093 
2094  if (SET_KIND_NONE != setop->output_set.set_kind)
2095  {
2096  /* If we don't have an existing output set,
2097  we clone the input set. */
2098  if (NULL == lookup_set(session, &setop->output_set))
2099  {
2100  create_set_copy_for_task(task, &setop->input_set, &setop->output_set);
2101  return;
2102  }
2103  }
2104 
2105  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
2106  {
2107  if (NULL == lookup_rfn(session, &setop->output_rfn))
2108  {
2109  struct ReferendumEntry *rfn;
2110 
2112  "P%u: output rfn <%s> missing, creating.\n",
2113  session->local_peer_idx,
2114  debug_str_rfn_key(&setop->output_rfn));
2115 
2116  rfn = rfn_create(session->num_peers);
2117  rfn->key = setop->output_rfn;
2118  put_rfn(session, rfn);
2119  }
2120  }
2121 
2122  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
2123  {
2124  if (NULL == lookup_diff(session, &setop->output_diff))
2125  {
2126  struct DiffEntry *diff;
2127 
2128  diff = diff_create();
2129  diff->key = setop->output_diff;
2130  put_diff(session, diff);
2131  }
2132  }
2133 
2134  if ((task->key.peer1 == session->local_peer_idx) && (task->key.peer2 == session->local_peer_idx))
2135  {
2136  /* XXX: mark the corresponding rfn as commited if necessary */
2137  finish_task(task);
2138  return;
2139  }
2140 
2141  if (task->key.peer1 == session->local_peer_idx)
2142  {
2144 
2146  "P%u: Looking up set {%s} to run remote union\n",
2147  session->local_peer_idx,
2148  debug_str_set_key(&setop->input_set));
2149 
2150  rcm.header.type = htons(GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
2151  rcm.header.size = htons(sizeof(struct GNUNET_CONSENSUS_RoundContextMessage));
2152 
2153  rcm.kind = htons(task->key.kind);
2154  rcm.peer1 = htons(task->key.peer1);
2155  rcm.peer2 = htons(task->key.peer2);
2156  rcm.leader = htons(task->key.leader);
2157  rcm.repetition = htons(task->key.repetition);
2158  rcm.is_contested = htons(0);
2159 
2160  GNUNET_assert(NULL == setop->op);
2161  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "P%u: initiating set op with P%u, our set is %s\n",
2162  session->local_peer_idx, task->key.peer2, debug_str_set_key(&setop->input_set));
2163 
2164  struct GNUNET_SET_Option opts[] = {
2165  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2167  };
2168 
2169  // XXX: maybe this should be done while
2170  // setting up tasks alreays?
2171  setop->op = GNUNET_SET_prepare(&session->peers[task->key.peer2],
2172  &session->global_id,
2173  &rcm.header,
2175  opts,
2176  set_result_cb,
2177  task);
2178 
2179  commit_set(session, task);
2180  }
2181  else if (task->key.peer2 == session->local_peer_idx)
2182  {
2183  /* Wait for the other peer to contact us */
2184  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting set op with P%u\n",
2185  session->local_peer_idx, task->key.peer1);
2186 
2187  if (NULL != setop->op)
2188  {
2189  commit_set(session, task);
2190  }
2191  }
2192  else
2193  {
2194  /* We made an error while constructing the task graph. */
2195  GNUNET_assert(0);
2196  }
2197 }
#define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT
Abort a round, don&#39;t send requested elements anymore.
Weighted diff.
static void commit_set(struct ConsensusSession *session, struct TaskEntry *task)
Commit the appropriate set for a task.
int16_t repetition
Repetition of the gradecast phase.
static void put_diff(struct ConsensusSession *session, struct DiffEntry *diff)
struct ReferendumEntry * rfn_create(uint16_t size)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, struct RfnKey *key)
static void finish_task(struct TaskEntry *task)
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: set_api.c:808
Sent as context message for set reconciliation.
static struct DiffEntry * lookup_diff(struct ConsensusSession *session, struct DiffKey *key)
struct GNUNET_PeerIdentity * peers
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
uint64_t lower_bound
Bounded Eppstein lower bound.
struct DiffKey key
struct SetKey input_set
Client gets notified of the required changes for both the local and the remote set.
struct TaskKey key
struct GNUNET_HashCode global_id
Global consensus identification, computed from the session id and participating authorities.
Option for set operations.
struct DiffEntry * diff_create()
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
struct DiffKey output_diff
A consensus session consists of one local client and the remote authorities.
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
int16_t leader
Leader in the gradecast phase.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
struct GNUNET_SET_OperationHandle * op
struct RfnKey output_rfn
union TaskFuncCls cls
struct SetKey output_set
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_eval_echo()

static void task_start_eval_echo ( struct TaskEntry task)
static

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

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

Referenced by construct_task_graph_gradecast().

2202 {
2204  struct ReferendumEntry *input_rfn;
2205  struct RfnElementInfo *ri;
2206  struct SetEntry *output_set;
2207  struct SetMutationProgressCls *progress_cls;
2208  struct ConsensusSession *session = task->step->session;
2209  struct SetKey sk_in;
2210  struct SetKey sk_out;
2211  struct RfnKey rk_in;
2212 
2213  sk_in = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, task->key.repetition, task->key.leader };
2214  sk_out = (struct SetKey) { SET_KIND_ECHO_RESULT, task->key.repetition, task->key.leader };
2215  output_set = lookup_set(session, &sk_out);
2216  if (NULL == output_set)
2217  {
2218  create_set_copy_for_task(task, &sk_in, &sk_out);
2219  return;
2220  }
2221 
2222 
2223  {
2224  // FIXME: should be marked as a shallow copy, so
2225  // we can destroy everything correctly
2226  struct SetEntry *last_set = GNUNET_new(struct SetEntry);
2227  last_set->h = output_set->h;
2228  last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
2229  put_set(session, last_set);
2230  }
2231 
2233  "Evaluating referendum in Task {%s}\n",
2234  debug_str_task_key(&task->key));
2235 
2236  progress_cls = GNUNET_new(struct SetMutationProgressCls);
2237  progress_cls->task = task;
2238 
2239  rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition, task->key.leader };
2240  input_rfn = lookup_rfn(session, &rk_in);
2241 
2242  GNUNET_assert(NULL != input_rfn);
2243 
2245  GNUNET_assert(NULL != iter);
2246 
2247  while (GNUNET_YES ==
2249  NULL,
2250  (const void **)&ri))
2251  {
2252  enum ReferendumVote majority_vote;
2253  uint16_t majority_num;
2254 
2255  rfn_majority(input_rfn, ri, &majority_num, &majority_vote);
2256 
2257  if (majority_num < session->num_peers / 3)
2258  {
2259  /* It is not the case that all nonfaulty peers
2260  echoed the same value. Since we're doing a set reconciliation, we
2261  can't simply send "nothing" for the value. Thus we mark our 'confirm'
2262  reconciliation as contested. Other peers might not know that the
2263  leader is faulty, thus we still re-distribute in the confirmation
2264  round. */
2265  output_set->is_contested = GNUNET_YES;
2266  }
2267 
2268  switch (majority_vote)
2269  {
2270  case VOTE_ADD:
2271  progress_cls->num_pending++;
2273  GNUNET_SET_add_element(output_set->h,
2274  ri->element,
2276  progress_cls));
2277  break;
2278 
2279  case VOTE_REMOVE:
2280  progress_cls->num_pending++;
2282  GNUNET_SET_remove_element(output_set->h,
2283  ri->element,
2285  progress_cls));
2286  break;
2287 
2288  case VOTE_STAY:
2289  /* Nothing to do. */
2290  break;
2291 
2292  default:
2293  /* not reached */
2294  GNUNET_assert(0);
2295  }
2296  }
2297 
2299 
2300  if (0 == progress_cls->num_pending)
2301  {
2302  // call closure right now, no pending ops
2303  GNUNET_free(progress_cls);
2304  finish_task(task);
2305  }
2306 }
Vote that an element should be removed.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
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:729
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:682
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
static struct ReferendumEntry * lookup_rfn(struct ConsensusSession *session, struct RfnKey *key)
static void finish_task(struct TaskEntry *task)
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Last result set from a gradecast.
static void create_set_copy_for_task(struct TaskEntry *task, struct SetKey *src_set_key, struct SetKey *dst_set_key)
Call the start function of the given task again after we created a copy of the given set...
struct TaskEntry * task
Task to finish once all changes are through.
Vote that nothing should change.
struct TaskKey key
int is_contested
GNUNET_YES if the set resulted from applying a referendum with contested elements.
static unsigned int num_peers
A consensus session consists of one local client and the remote authorities.
Vote that an element should be added.
int16_t leader
Leader in the gradecast phase.
struct Step * step
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
static void set_mutation_done(void *cls)
static void rfn_majority(const struct ReferendumEntry *rfn, const struct RfnElementInfo *ri, uint16_t *ret_majority, enum ReferendumVote *ret_vote)
For a given majority, count what the outcome is (add/remove/keep), and give the number of peers that ...
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
struct SetKey key
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_start_finish()

static void task_start_finish ( struct TaskEntry task)
static

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

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

Referenced by construct_task_graph().

2311 {
2312  struct SetEntry *final_set;
2313  struct ConsensusSession *session = task->step->session;
2314 
2315  final_set = lookup_set(session, &task->cls.finish.input_set);
2316 
2317  GNUNET_assert(NULL != final_set);
2318 
2319 
2320  GNUNET_SET_iterate(final_set->h,
2322  task);
2323 }
struct FinishCls finish
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static struct SetEntry * lookup_set(struct ConsensusSession *session, struct SetKey *key)
struct SetKey input_set
A consensus session consists of one local client and the remote authorities.
struct Step * step
static int send_to_client_iter(void *cls, const struct GNUNET_SET_Element *element)
Send the final result set of the consensus to the client, element by element.
union TaskFuncCls cls
int GNUNET_SET_iterate(struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *iter_cls)
Iterate over all elements in the given set.
Definition: set_api.c:1167
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 2326 of file gnunet-service-consensus.c.

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

Referenced by run_ready_steps().

2327 {
2328  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "P%u: starting task {%s}\n", session->local_peer_idx, debug_str_task_key(&task->key));
2329 
2332  GNUNET_assert(NULL != task->start);
2333 
2334  task->start(task);
2335 
2336  task->is_started = GNUNET_YES;
2337 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct TaskKey key
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
#define GNUNET_YES
Definition: gnunet_common.h:77
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 2415 of file gnunet-service-consensus.c.

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

Referenced by handle_client_join().

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

◆ compute_global_id()

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

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

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

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

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

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

Referenced by handle_client_join().

2438 {
2439  const char *salt = "gnunet-service-consensus/session_id";
2440 
2442  GNUNET_CRYPTO_kdf(&session->global_id,
2443  sizeof(struct GNUNET_HashCode),
2444  salt,
2445  strlen(salt),
2446  session->peers,
2447  session->num_peers * sizeof(struct GNUNET_PeerIdentity),
2448  local_session_id,
2449  sizeof(struct GNUNET_HashCode),
2450  NULL));
2451 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_PeerIdentity * peers
A 512-bit hashcode.
struct GNUNET_HashCode global_id
Global consensus identification, computed from the session id and participating authorities.
The identity of the host (wraps the signing key of the peer).
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:91
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.

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

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

Referenced by initialize_session_peer_list().

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

◆ initialize_session_peer_list()

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

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

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

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

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

Referenced by handle_client_join().

2478 {
2479  const struct GNUNET_PeerIdentity *msg_peers
2480  = (const struct GNUNET_PeerIdentity *)&join_msg[1];
2481  int local_peer_in_list;
2482 
2483  session->num_peers = ntohl(join_msg->num_peers);
2484 
2485  /* Peers in the join message, may or may not include the local peer,
2486  Add it if it is missing. */
2487  local_peer_in_list = GNUNET_NO;
2488  for (unsigned int i = 0; i < session->num_peers; i++)
2489  {
2490  if (0 == GNUNET_memcmp(&msg_peers[i],
2491  &my_peer))
2492  {
2493  local_peer_in_list = GNUNET_YES;
2494  break;
2495  }
2496  }
2497  if (GNUNET_NO == local_peer_in_list)
2498  session->num_peers++;
2499 
2500  session->peers = GNUNET_new_array(session->num_peers,
2501  struct GNUNET_PeerIdentity);
2502  if (GNUNET_NO == local_peer_in_list)
2503  session->peers[session->num_peers - 1] = my_peer;
2504 
2505  GNUNET_memcpy(session->peers,
2506  msg_peers,
2507  ntohl(join_msg->num_peers) * sizeof(struct GNUNET_PeerIdentity));
2508  qsort(session->peers,
2509  session->num_peers,
2510  sizeof(struct GNUNET_PeerIdentity),
2511  &peer_id_cmp);
2512 }
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int peer_id_cmp(const void *h1, const void *h2)
Compare two peer identities.
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int num_peers
Number of other peers in the consensus.
static struct GNUNET_PeerIdentity my_peer
Peer that runs this service.
uint32_t num_peers
Number of peers (at the end of this message) that want to participate in the consensus.
Definition: consensus.h:47
struct GNUNET_PeerIdentity * peers
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
The identity of the host (wraps the signing key of the peer).
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_task()

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

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

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

Referenced by set_listen_cb().

2518 {
2519  struct GNUNET_HashCode hash;
2520 
2521 
2522  GNUNET_CRYPTO_hash(key, sizeof(struct TaskKey), &hash);
2523  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking up task hash %s\n",
2524  GNUNET_h2s(&hash));
2525  return GNUNET_CONTAINER_multihashmap_get(session->taskmap, &hash);
2526 }
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
struct GNUNET_CONTAINER_MultiHashMap * taskmap
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
Tuple of integers that together identify a task uniquely.
#define GNUNET_log(kind,...)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_listen_cb()

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

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

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

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

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

Referenced by handle_client_join().

2549 {
2550  struct ConsensusSession *session = cls;
2551  struct TaskKey tk;
2552  struct TaskEntry *task;
2554 
2555  if (NULL == context_msg)
2556  {
2557  GNUNET_break_op(0);
2558  return;
2559  }
2560 
2561  if (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT != ntohs(context_msg->type))
2562  {
2563  GNUNET_break_op(0);
2564  return;
2565  }
2566 
2567  if (sizeof(struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs(context_msg->size))
2568  {
2569  GNUNET_break_op(0);
2570  return;
2571  }
2572 
2573  cm = (struct GNUNET_CONSENSUS_RoundContextMessage *)context_msg;
2574 
2575  tk = ((struct TaskKey) {
2576  .kind = ntohs(cm->kind),
2577  .peer1 = ntohs(cm->peer1),
2578  .peer2 = ntohs(cm->peer2),
2579  .repetition = ntohs(cm->repetition),
2580  .leader = ntohs(cm->leader),
2581  });
2582 
2583  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2584  session->local_peer_idx, debug_str_task_key(&tk));
2585 
2586  task = lookup_task(session, &tk);
2587 
2588  if (NULL == task)
2589  {
2590  GNUNET_break_op(0);
2591  return;
2592  }
2593 
2594  if (GNUNET_YES == task->is_finished)
2595  {
2596  GNUNET_break_op(0);
2597  return;
2598  }
2599 
2600  if (task->key.peer2 != session->local_peer_idx)
2601  {
2602  /* We're being asked, so we must be thne 2nd peer. */
2603  GNUNET_break_op(0);
2604  return;
2605  }
2606 
2607  GNUNET_assert(!((task->key.peer1 == session->local_peer_idx) &&
2608  (task->key.peer2 == session->local_peer_idx)));
2609 
2610  struct GNUNET_SET_Option opts[] = {
2611  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2613  };
2614 
2615  task->cls.setop.op = GNUNET_SET_accept(request,
2617  opts,
2618  set_result_cb,
2619  task);
2620 
2621  /* If the task hasn't been started yet,
2622  we wait for that until we commit. */
2623 
2624  if (GNUNET_YES == task->is_started)
2625  {
2626  commit_set(session, task);
2627  }
2628 }
#define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT
Abort a round, don&#39;t send requested elements anymore.
static void commit_set(struct ConsensusSession *session, struct TaskEntry *task)
Commit the appropriate set for a task.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static struct TaskEntry * lookup_task(struct ConsensusSession *session, struct TaskKey *key)
Sent as context message for set reconciliation.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
int16_t peer2
Number of the second peer in canonical order.
uint64_t lower_bound
Bounded Eppstein lower bound.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
Client gets notified of the required changes for both the local and the remote set.
struct TaskKey key
Option for set operations.
int16_t leader
Leader in the gradecast phase.
A consensus session consists of one local client and the remote authorities.
Tuple of integers that together identify a task uniquely.
uint16_t kind
A value from &#39;enum PhaseKind&#39;.
static void set_result_cb(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
struct SetOpCls setop
struct GNUNET_SET_OperationHandle * op
#define GNUNET_YES
Definition: gnunet_common.h:77
union TaskFuncCls cls
int16_t peer1
Number of the first peer in canonical order.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen().
Definition: set_api.c:1080
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_task()

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

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2635 {
2636  struct GNUNET_HashCode round_hash;
2637  struct Step *s;
2638 
2639  GNUNET_assert(NULL != t->step);
2640 
2641  t = GNUNET_memdup(t, sizeof(struct TaskEntry));
2642 
2643  s = t->step;
2644 
2645  if (s->tasks_len == s->tasks_cap)
2646  {
2647  unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2649  s->tasks_cap,
2650  target_size);
2651  }
2652 
2653 #ifdef GNUNET_EXTRA_LOGGING
2654  GNUNET_assert(NULL != s->debug_name);
2655  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2656  debug_str_task_key(&t->key),
2657  s->debug_name);
2658 #endif
2659 
2660  s->tasks[s->tasks_len] = t;
2661  s->tasks_len++;
2662 
2663  GNUNET_CRYPTO_hash(&t->key, sizeof(struct TaskKey), &round_hash);
2665  GNUNET_CONTAINER_multihashmap_put(taskmap, &round_hash, t,
2667 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
unsigned int tasks_len
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskKey key
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct TaskEntry ** tasks
Tasks that this step is composed of.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Tuple of integers that together identify a task uniquely.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int tasks_cap
Here is the call graph for this function:
Here is the caller graph for this function:

◆ install_step_timeouts()

static void install_step_timeouts ( struct ConsensusSession session)
static

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

Referenced by handle_client_conclude().

2672 {
2673  /* Given the fully constructed task graph
2674  with rounds for tasks, we can give the tasks timeouts. */
2675 
2676  // unsigned int max_round;
2677 
2678  /* XXX: implement! */
2679 }
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 2687 of file gnunet-service-consensus.c.

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2688 {
2689  uint16_t a;
2690  uint16_t b;
2691 
2692  GNUNET_assert(*p1 < n);
2693  GNUNET_assert(*p2 < n);
2694 
2695  if (*p1 < *p2)
2696  {
2697  a = *p1;
2698  b = *p2;
2699  }
2700  else
2701  {
2702  a = *p2;
2703  b = *p1;
2704  }
2705 
2706  /* For uniformly random *p1, *p2,
2707  this condition is true with 50% chance */
2708  if (((b - a) + n) % n <= n / 2)
2709  {
2710  *p1 = a;
2711  *p2 = b;
2712  }
2713  else
2714  {
2715  *p1 = b;
2716  *p2 = a;
2717  }
2718 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Here is the caller graph for this function:

◆ step_depend_on()

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

Record dep as a dependency of step.

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2726 {
2727  /* We're not checking for cyclic dependencies,
2728  but this is a cheap sanity check. */
2729  GNUNET_assert(step != dep);
2730  GNUNET_assert(NULL != step);
2731  GNUNET_assert(NULL != dep);
2732  GNUNET_assert(dep->round <= step->round);
2733 
2734 #ifdef GNUNET_EXTRA_LOGGING
2735  /* Make sure we have complete debugging information.
2736  Also checks that we don't screw up too badly
2737  constructing the task graph. */
2738  GNUNET_assert(NULL != step->debug_name);
2739  GNUNET_assert(NULL != dep->debug_name);
2741  "Making step `%s' depend on `%s'\n",
2742  step->debug_name,
2743  dep->debug_name);
2744 #endif
2745 
2746  if (dep->subordinates_cap == dep->subordinates_len)
2747  {
2748  unsigned int target_size = 3 * (dep->subordinates_cap + 1) / 2;
2750  dep->subordinates_cap,
2751  target_size);
2752  }
2753 
2755 
2756  dep->subordinates[dep->subordinates_len] = step;
2757  dep->subordinates_len++;
2758 
2759  step->pending_prereq++;
2760 }
unsigned int subordinates_cap
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
size_t pending_prereq
Counter for the prerequisites of this step.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
struct Step ** subordinates
char * debug_name
Human-readable name for the task, used for debugging.
unsigned int round
#define GNUNET_log(kind,...)
unsigned int subordinates_len
Here is the caller graph for this function:

◆ create_step()

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

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2765 {
2766  struct Step *step;
2767 
2768  step = GNUNET_new(struct Step);
2769  step->session = session;
2770  step->round = round;
2773  session->steps_tail,
2774  step);
2775  return step;
2776 }
struct ConsensusSession * session
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int early_finishable
When we&#39;re doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
unsigned int round
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 2784 of file gnunet-service-consensus.c.

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

Referenced by construct_task_graph().

2789 {
2790  uint16_t n = session->num_peers;
2791  uint16_t me = session->local_peer_idx;
2792 
2793  uint16_t p1;
2794  uint16_t p2;
2795 
2796  /* The task we're currently setting up. */
2797  struct TaskEntry task;
2798 
2799  struct Step *step;
2800  struct Step *prev_step;
2801 
2802  uint16_t round;
2803 
2804  unsigned int k;
2805 
2806  round = step_before->round + 1;
2807 
2808  /* gcast step 1: leader disseminates */
2809 
2810  step = create_step(session, round, GNUNET_YES);
2811 
2812 #ifdef GNUNET_EXTRA_LOGGING
2813  GNUNET_asprintf(&step->debug_name, "disseminate leader %u rep %u", lead, rep);
2814 #endif
2815  step_depend_on(step, step_before);
2816 
2817  if (lead == me)
2818  {
2819  for (k = 0; k < n; k++)
2820  {
2821  if (k == me)
2822  continue;
2823  p1 = me;
2824  p2 = k;
2825  arrange_peers(&p1, &p2, n);
2826  task = ((struct TaskEntry) {
2827  .step = step,
2828  .start = task_start_reconcile,
2829  .cancel = task_cancel_reconcile,
2830  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep, me },
2831  });
2832  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2833  put_task(session->taskmap, &task);
2834  }
2835  /* We run this task to make sure that the leader
2836  has the stored the SET_KIND_LEADER set of himself,
2837  so it can participate in the rest of the gradecast
2838  without the code having to handle any special cases. */
2839  task = ((struct TaskEntry) {
2840  .step = step,
2841  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, me, me, rep, me },
2842  .start = task_start_reconcile,
2843  .cancel = task_cancel_reconcile,
2844  });
2845  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2846  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep, me };
2847  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, rep, me };
2848  put_task(session->taskmap, &task);
2849  }
2850  else
2851  {
2852  p1 = me;
2853  p2 = lead;
2854  arrange_peers(&p1, &p2, n);
2855  task = ((struct TaskEntry) {
2856  .step = step,
2857  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep, lead },
2858  .start = task_start_reconcile,
2859  .cancel = task_cancel_reconcile,
2860  });
2861  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2862  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep, lead };
2863  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, rep, lead };
2864  put_task(session->taskmap, &task);
2865  }
2866 
2867  /* gcast phase 2: echo */
2868  prev_step = step;
2869  round += 1;
2870  step = create_step(session, round, GNUNET_YES);
2871 #ifdef GNUNET_EXTRA_LOGGING
2872  GNUNET_asprintf(&step->debug_name, "echo leader %u rep %u", lead, rep);
2873 #endif
2874  step_depend_on(step, prev_step);
2875 
2876  for (k = 0; k < n; k++)
2877  {
2878  p1 = k;
2879  p2 = me;
2880  arrange_peers(&p1, &p2, n);
2881  task = ((struct TaskEntry) {
2882  .step = step,
2883  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO, p1, p2, rep, lead },
2884  .start = task_start_reconcile,
2885  .cancel = task_cancel_reconcile,
2886  });
2887  task.cls.setop.input_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep, lead };
2888  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_ECHO, rep, lead };
2889  put_task(session->taskmap, &task);
2890  }
2891 
2892  prev_step = step;
2893  /* Same round, since step only has local tasks */
2894  step = create_step(session, round, GNUNET_YES);
2895 #ifdef GNUNET_EXTRA_LOGGING
2896  GNUNET_asprintf(&step->debug_name, "echo grade leader %u rep %u", lead, rep);
2897 #endif
2898  step_depend_on(step, prev_step);
2899 
2900  arrange_peers(&p1, &p2, n);
2901  task = ((struct TaskEntry) {
2902  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO_GRADE, -1, -1, rep, lead },
2903  .step = step,
2904  .start = task_start_eval_echo
2905  });
2906  put_task(session->taskmap, &task);
2907 
2908  prev_step = step;
2909  round += 1;
2910  step = create_step(session, round, GNUNET_YES);
2911 #ifdef GNUNET_EXTRA_LOGGING
2912  GNUNET_asprintf(&step->debug_name, "confirm leader %u rep %u", lead, rep);
2913 #endif
2914  step_depend_on(step, prev_step);
2915 
2916  /* gcast phase 3: confirmation and grading */
2917  for (k = 0; k < n; k++)
2918  {
2919  p1 = k;
2920  p2 = me;
2921  arrange_peers(&p1, &p2, n);
2922  task = ((struct TaskEntry) {
2923  .step = step,
2924  .start = task_start_reconcile,
2925  .cancel = task_cancel_reconcile,
2926  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM, p1, p2, rep, lead },
2927  });
2928  task.cls.setop.input_set = (struct SetKey) { SET_KIND_ECHO_RESULT, rep, lead };
2929  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_CONFIRM, rep, lead };
2930  /* If there was at least one element in the echo round that was
2931  contested (i.e. it had no n-t majority), then we let the other peers
2932  know, and other peers let us know. The contested flag for each peer is
2933  stored in the rfn. */
2934  task.cls.setop.transceive_contested = GNUNET_YES;
2935  put_task(session->taskmap, &task);
2936  }
2937 
2938  prev_step = step;
2939  /* Same round, since step only has local tasks */
2940  step = create_step(session, round, GNUNET_YES);
2941 #ifdef GNUNET_EXTRA_LOGGING
2942  GNUNET_asprintf(&step->debug_name, "confirm grade leader %u rep %u", lead, rep);
2943 #endif
2944  step_depend_on(step, prev_step);
2945 
2946  task = ((struct TaskEntry) {
2947  .step = step,
2948  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM_GRADE, -1, -1, rep, lead },
2949  .start = task_start_grade,
2950  });
2951  put_task(session->taskmap, &task);
2952 
2953  step_depend_on(step_after, step);
2954 }
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static void task_start_reconcile(struct TaskEntry *task)
static void task_start_grade(struct TaskEntry *task)
static void arrange_peers(uint16_t *p1, uint16_t *p2, uint16_t n)
unsigned int num_peers
Number of other peers in the consensus.
struct GNUNET_CONTAINER_MultiHashMap * taskmap
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
static struct Step * create_step(struct ConsensusSession *session, int round, int early_finishable)
char * debug_name
Human-readable name for the task, used for debugging.
static void task_start_eval_echo(struct TaskEntry *task)
static void step_depend_on(struct Step *step, struct Step *dep)
Record dep as a dependency of step.
Tuple of integers that together identify a task uniquely.
unsigned int round
static void task_cancel_reconcile(struct TaskEntry *task)
struct Step * step
unsigned int local_peer_idx
Index of the local peer in the peers array.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void put_task(struct GNUNET_CONTAINER_MultiHashMap *taskmap, struct TaskEntry *t)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ construct_task_graph()

static void construct_task_graph ( struct ConsensusSession session)
static

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

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

Referenced by handle_client_join().

2959 {
2960  uint16_t n = session->num_peers;
2961  uint16_t t = n / 3;
2962 
2963  uint16_t me = session->local_peer_idx;
2964 
2965  /* The task we're currently setting up. */
2966  struct TaskEntry task;
2967 
2968  /* Current leader */
2969  unsigned int lead;
2970 
2971  struct Step *step;
2972  struct Step *prev_step;
2973 
2974  unsigned int round = 0;
2975 
2976  unsigned int i;
2977 
2978  // XXX: introduce first step,
2979  // where we wait for all insert acks
2980  // from the set service
2981 
2982  /* faster but brittle all-to-all */
2983 
2984  // XXX: Not implemented yet
2985 
2986  /* all-to-all step */
2987 
2988  step = create_step(session, round, GNUNET_NO);
2989 
2990 #ifdef GNUNET_EXTRA_LOGGING
2991  step->debug_name = GNUNET_strdup("all to all");
2992 #endif
2993 
2994  for (i = 0; i < n; i++)
2995  {
2996  uint16_t p1;
2997  uint16_t p2;
2998 
2999  p1 = me;
3000  p2 = i;
3001  arrange_peers(&p1, &p2, n);
3002  task = ((struct TaskEntry) {
3003  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL, p1, p2, -1, -1 },
3004  .step = step,
3005  .start = task_start_reconcile,
3006  .cancel = task_cancel_reconcile,
3007  });
3008  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3009  task.cls.setop.output_set = task.cls.setop.input_set;
3010  task.cls.setop.do_not_remove = GNUNET_YES;
3011  put_task(session->taskmap, &task);
3012  }
3013 
3014  round += 1;
3015  prev_step = step;
3016  step = create_step(session, round, GNUNET_NO);;
3017 #ifdef GNUNET_EXTRA_LOGGING
3018  step->debug_name = GNUNET_strdup("all to all 2");
3019 #endif
3020  step_depend_on(step, prev_step);
3021 
3022 
3023  for (i = 0; i < n; i++)
3024  {
3025  uint16_t p1;
3026  uint16_t p2;
3027 
3028  p1 = me;
3029  p2 = i;
3030  arrange_peers(&p1, &p2, n);
3031  task = ((struct TaskEntry) {
3032  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL_2, p1, p2, -1, -1 },
3033  .step = step,
3034  .start = task_start_reconcile,
3035  .cancel = task_cancel_reconcile,
3036  });
3037  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3038  task.cls.setop.output_set = task.cls.setop.input_set;
3039  task.cls.setop.do_not_remove = GNUNET_YES;
3040  put_task(session->taskmap, &task);
3041  }
3042 
3043  round += 1;
3044 
3045  prev_step = step;
3046  step = NULL;
3047 
3048 
3049 
3050  /* Byzantine union */
3051 
3052  /* sequential repetitions of the gradecasts */
3053  for (i = 0; i < t + 1; i++)
3054  {
3055  struct Step *step_rep_start;
3056  struct Step *step_rep_end;
3057 
3058  /* Every repetition is in a separate round. */
3059  step_rep_start = create_step(session, round, GNUNET_YES);
3060 #ifdef GNUNET_EXTRA_LOGGING
3061  GNUNET_asprintf(&step_rep_start->debug_name, "gradecast start rep %u", i);
3062 #endif
3063 
3064  step_depend_on(step_rep_start, prev_step);
3065 
3066  /* gradecast has three rounds */
3067  round += 3;
3068  step_rep_end = create_step(session, round, GNUNET_YES);
3069 #ifdef GNUNET_EXTRA_LOGGING
3070  GNUNET_asprintf(&step_rep_end->debug_name, "gradecast end rep %u", i);
3071 #endif
3072 
3073  /* parallel gradecasts */
3074  for (lead = 0; lead < n; lead++)
3075  construct_task_graph_gradecast(session, i, lead, step_rep_start, step_rep_end);
3076 
3077  task = ((struct TaskEntry) {
3078  .step = step_rep_end,
3079  .key = (struct TaskKey) { PHASE_KIND_APPLY_REP, -1, -1, i, -1 },
3080  .start = task_start_apply_round,
3081  });
3082