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

multi-peer set reconciliation More...

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

Go to the source code of this file.

Data Structures

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

Typedefs

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

Enumerations

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

Functions

static void finish_task (struct TaskEntry *task)
 
static void run_ready_steps (struct ConsensusSession *session)
 
static const char * phasename (uint16_t phase)
 
static const char * setname (uint16_t kind)
 
static const char * rfnname (uint16_t kind)
 
static const char * diffname (uint16_t kind)
 
static int send_to_client_iter (void *cls, const struct GNUNET_SET_Element *element)
 Send the final result set of the consensus to the client, element by element. More...
 
static struct SetEntrylookup_set (struct ConsensusSession *session, 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 221 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.

40 {
45  VOTE_STAY = 0,
49  VOTE_ADD = 1,
53  VOTE_REMOVE = 2,
54 };
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 57 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 141 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 159 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 171 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 179 of file gnunet-service-consensus.c.

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

Definition at line 2462 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().

2463 {
2464  GNUNET_assert (GNUNET_NO == task->is_finished);
2465  task->is_finished = GNUNET_YES;
2466 
2467  task->step->finished_tasks++;
2468 
2470  "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
2471  task->step->session->local_peer_idx,
2472  debug_str_task_key (&task->key),
2473  (unsigned int) task->step->finished_tasks,
2474  (unsigned int) task->step->tasks_len);
2475 
2476  if (task->step->finished_tasks == task->step->tasks_len)
2477  finish_step (task->step);
2478 }
#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 2419 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().

2420 {
2421  struct Step *step;
2422 
2423  step = session->steps_head;
2424 
2425  while (NULL != step)
2426  {
2427  if ((GNUNET_NO == step->is_running) && (0 == step->pending_prereq) &&
2428  (GNUNET_NO == step->is_finished))
2429  {
2430  size_t i;
2431 
2432  GNUNET_assert (0 == step->finished_tasks);
2433 
2434 #ifdef GNUNET_EXTRA_LOGGING
2436  "P%u: Running step `%s' of round %d with %d tasks and %d subordinates\n",
2437  session->local_peer_idx,
2438  step->debug_name,
2439  step->round, step->tasks_len, step->subordinates_len);
2440 #endif
2441 
2442  step->is_running = GNUNET_YES;
2443  for (i = 0; i < step->tasks_len; i++)
2444  start_task (session, step->tasks[i]);
2445 
2446  /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
2447  if ((step->finished_tasks == step->tasks_len) && (GNUNET_NO ==
2448  step->is_finished))
2449  finish_step (step);
2450 
2451  /* Running the next ready steps will be triggered by task completion */
2452  return;
2453  }
2454  step = step->next;
2455  }
2456 
2457  return;
2458 }
#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 549 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().

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

◆ setname()

static const char* setname ( uint16_t  kind)
static

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

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

Referenced by diffname().

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

◆ rfnname()

static const char* rfnname ( uint16_t  kind)
static

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

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

Referenced by diffname().

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

◆ diffname()

static const char* diffname ( uint16_t  kind)
static

Definition at line 609 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().

610 {
611  switch (kind)
612  {
613  case DIFF_KIND_NONE: return "NONE";
614 
615  case DIFF_KIND_LEADER_CONSENSUS: return "LEADER_CONSENSUS";
616 
617  case DIFF_KIND_GRADECAST_RESULT: return "GRADECAST_RESULT";
618 
619  case DIFF_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
620 
621  default: return "(unknown)";
622  }
623 }
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 706 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().

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

756 {
757  struct GNUNET_HashCode hash;
758 
760  "P%u: looking up set {%s}\n",
761  session->local_peer_idx,
762  debug_str_set_key (key));
763 
765  GNUNET_CRYPTO_hash (key, sizeof(struct SetKey), &hash);
766  return GNUNET_CONTAINER_multihashmap_get (session->setmap, &hash);
767 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CONTAINER_MultiHashMap * setmap
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
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 771 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().

772 {
773  struct GNUNET_HashCode hash;
774 
776  "P%u: looking up diff {%s}\n",
777  session->local_peer_idx,
778  debug_str_diff_key (key));
779 
781  GNUNET_CRYPTO_hash (key, sizeof(struct DiffKey), &hash);
782  return GNUNET_CONTAINER_multihashmap_get (session->diffmap, &hash);
783 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
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 787 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().

788 {
789  struct GNUNET_HashCode hash;
790 
792  "P%u: looking up rfn {%s}\n",
793  session->local_peer_idx,
794  debug_str_rfn_key (key));
795 
797  GNUNET_CRYPTO_hash (key, sizeof(struct RfnKey), &hash);
798  return GNUNET_CONTAINER_multihashmap_get (session->rfnmap, &hash);
799 }
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:48
A 512-bit hashcode.
#define GNUNET_log(kind,...)
unsigned int local_peer_idx
Index of the local peer in the peers array.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ diff_insert()

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

Definition at line 803 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().

806 {
807  struct DiffElementInfo *di;
808  struct GNUNET_HashCode hash;
809 
810  GNUNET_assert ((1 == weight) || (-1 == weight));
811 
813  "diff_insert with element size %u\n",
814  element->size);
815 
817  "hashing element\n");
818 
819  GNUNET_SET_element_hash (element, &hash);
820 
822  "hashed element\n");
823 
824  di = GNUNET_CONTAINER_multihashmap_get (diff->changes, &hash);
825 
826  if (NULL == di)
827  {
828  di = GNUNET_new (struct DiffElementInfo);
829  di->element = GNUNET_SET_element_dup (element);
832  &hash, di,
834  }
835 
836  di->weight = weight;
837 }
#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:1246
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
struct GNUNET_CONTAINER_MultiHashMap * changes
int weight
Positive weight for &#39;add&#39;, negative weights for &#39;remove&#39;.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
uint16_t size
Number of bytes in the buffer pointed to by data.
#define GNUNET_log(kind,...)
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1223
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_commit()

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

Definition at line 841 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().

843 {
844  GNUNET_assert (commit_peer < rfn->num_peers);
845 
846  rfn->peer_commited[commit_peer] = GNUNET_YES;
847 }
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 851 of file gnunet-service-consensus.c.

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

Referenced by set_result_cb().

853 {
854  GNUNET_assert (contested_peer < rfn->num_peers);
855 
856  rfn->peer_contested[contested_peer] = GNUNET_YES;
857 }
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 861 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().

862 {
863  uint16_t i;
864  uint16_t ret;
865 
866  ret = 0;
867  for (i = 0; i < rfn->num_peers; i++)
868  if ((GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO ==
869  rfn->peer_contested[i]))
870  ret++;
871 
872  return ret;
873 }
int * peer_contested
Contestation state of the peer.
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_NO
Definition: gnunet_common.h:78
#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 877 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().

881 {
882  struct RfnElementInfo *ri;
883  struct GNUNET_HashCode hash;
884 
885  GNUNET_assert (voting_peer < rfn->num_peers);
886 
887  /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
888  since VOTE_KEEP is implicit in not voting. */
889  GNUNET_assert ((VOTE_ADD == vote) || (VOTE_REMOVE == vote));
890 
891  GNUNET_SET_element_hash (element, &hash);
893 
894  if (NULL == ri)
895  {
896  ri = GNUNET_new (struct RfnElementInfo);
897  ri->element = GNUNET_SET_element_dup (element);
898  ri->votes = GNUNET_new_array (rfn->num_peers, int);
901  &hash, ri,
903  }
904 
905  ri->votes[voting_peer] = GNUNET_YES;
906  ri->proposal = vote;
907 }
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:1246
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
A 512-bit hashcode.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static unsigned int num_peers
Vote that an element should be added.
const struct GNUNET_SET_Element * element
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1223
#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 911 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().

912 {
913  uint16_t me = task->step->session->local_peer_idx;
914 
915  if (task->key.peer1 == me)
916  return task->key.peer2;
917  return task->key.peer1;
918 }
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 922 of file gnunet-service-consensus.c.

Referenced by set_result_cb().

923 {
924  uint64_t a = *(uint64_t *) pa;
925  uint64_t b = *(uint64_t *) pb;
926 
927  if (a == b)
928  return 0;
929  if (a < b)
930  return -1;
931  return 1;
932 }
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 945 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().

949 {
950  struct TaskEntry *task = cls;
951  struct ConsensusSession *session = task->step->session;
952  struct SetEntry *output_set = NULL;
953  struct DiffEntry *output_diff = NULL;
954  struct ReferendumEntry *output_rfn = NULL;
955  unsigned int other_idx;
956  struct SetOpCls *setop;
957  const struct ConsensusElement *consensus_element = NULL;
958 
959  if (NULL != element)
960  {
962  "P%u: got element of type %u, status %u\n",
963  session->local_peer_idx,
964  (unsigned) element->element_type,
965  (unsigned) status);
967  element->element_type);
968  consensus_element = element->data;
969  }
970 
971  setop = &task->cls.setop;
972 
973 
975  "P%u: got set result for {%s}, status %u\n",
976  session->local_peer_idx,
977  debug_str_task_key (&task->key),
978  status);
979 
980  if (GNUNET_NO == task->is_started)
981  {
982  GNUNET_break_op (0);
983  return;
984  }
985 
986  if (GNUNET_YES == task->is_finished)
987  {
988  GNUNET_break_op (0);
989  return;
990  }
991 
992  other_idx = task_other_peer (task);
993 
994  if (SET_KIND_NONE != setop->output_set.set_kind)
995  {
996  output_set = lookup_set (session, &setop->output_set);
997  GNUNET_assert (NULL != output_set);
998  }
999 
1000  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
1001  {
1002  output_diff = lookup_diff (session, &setop->output_diff);
1003  GNUNET_assert (NULL != output_diff);
1004  }
1005 
1006  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
1007  {
1008  output_rfn = lookup_rfn (session, &setop->output_rfn);
1009  GNUNET_assert (NULL != output_rfn);
1010  }
1011 
1012  if (GNUNET_YES == session->peers_blacklisted[other_idx])
1013  {
1014  /* Peer might have been blacklisted
1015  by a gradecast running in parallel, ignore elements from now */
1017  return;
1019  return;
1020  }
1021 
1022  if ((NULL != consensus_element) && (0 != consensus_element->marker))
1023  {
1025  "P%u: got some marker\n",
1026  session->local_peer_idx);
1027  if ((GNUNET_YES == setop->transceive_contested) &&
1028  (CONSENSUS_MARKER_CONTESTED == consensus_element->marker))
1029  {
1030  GNUNET_assert (NULL != output_rfn);
1031  rfn_contest (output_rfn, task_other_peer (task));
1032  return;
1033  }
1034 
1035  if (CONSENSUS_MARKER_SIZE == consensus_element->marker)
1036  {
1038  "P%u: got size marker\n",
1039  session->local_peer_idx);
1040 
1041 
1042  struct ConsensusSizeElement *cse = (void *) consensus_element;
1043 
1044  if (cse->sender_index == other_idx)
1045  {
1046  if (NULL == session->first_sizes_received)
1047  session->first_sizes_received = GNUNET_new_array (session->num_peers,
1048  uint64_t);
1049  session->first_sizes_received[other_idx] = GNUNET_ntohll (cse->size);
1050 
1051  uint64_t *copy = GNUNET_memdup (session->first_sizes_received,
1052  sizeof(uint64_t) * session->num_peers);
1053  qsort (copy, session->num_peers, sizeof(uint64_t), cmp_uint64_t);
1054  session->lower_bound = copy[session->num_peers / 3 + 1];
1056  "P%u: lower bound %llu\n",
1057  session->local_peer_idx,
1058  (long long) session->lower_bound);
1059  GNUNET_free (copy);
1060  }
1061  return;
1062  }
1063 
1064  return;
1065  }
1066 
1067  switch (status)
1068  {
1070  GNUNET_assert (NULL != consensus_element);
1072  "Adding element in Task {%s}\n",
1073  debug_str_task_key (&task->key));
1074  if (NULL != output_set)
1075  {
1076  // FIXME: record pending adds, use callback
1077  GNUNET_SET_add_element (output_set->h,
1078  element,
1079  NULL,
1080  NULL);
1081 #ifdef GNUNET_EXTRA_LOGGING
1083  "P%u: adding element %s into set {%s} of task {%s}\n",
1084  session->local_peer_idx,
1085  debug_str_element (element),
1086  debug_str_set_key (&setop->output_set),
1087  debug_str_task_key (&task->key));
1088 #endif
1089  }
1090  if (NULL != output_diff)
1091  {
1092  diff_insert (output_diff, 1, element);
1093 #ifdef GNUNET_EXTRA_LOGGING
1095  "P%u: adding element %s into diff {%s} of task {%s}\n",
1096  session->local_peer_idx,
1097  debug_str_element (element),
1098  debug_str_diff_key (&setop->output_diff),
1099  debug_str_task_key (&task->key));
1100 #endif
1101  }
1102  if (NULL != output_rfn)
1103  {
1104  rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element);
1105 #ifdef GNUNET_EXTRA_LOGGING
1107  "P%u: adding element %s into rfn {%s} of task {%s}\n",
1108  session->local_peer_idx,
1109  debug_str_element (element),
1110  debug_str_rfn_key (&setop->output_rfn),
1111  debug_str_task_key (&task->key));
1112 #endif
1113  }
1114  // XXX: add result to structures in task
1115  break;
1116 
1118  GNUNET_assert (NULL != consensus_element);
1119  if (GNUNET_YES == setop->do_not_remove)
1120  break;
1121  if (CONSENSUS_MARKER_CONTESTED == consensus_element->marker)
1122  break;
1124  "Removing element in Task {%s}\n",
1125  debug_str_task_key (&task->key));
1126  if (NULL != output_set)
1127  {
1128  // FIXME: record pending adds, use callback
1129  GNUNET_SET_remove_element (output_set->h,
1130  element,
1131  NULL,
1132  NULL);
1133 #ifdef GNUNET_EXTRA_LOGGING
1135  "P%u: removing element %s from set {%s} of task {%s}\n",
1136  session->local_peer_idx,
1137  debug_str_element (element),
1138  debug_str_set_key (&setop->output_set),
1139  debug_str_task_key (&task->key));
1140 #endif
1141  }
1142  if (NULL != output_diff)
1143  {
1144  diff_insert (output_diff, -1, element);
1145 #ifdef GNUNET_EXTRA_LOGGING
1147  "P%u: removing element %s from diff {%s} of task {%s}\n",
1148  session->local_peer_idx,
1149  debug_str_element (element),
1150  debug_str_diff_key (&setop->output_diff),
1151  debug_str_task_key (&task->key));
1152 #endif
1153  }
1154  if (NULL != output_rfn)
1155  {
1156  rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element);
1157 #ifdef GNUNET_EXTRA_LOGGING
1159  "P%u: removing element %s from rfn {%s} of task {%s}\n",
1160  session->local_peer_idx,
1161  debug_str_element (element),
1162  debug_str_rfn_key (&setop->output_rfn),
1163  debug_str_task_key (&task->key));
1164 #endif
1165  }
1166  break;
1167 
1169  // XXX: check first if any changes to the underlying
1170  // set are still pending
1172  "P%u: Finishing setop in Task {%s} (%u/%u)\n",
1173  session->local_peer_idx,
1174  debug_str_task_key (&task->key),
1175  (unsigned int) task->step->finished_tasks,
1176  (unsigned int) task->step->tasks_len);
1177  if (NULL != output_rfn)
1178  {
1179  rfn_commit (output_rfn, task_other_peer (task));
1180  }
1181  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1182  {
1183  session->first_size = current_size;
1184  }
1185  finish_task (task);
1186  break;
1187 
1189  // XXX: cleanup
1190  GNUNET_break_op (0);
1191  finish_task (task);
1192  return;
1193 
1194  default:
1195  /* not reached */
1196  GNUNET_assert (0);
1197  }
1198 }
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:734
Weighted diff.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
Consensus element, either marker or payload.
Element should be added to the result set of the remote peer, i.e.
static void rfn_contest(struct ReferendumEntry *rfn, uint16_t contested_peer)
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 1367 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().

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

1536 {
1537  struct GNUNET_HashCode hash;
1538 
1539  GNUNET_assert (NULL != diff);
1540 
1541  GNUNET_CRYPTO_hash (&diff->key, sizeof(struct DiffKey), &hash);
1543  GNUNET_CONTAINER_multihashmap_put (session->diffmap, &hash,
1544  diff,
1546 }
#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:48
struct DiffKey key
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_CONTAINER_MultiHashMap * diffmap
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_set()

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

Definition at line 1550 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().

1552 {
1553  struct GNUNET_HashCode hash;
1554 
1555  GNUNET_assert (NULL != set->h);
1556 
1558  "Putting set %s\n",
1559  debug_str_set_key (&set->key));
1560 
1561  GNUNET_CRYPTO_hash (&set->key, sizeof(struct SetKey), &hash);
1563  GNUNET_CONTAINER_multihashmap_put (session->setmap, &hash, set,
1565 }
If a value with the given key exists, replace it.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct GNUNET_CONTAINER_MultiHashMap * setmap
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
A 512-bit hashcode.
#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 1569 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().

1571 {
1572  struct GNUNET_HashCode hash;
1573 
1574  GNUNET_CRYPTO_hash (&rfn->key, sizeof(struct RfnKey), &hash);
1576  GNUNET_CONTAINER_multihashmap_put (session->rfnmap, &hash, rfn,
1578 }
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:48
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_cancel_reconcile()

static void task_cancel_reconcile ( struct TaskEntry task)
static

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

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

1583 {
1584  /* not implemented yet */
1585  GNUNET_assert (0);
1586 }
#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 1590 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().

1594 {
1596  struct DiffElementInfo *di;
1597 
1599 
1600  while (GNUNET_YES ==
1602  NULL,
1603  (const void **) &di))
1604  {
1605  if (di->weight > 0)
1606  {
1607  rfn_vote (rfn, voting_peer, VOTE_ADD, di->element);
1608  }
1609  if (di->weight < 0)
1610  {
1611  rfn_vote (rfn, voting_peer, VOTE_REMOVE, di->element);
1612  }
1613  }
1614 
1616 }
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 1620 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().

1621 {
1622  struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1623 
1625 
1626  return d;
1627 }
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 1631 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.

1633 {
1634  struct DiffEntry *diff_new;
1636  struct DiffElementInfo *di;
1637 
1638  diff_new = diff_create ();
1639 
1642  (const
1643  void **) &
1644  di))
1645  {
1646  diff_insert (diff_new, di->weight, di->element);
1647  }
1649 
1652  (const
1653  void **) &
1654  di))
1655  {
1656  diff_insert (diff_new, di->weight, di->element);
1657  }
1659 
1660  return diff_new;
1661 }
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 1665 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().

1666 {
1667  struct ReferendumEntry *rfn;
1668 
1669  rfn = GNUNET_new (struct ReferendumEntry);
1671  rfn->peer_commited = GNUNET_new_array (size, int);
1672  rfn->peer_contested = GNUNET_new_array (size, int);
1673  rfn->num_peers = size;
1674 
1675  return rfn;
1676 }
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:67
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rfn_majority()

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

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

Definition at line 1697 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().

1701 {
1702  uint16_t votes_yes = 0;
1703  uint16_t num_commited = 0;
1704  uint16_t i;
1705 
1707  "Computing rfn majority for element %s of rfn {%s}\n",
1708  debug_str_element (ri->element),
1709  debug_str_rfn_key (&rfn->key));
1710 
1711  for (i = 0; i < rfn->num_peers; i++)
1712  {
1713  if (GNUNET_NO == rfn->peer_commited[i])
1714  continue;
1715  num_commited++;
1716 
1717  if (GNUNET_YES == ri->votes[i])
1718  votes_yes++;
1719  }
1720 
1721  if (votes_yes > (num_commited) / 2)
1722  {
1723  *ret_vote = ri->proposal;
1724  *ret_majority = votes_yes;
1725  }
1726  else
1727  {
1728  *ret_vote = VOTE_STAY;
1729  *ret_majority = num_commited - votes_yes;
1730  }
1731 }
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 1742 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().

1743 {
1744  struct SetCopyCls *scc = cls;
1745  struct TaskEntry *task = scc->task;
1746  struct SetKey dst_set_key = scc->dst_set_key;
1747  struct SetEntry *set;
1748  struct SetHandle *sh = GNUNET_new (struct SetHandle);
1749 
1750  sh->h = copy;
1752  task->step->session->set_handles_tail,
1753  sh);
1754 
1755  GNUNET_free (scc);
1756  set = GNUNET_new (struct SetEntry);
1757  set->h = copy;
1758  set->key = dst_set_key;
1759  put_set (task->step->session, set);
1760 
1761  task->start (task);
1762 }
#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 1770 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().

1773 {
1774  struct SetEntry *src_set;
1775  struct SetCopyCls *scc = GNUNET_new (struct SetCopyCls);
1776 
1778  "Copying set {%s} to {%s} for task {%s}\n",
1779  debug_str_set_key (src_set_key),
1780  debug_str_set_key (dst_set_key),
1781  debug_str_task_key (&task->key));
1782 
1783  scc->task = task;
1784  scc->dst_set_key = *dst_set_key;
1785  src_set = lookup_set (task->step->session, src_set_key);
1786  GNUNET_assert (NULL != src_set);
1787  GNUNET_SET_copy_lazy (src_set->h,
1788  set_copy_cb,
1789  scc);
1790 }
#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:1194
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 1804 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().

1805 {
1806  struct SetMutationProgressCls *pc = cls;
1807 
1808  GNUNET_assert (pc->num_pending > 0);
1809 
1810  pc->num_pending--;
1811 
1812  if (0 == pc->num_pending)
1813  {
1814  struct TaskEntry *task = pc->task;
1815  GNUNET_free (pc);
1816  finish_task (task);
1817  }
1818 }
#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 1822 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().

1823 {
1824  unsigned int i;
1825 
1826  if (GNUNET_YES == step->is_running)
1827  return;
1828  if (GNUNET_YES == step->is_finished)
1829  return;
1830  if (GNUNET_NO == step->early_finishable)
1831  return;
1832 
1833  step->is_finished = GNUNET_YES;
1834 
1835 #ifdef GNUNET_EXTRA_LOGGING
1837  "Finishing step `%s' early.\n",
1838  step->debug_name);
1839 #endif
1840 
1841  for (i = 0; i < step->subordinates_len; i++)
1842  {
1843  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1844  step->subordinates[i]->pending_prereq--;
1845 #ifdef GNUNET_EXTRA_LOGGING
1847  "Decreased pending_prereq to %u for step `%s'.\n",
1848  (unsigned int) step->subordinates[i]->pending_prereq,
1849  step->subordinates[i]->debug_name);
1850 #endif
1852  }
1853 
1854  // XXX: maybe schedule as task to avoid recursion?
1855  run_ready_steps (step->session);
1856 }
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 1860 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().

1861 {
1862  unsigned int i;
1863 
1864  GNUNET_assert (step->finished_tasks == step->tasks_len);
1865  GNUNET_assert (GNUNET_YES == step->is_running);
1866  GNUNET_assert (GNUNET_NO == step->is_finished);
1867 
1868 #ifdef GNUNET_EXTRA_LOGGING
1870  "All tasks of step `%s' with %u subordinates finished.\n",
1871  step->debug_name,
1872  step->subordinates_len);
1873 #endif
1874 
1875  for (i = 0; i < step->subordinates_len; i++)
1876  {
1877  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1878  step->subordinates[i]->pending_prereq--;
1879 #ifdef GNUNET_EXTRA_LOGGING
1881  "Decreased pending_prereq to %u for step `%s'.\n",
1882  (unsigned int) step->subordinates[i]->pending_prereq,
1883  step->subordinates[i]->debug_name);
1884 #endif
1885  }
1886 
1887  step->is_finished = GNUNET_YES;
1888 
1889  // XXX: maybe schedule as task to avoid recursion?
1890  run_ready_steps (step->session);
1891 }
#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 1901 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().

1902 {
1903  struct ConsensusSession *session = task->step->session;
1904  struct SetKey sk_in;
1905  struct SetKey sk_out;
1906  struct RfnKey rk_in;
1907  struct SetEntry *set_out;
1908  struct ReferendumEntry *rfn_in;
1910  struct RfnElementInfo *ri;
1911  struct SetMutationProgressCls *progress_cls;
1912  uint16_t worst_majority = UINT16_MAX;
1913 
1914  sk_in = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition };
1915  rk_in = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1916  sk_out = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition + 1 };
1917 
1918  set_out = lookup_set (session, &sk_out);
1919  if (NULL == set_out)
1920  {
1921  create_set_copy_for_task (task, &sk_in, &sk_out);
1922  return;
1923  }
1924 
1925  rfn_in = lookup_rfn (session, &rk_in);
1926  GNUNET_assert (NULL != rfn_in);
1927 
1928  progress_cls = GNUNET_new (struct SetMutationProgressCls);
1929  progress_cls->task = task;
1930 
1932 
1933  while (GNUNET_YES ==
1935  NULL,
1936  (const void **) &ri))
1937  {
1938  uint16_t majority_num;
1939  enum ReferendumVote majority_vote;
1940 
1941  rfn_majority (rfn_in, ri, &majority_num, &majority_vote);
1942 
1943  if (worst_majority > majority_num)
1944  worst_majority = majority_num;
1945 
1946  switch (majority_vote)
1947  {
1948  case VOTE_ADD:
1949  progress_cls->num_pending++;
1951  GNUNET_SET_add_element (set_out->h,
1952  ri->element,
1954  progress_cls));
1956  "P%u: apply round: adding element %s with %u-majority.\n",
1957  session->local_peer_idx,
1958  debug_str_element (ri->element), majority_num);
1959  break;
1960 
1961  case VOTE_REMOVE:
1962  progress_cls->num_pending++;
1964  GNUNET_SET_remove_element (set_out->h,
1965  ri->element,
1967  progress_cls));
1969  "P%u: apply round: deleting element %s with %u-majority.\n",
1970  session->local_peer_idx,
1971  debug_str_element (ri->element), majority_num);
1972  break;
1973 
1974  case VOTE_STAY:
1976  "P%u: apply round: keeping element %s with %u-majority.\n",
1977  session->local_peer_idx,
1978  debug_str_element (ri->element), majority_num);
1979  // do nothing
1980  break;
1981 
1982  default:
1983  GNUNET_assert (0);
1984  break;
1985  }
1986  }
1987 
1988  if (0 == progress_cls->num_pending)
1989  {
1990  // call closure right now, no pending ops
1991  GNUNET_free (progress_cls);
1992  finish_task (task);
1993  }
1994 
1995  {
1996  uint16_t thresh = (session->num_peers / 3) * 2;
1997 
1998  if (worst_majority >= thresh)
1999  {
2000  switch (session->early_stopping)
2001  {
2002  case EARLY_STOPPING_NONE:
2005  "P%u: Stopping early (after one more superround)\n",
2006  session->local_peer_idx);
2007  break;
2008 
2011  "P%u: finishing steps due to early finish\n",
2012  session->local_peer_idx);
2014  {
2015  struct Step *step;
2016  for (step = session->steps_head; NULL != step; step = step->next)
2017  try_finish_step_early (step);
2018  }
2019  break;
2020 
2021  case EARLY_STOPPING_DONE:
2022  /* We shouldn't be here anymore after early stopping */
2023  GNUNET_break (0);
2024  break;
2025 
2026  default:
2027  GNUNET_assert (0);
2028  break;
2029  }
2030  }
2031  else if (EARLY_STOPPING_NONE != session->early_stopping)
2032  {
2033  // Our assumption about the number of bad peers
2034  // has been broken.
2035  GNUNET_break_op (0);
2036  }
2037  else
2038  {
2040  "P%u: NOT finishing early (majority not good enough)\n",
2041  session->local_peer_idx);
2042  }
2043  }
2045 }
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:734
static void try_finish_step_early(struct Step *step)
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static 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 2049 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().

2050 {
2051  struct ConsensusSession *session = task->step->session;
2052  struct ReferendumEntry *output_rfn;
2053  struct ReferendumEntry *input_rfn;
2054  struct DiffEntry *input_diff;
2055  struct RfnKey rfn_key;
2056  struct DiffKey diff_key;
2058  struct RfnElementInfo *ri;
2059  unsigned int gradecast_confidence = 2;
2060 
2061  rfn_key = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
2062  output_rfn = lookup_rfn (session, &rfn_key);
2063  if (NULL == output_rfn)
2064  {
2065  output_rfn = rfn_create (session->num_peers);
2066  output_rfn->key = rfn_key;
2067  put_rfn (session, output_rfn);
2068  }
2069 
2070  diff_key = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, task->key.repetition,
2071  task->key.leader };
2072  input_diff = lookup_diff (session, &diff_key);
2073  GNUNET_assert (NULL != input_diff);
2074 
2075  rfn_key = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2076  task->key.leader };
2077  input_rfn = lookup_rfn (session, &rfn_key);
2078  GNUNET_assert (NULL != input_rfn);
2079 
2081  input_rfn->rfn_elements);
2082 
2083  apply_diff_to_rfn (input_diff, output_rfn, task->key.leader,
2084  session->num_peers);
2085 
2086  while (GNUNET_YES ==
2088  NULL,
2089  (const void **) &ri))
2090  {
2091  uint16_t majority_num;
2092  enum ReferendumVote majority_vote;
2093 
2094  // XXX: we need contested votes and non-contested votes here
2095  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2096 
2097  if (majority_num <= session->num_peers / 3)
2098  majority_vote = VOTE_REMOVE;
2099 
2100  switch (majority_vote)
2101  {
2102  case VOTE_STAY:
2103  break;
2104 
2105  case VOTE_ADD:
2106  rfn_vote (output_rfn, task->key.leader, VOTE_ADD, ri->element);
2107  break;
2108 
2109  case VOTE_REMOVE:
2110  rfn_vote (output_rfn, task->key.leader, VOTE_REMOVE, ri->element);
2111  break;
2112 
2113  default:
2114  GNUNET_assert (0);
2115  break;
2116  }
2117  }
2119 
2120  {
2121  uint16_t noncontested;
2122  noncontested = rfn_noncontested (input_rfn);
2123  if (noncontested < (session->num_peers / 3) * 2)
2124  {
2125  gradecast_confidence = GNUNET_MIN (1, gradecast_confidence);
2126  }
2127  if (noncontested < (session->num_peers / 3) + 1)
2128  {
2129  gradecast_confidence = 0;
2130  }
2131  }
2132 
2133  if (gradecast_confidence >= 1)
2134  rfn_commit (output_rfn, task->key.leader);
2135 
2136  if (gradecast_confidence <= 1)
2137  session->peers_blacklisted[task->key.leader] = GNUNET_YES;
2138 
2139  finish_task (task);
2140 }
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 2144 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().

2145 {
2146  struct SetEntry *input;
2147  struct SetOpCls *setop = &task->cls.setop;
2148  struct ConsensusSession *session = task->step->session;
2149 
2150  input = lookup_set (session, &setop->input_set);
2151  GNUNET_assert (NULL != input);
2152  GNUNET_assert (NULL != input->h);
2153 
2154  /* We create the outputs for the operation here
2155  (rather than in the set operation callback)
2156  because we want something valid in there, even
2157  if the other peer doesn't talk to us */
2158 
2159  if (SET_KIND_NONE != setop->output_set.set_kind)
2160  {
2161  /* If we don't have an existing output set,
2162  we clone the input set. */
2163  if (NULL == lookup_set (session, &setop->output_set))
2164  {
2165  create_set_copy_for_task (task, &setop->input_set, &setop->output_set);
2166  return;
2167  }
2168  }
2169 
2170  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
2171  {
2172  if (NULL == lookup_rfn (session, &setop->output_rfn))
2173  {
2174  struct ReferendumEntry *rfn;
2175 
2177  "P%u: output rfn <%s> missing, creating.\n",
2178  session->local_peer_idx,
2179  debug_str_rfn_key (&setop->output_rfn));
2180 
2181  rfn = rfn_create (session->num_peers);
2182  rfn->key = setop->output_rfn;
2183  put_rfn (session, rfn);
2184  }
2185  }
2186 
2187  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
2188  {
2189  if (NULL == lookup_diff (session, &setop->output_diff))
2190  {
2191  struct DiffEntry *diff;
2192 
2193  diff = diff_create ();
2194  diff->key = setop->output_diff;
2195  put_diff (session, diff);
2196  }
2197  }
2198 
2199  if ((task->key.peer1 == session->local_peer_idx) && (task->key.peer2 ==
2200  session->local_peer_idx))
2201  {
2202  /* XXX: mark the corresponding rfn as commited if necessary */
2203  finish_task (task);
2204  return;
2205  }
2206 
2207  if (task->key.peer1 == session->local_peer_idx)
2208  {
2210 
2212  "P%u: Looking up set {%s} to run remote union\n",
2213  session->local_peer_idx,
2214  debug_str_set_key (&setop->input_set));
2215 
2216  rcm.header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
2217  rcm.header.size = htons (sizeof(struct
2219 
2220  rcm.kind = htons (task->key.kind);
2221  rcm.peer1 = htons (task->key.peer1);
2222  rcm.peer2 = htons (task->key.peer2);
2223  rcm.leader = htons (task->key.leader);
2224  rcm.repetition = htons (task->key.repetition);
2225  rcm.is_contested = htons (0);
2226 
2227  GNUNET_assert (NULL == setop->op);
2229  "P%u: initiating set op with P%u, our set is %s\n",
2230  session->local_peer_idx, task->key.peer2, debug_str_set_key (
2231  &setop->input_set));
2232 
2233  struct GNUNET_SET_Option opts[] = {
2234  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2236  };
2237 
2238  // XXX: maybe this should be done while
2239  // setting up tasks alreays?
2240  setop->op = GNUNET_SET_prepare (&session->peers[task->key.peer2],
2241  &session->global_id,
2242  &rcm.header,
2244  opts,
2245  set_result_cb,
2246  task);
2247 
2248  commit_set (session, task);
2249  }
2250  else if (task->key.peer2 == session->local_peer_idx)
2251  {
2252  /* Wait for the other peer to contact us */
2253  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting set op with P%u\n",
2254  session->local_peer_idx, task->key.peer1);
2255 
2256  if (NULL != setop->op)
2257  {
2258  commit_set (session, task);
2259  }
2260  }
2261  else
2262  {
2263  /* We made an error while constructing the task graph. */
2264  GNUNET_assert (0);
2265  }
2266 }
#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:813
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 2270 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().

2271 {
2273  struct ReferendumEntry *input_rfn;
2274  struct RfnElementInfo *ri;
2275  struct SetEntry *output_set;
2276  struct SetMutationProgressCls *progress_cls;
2277  struct ConsensusSession *session = task->step->session;
2278  struct SetKey sk_in;
2279  struct SetKey sk_out;
2280  struct RfnKey rk_in;
2281 
2282  sk_in = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, task->key.repetition,
2283  task->key.leader };
2284  sk_out = (struct SetKey) { SET_KIND_ECHO_RESULT, task->key.repetition,
2285  task->key.leader };
2286  output_set = lookup_set (session, &sk_out);
2287  if (NULL == output_set)
2288  {
2289  create_set_copy_for_task (task, &sk_in, &sk_out);
2290  return;
2291  }
2292 
2293 
2294  {
2295  // FIXME: should be marked as a shallow copy, so
2296  // we can destroy everything correctly
2297  struct SetEntry *last_set = GNUNET_new (struct SetEntry);
2298  last_set->h = output_set->h;
2299  last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
2300  put_set (session, last_set);
2301  }
2302 
2304  "Evaluating referendum in Task {%s}\n",
2305  debug_str_task_key (&task->key));
2306 
2307  progress_cls = GNUNET_new (struct SetMutationProgressCls);
2308  progress_cls->task = task;
2309 
2310  rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2311  task->key.leader };
2312  input_rfn = lookup_rfn (session, &rk_in);
2313 
2314  GNUNET_assert (NULL != input_rfn);
2315 
2317  input_rfn->rfn_elements);
2318  GNUNET_assert (NULL != iter);
2319 
2320  while (GNUNET_YES ==
2322  NULL,
2323  (const void **) &ri))
2324  {
2325  enum ReferendumVote majority_vote;
2326  uint16_t majority_num;
2327 
2328  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2329 
2330  if (majority_num < session->num_peers / 3)
2331  {
2332  /* It is not the case that all nonfaulty peers
2333  echoed the same value. Since we're doing a set reconciliation, we
2334  can't simply send "nothing" for the value. Thus we mark our 'confirm'
2335  reconciliation as contested. Other peers might not know that the
2336  leader is faulty, thus we still re-distribute in the confirmation
2337  round. */output_set->is_contested = GNUNET_YES;
2338  }
2339 
2340  switch (majority_vote)
2341  {
2342  case VOTE_ADD:
2343  progress_cls->num_pending++;
2345  GNUNET_SET_add_element (output_set->h,
2346  ri->element,
2348  progress_cls));
2349  break;
2350 
2351  case VOTE_REMOVE:
2352  progress_cls->num_pending++;
2354  GNUNET_SET_remove_element (output_set->h,
2355  ri->element,
2357  progress_cls));
2358  break;
2359 
2360  case VOTE_STAY:
2361  /* Nothing to do. */
2362  break;
2363 
2364  default:
2365  /* not reached */
2366  GNUNET_assert (0);
2367  }
2368  }
2369 
2371 
2372  if (0 == progress_cls->num_pending)
2373  {
2374  // call closure right now, no pending ops
2375  GNUNET_free (progress_cls);
2376  finish_task (task);
2377  }
2378 }
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:734
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
int16_t repetition
Repetition of the gradecast phase.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct ConsensusSession * session
static 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 2382 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().

2383 {
2384  struct SetEntry *final_set;
2385  struct ConsensusSession *session = task->step->session;
2386 
2387  final_set = lookup_set (session, &task->cls.finish.input_set);
2388 
2389  GNUNET_assert (NULL != final_set);
2390 
2391 
2392  GNUNET_SET_iterate (final_set->h,
2394  task);
2395 }
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:1172
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_task()

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

Definition at line 2399 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().

2400 {
2401  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: starting task {%s}\n",
2402  session->local_peer_idx, debug_str_task_key (&task->key));
2403 
2404  GNUNET_assert (GNUNET_NO == task->is_started);
2405  GNUNET_assert (GNUNET_NO == task->is_finished);
2406  GNUNET_assert (NULL != task->start);
2407 
2408  task->start (task);
2409 
2410  task->is_started = GNUNET_YES;
2411 }
#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 2489 of file gnunet-service-consensus.c.

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

Referenced by handle_client_join().

2491 {
2492  int i;
2493 
2494  for (i = 0; i < session->num_peers; i++)
2495  if (0 == GNUNET_memcmp (peer, &session->peers[i]))
2496  return i;
2497  return -1;
2498 }
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 2511 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().

2513 {
2514  const char *salt = "gnunet-service-consensus/session_id";
2515 
2517  GNUNET_CRYPTO_kdf (&session->global_id,
2518  sizeof(struct GNUNET_HashCode),
2519  salt,
2520  strlen (salt),
2521  session->peers,
2522  session->num_peers * sizeof(struct
2524  local_session_id,
2525  sizeof(struct GNUNET_HashCode),
2526  NULL));
2527 }
#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:89
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 2538 of file gnunet-service-consensus.c.

Referenced by initialize_session_peer_list().

2539 {
2540  return memcmp (h1, h2, sizeof(struct GNUNET_PeerIdentity));
2541 }
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 2552 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().

2555 {
2556  const struct GNUNET_PeerIdentity *msg_peers
2557  = (const struct GNUNET_PeerIdentity *) &join_msg[1];
2558  int local_peer_in_list;
2559 
2560  session->num_peers = ntohl (join_msg->num_peers);
2561 
2562  /* Peers in the join message, may or may not include the local peer,
2563  Add it if it is missing. */
2564  local_peer_in_list = GNUNET_NO;
2565  for (unsigned int i = 0; i < session->num_peers; i++)
2566  {
2567  if (0 == GNUNET_memcmp (&msg_peers[i],
2568  &my_peer))
2569  {
2570  local_peer_in_list = GNUNET_YES;
2571  break;
2572  }
2573  }
2574  if (GNUNET_NO == local_peer_in_list)
2575  session->num_peers++;
2576 
2577  session->peers = GNUNET_new_array (session->num_peers,
2578  struct GNUNET_PeerIdentity);
2579  if (GNUNET_NO == local_peer_in_list)
2580  session->peers[session->num_peers - 1] = my_peer;
2581 
2582  GNUNET_memcpy (session->peers,
2583  msg_peers,
2584  ntohl (join_msg->num_peers) * sizeof(struct
2586  qsort (session->peers,
2587  session->num_peers,
2588  sizeof(struct GNUNET_PeerIdentity),
2589  &peer_id_cmp);
2590 }
#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:48
struct GNUNET_PeerIdentity * peers
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
The identity of the host (wraps the signing key of the peer).
#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 2594 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().

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

◆ set_listen_cb()

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

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

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

Definition at line 2623 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().

2627 {
2628  struct ConsensusSession *session = cls;
2629  struct TaskKey tk;
2630  struct TaskEntry *task;
2632 
2633  if (NULL == context_msg)
2634  {
2635  GNUNET_break_op (0);
2636  return;
2637  }
2638 
2640  context_msg->type))
2641  {
2642  GNUNET_break_op (0);
2643  return;
2644  }
2645 
2646  if (sizeof(struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs (
2647  context_msg->size))
2648  {
2649  GNUNET_break_op (0);
2650  return;
2651  }
2652 
2653  cm = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg;
2654 
2655  tk = ((struct TaskKey) {
2656  .kind = ntohs (cm->kind),
2657  .peer1 = ntohs (cm->peer1),
2658  .peer2 = ntohs (cm->peer2),
2659  .repetition = ntohs (cm->repetition),
2660  .leader = ntohs (cm->leader),
2661  });
2662 
2663  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2664  session->local_peer_idx, debug_str_task_key (&tk));
2665 
2666  task = lookup_task (session, &tk);
2667 
2668  if (NULL == task)
2669  {
2670  GNUNET_break_op (0);
2671  return;
2672  }
2673 
2674  if (GNUNET_YES == task->is_finished)
2675  {
2676  GNUNET_break_op (0);
2677  return;
2678  }
2679 
2680  if (task->key.peer2 != session->local_peer_idx)
2681  {
2682  /* We're being asked, so we must be thne 2nd peer. */
2683  GNUNET_break_op (0);
2684  return;
2685  }
2686 
2687  GNUNET_assert (! ((task->key.peer1 == session->local_peer_idx) &&
2688  (task->key.peer2 == session->local_peer_idx)));
2689 
2690  struct GNUNET_SET_Option opts[] = {
2691  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2693  };
2694 
2695  task->cls.setop.op = GNUNET_SET_accept (request,
2697  opts,
2698  set_result_cb,
2699  task);
2700 
2701  /* If the task hasn't been started yet,
2702  we wait for that until we commit. */
2703 
2704  if (GNUNET_YES == task->is_started)
2705  {
2706  commit_set (session, task);
2707  }
2708 }
#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:1085
Fail set operations when the other peer shows weird behavior that might by a Byzantine fault...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_task()

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

Definition at line 2712 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().

2714 {
2715  struct GNUNET_HashCode round_hash;
2716  struct Step *s;
2717 
2718  GNUNET_assert (NULL != t->step);
2719 
2720  t = GNUNET_memdup (t, sizeof(struct TaskEntry));
2721 
2722  s = t->step;
2723 
2724  if (s->tasks_len == s->tasks_cap)
2725  {
2726  unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2728  s->tasks_cap,
2729  target_size);
2730  }
2731 
2732 #ifdef GNUNET_EXTRA_LOGGING
2733  GNUNET_assert (NULL != s->debug_name);
2734  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2735  debug_str_task_key (&t->key),
2736  s->debug_name);
2737 #endif
2738 
2739  s->tasks[s->tasks_len] = t;
2740  s->tasks_len++;
2741 
2742  GNUNET_CRYPTO_hash (&t->key, sizeof(struct TaskKey), &round_hash);
2744  GNUNET_CONTAINER_multihashmap_put (taskmap, &round_hash, t,
2746 }
#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:48
A 512-bit hashcode.
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskKey key
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct TaskEntry ** tasks
Tasks that this step is composed of.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Tuple of integers that together identify a task uniquely.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int tasks_cap
Here is the call graph for this function:
Here is the caller graph for this function:

◆ install_step_timeouts()

static void install_step_timeouts ( struct ConsensusSession session)
static

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

Referenced by handle_client_conclude().

2751 {
2752  /* Given the fully constructed task graph
2753  with rounds for tasks, we can give the tasks timeouts. */
2754 
2755  // unsigned int max_round;
2756 
2757  /* XXX: implement! */
2758 }
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 2765 of file gnunet-service-consensus.c.

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2766 {
2767  uint16_t a;
2768  uint16_t b;
2769 
2770  GNUNET_assert (*p1 < n);
2771  GNUNET_assert (*p2 < n);
2772 
2773  if (*p1 < *p2)
2774  {
2775  a = *p1;
2776  b = *p2;
2777  }
2778  else
2779  {
2780  a = *p2;
2781  b = *p1;
2782  }
2783 
2784  /* For uniformly random *p1, *p2,
2785  this condition is true with 50% chance */
2786  if (((b - a) + n) % n <= n / 2)
2787  {
2788  *p1 = a;
2789  *p2 = b;
2790  }
2791  else
2792  {
2793  *p1 = b;
2794  *p2 = a;
2795  }
2796 }
#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 2803 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().

2804 {
2805  /* We're not checking for cyclic dependencies,
2806  but this is a cheap sanity check. */
2807  GNUNET_assert (step != dep);
2808  GNUNET_assert (NULL != step);
2809  GNUNET_assert (NULL != dep);
2810  GNUNET_assert (dep->round <= step->round);
2811 
2812 #ifdef GNUNET_EXTRA_LOGGING
2813  /* Make sure we have complete debugging information.
2814  Also checks that we don't screw up too badly
2815  constructing the task graph. */
2816  GNUNET_assert (NULL != step->debug_name);
2817  GNUNET_assert (NULL != dep->debug_name);
2819  "Making step `%s' depend on `%s'\n",
2820  step->debug_name,
2821  dep->debug_name);
2822 #endif
2823 
2824  if (dep->subordinates_cap == dep->subordinates_len)
2825  {
2826  unsigned int target_size = 3 * (dep->subordinates_cap + 1) / 2;
2828  dep->subordinates_cap,
2829  target_size);
2830  }
2831 
2833 
2834  dep->subordinates[dep->subordinates_len] = step;
2835  dep->subordinates_len++;
2836 
2837  step->pending_prereq++;
2838 }
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 2842 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().

2843 {
2844  struct Step *step;
2845 
2846  step = GNUNET_new (struct Step);
2847  step->session = session;
2848  step->round = round;
2851  session->steps_tail,
2852  step);
2853  return step;
2854 }
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 2862 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().

2867 {
2868  uint16_t n = session->num_peers;
2869  uint16_t me = session->local_peer_idx;
2870 
2871  uint16_t p1;
2872  uint16_t p2;
2873 
2874  /* The task we're currently setting up. */
2875  struct TaskEntry task;
2876 
2877  struct Step *step;
2878  struct Step *prev_step;
2879 
2880  uint16_t round;
2881 
2882  unsigned int k;
2883 
2884  round = step_before->round + 1;
2885 
2886  /* gcast step 1: leader disseminates */
2887 
2888  step = create_step (session, round, GNUNET_YES);
2889 
2890 #ifdef GNUNET_EXTRA_LOGGING
2891  GNUNET_asprintf (&step->debug_name, "disseminate leader %u rep %u", lead,
2892  rep);
2893 #endif
2894  step_depend_on (step, step_before);
2895 
2896  if (lead == me)
2897  {
2898  for (k = 0; k < n; k++)
2899  {
2900  if (k == me)
2901  continue;
2902  p1 = me;
2903  p2 = k;
2904  arrange_peers (&p1, &p2, n);
2905  task = ((struct TaskEntry) {
2906  .step = step,
2907  .start = task_start_reconcile,
2908  .cancel = task_cancel_reconcile,
2909  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep,
2910  me },
2911  });
2912  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2913  put_task (session->taskmap, &task);
2914  }
2915  /* We run this task to make sure that the leader
2916  has the stored the SET_KIND_LEADER set of himself,
2917  so it can participate in the rest of the gradecast
2918  without the code having to handle any special cases. */
2919  task = ((struct TaskEntry) {
2920  .step = step,
2921  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, me, me, rep, me },
2922  .start = task_start_reconcile,
2923  .cancel = task_cancel_reconcile,
2924  });
2925  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2926  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
2927  me };
2928  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL,
2929  rep, me };
2930  put_task (session->taskmap, &task);
2931  }
2932  else
2933  {
2934  p1 = me;
2935  p2 = lead;
2936  arrange_peers (&p1, &p2, n);
2937  task = ((struct TaskEntry) {
2938  .step = step,
2939  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_LEADER, p1, p2, rep,
2940  lead },
2941  .start = task_start_reconcile,
2942  .cancel = task_cancel_reconcile,
2943  });
2944  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, rep };
2945  task.cls.setop.output_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
2946  lead };
2947  task.cls.setop.output_diff = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL,
2948  rep, lead };
2949  put_task (session->taskmap, &task);
2950  }
2951 
2952  /* gcast phase 2: echo */
2953  prev_step = step;
2954  round += 1;
2955  step = create_step (session, round, GNUNET_YES);
2956 #ifdef GNUNET_EXTRA_LOGGING
2957  GNUNET_asprintf (&step->debug_name, "echo leader %u rep %u", lead, rep);
2958 #endif
2959  step_depend_on (step, prev_step);
2960 
2961  for (k = 0; k < n; k++)
2962  {
2963  p1 = k;
2964  p2 = me;
2965  arrange_peers (&p1, &p2, n);
2966  task = ((struct TaskEntry) {
2967  .step = step,
2968  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO, p1, p2, rep, lead },
2969  .start = task_start_reconcile,
2970  .cancel = task_cancel_reconcile,
2971  });
2972  task.cls.setop.input_set = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, rep,
2973  lead };
2974  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_ECHO, rep, lead };
2975  put_task (session->taskmap, &task);
2976  }
2977 
2978  prev_step = step;
2979  /* Same round, since step only has local tasks */
2980  step = create_step (session, round, GNUNET_YES);
2981 #ifdef GNUNET_EXTRA_LOGGING
2982  GNUNET_asprintf (&step->debug_name, "echo grade leader %u rep %u", lead, rep);
2983 #endif
2984  step_depend_on (step, prev_step);
2985 
2986  arrange_peers (&p1, &p2, n);
2987  task = ((struct TaskEntry) {
2988  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_ECHO_GRADE, -1, -1, rep,
2989  lead },
2990  .step = step,
2991  .start = task_start_eval_echo
2992  });
2993  put_task (session->taskmap, &task);
2994 
2995  prev_step = step;
2996  round += 1;
2997  step = create_step (session, round, GNUNET_YES);
2998 #ifdef GNUNET_EXTRA_LOGGING
2999  GNUNET_asprintf (&step->debug_name, "confirm leader %u rep %u", lead, rep);
3000 #endif
3001  step_depend_on (step, prev_step);
3002 
3003  /* gcast phase 3: confirmation and grading */
3004  for (k = 0; k < n; k++)
3005  {
3006  p1 = k;
3007  p2 = me;
3008  arrange_peers (&p1, &p2, n);
3009  task = ((struct TaskEntry) {
3010  .step = step,
3011  .start = task_start_reconcile,
3012  .cancel = task_cancel_reconcile,
3013  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM, p1, p2, rep,
3014  lead },
3015  });
3016  task.cls.setop.input_set = (struct SetKey) { SET_KIND_ECHO_RESULT, rep,
3017  lead };
3018  task.cls.setop.output_rfn = (struct RfnKey) { RFN_KIND_CONFIRM, rep, lead };
3019  /* If there was at least one element in the echo round that was
3020  contested (i.e. it had no n-t majority), then we let the other peers
3021  know, and other peers let us know. The contested flag for each peer is
3022  stored in the rfn. */
3023  task.cls.setop.transceive_contested = GNUNET_YES;
3024  put_task (session->taskmap, &task);
3025  }
3026 
3027  prev_step = step;
3028  /* Same round, since step only has local tasks */
3029  step = create_step (session, round, GNUNET_YES);
3030 #ifdef GNUNET_EXTRA_LOGGING
3031  GNUNET_asprintf (&step->debug_name, "confirm grade leader %u rep %u", lead,
3032  rep);
3033 #endif
3034  step_depend_on (step, prev_step);
3035 
3036  task = ((struct TaskEntry) {
3037  .step = step,
3038  .key = (struct TaskKey) { PHASE_KIND_GRADECAST_CONFIRM_GRADE, -1, -1, rep,
3039  lead },
3040  .start = task_start_grade,
3041  });
3042  put_task (session->taskmap, &task);
3043 
3044  step_depend_on (step_after, step);
3045 }
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 3049 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().

3050 {
3051  uint16_t n = session->num_peers;
3052  uint16_t t = n / 3;
3053 
3054  uint16_t me = session->local_peer_idx;
3055 
3056  /* The task we're currently setting up. */
3057  struct TaskEntry task;
3058 
3059  /* Current leader */
3060  unsigned int lead;
3061 
3062  struct Step *step;
3063  struct Step *prev_step;
3064 
3065  unsigned int round = 0;
3066 
3067  unsigned int i;
3068 
3069  // XXX: introduce first step,
3070  // where we wait for all insert acks
3071  // from the set service
3072 
3073  /* faster but brittle all-to-all */
3074 
3075  // XXX: Not implemented yet
3076 
3077  /* all-to-all step */
3078 
3079  step = create_step (session, round, GNUNET_NO);
3080 
3081 #ifdef GNUNET_EXTRA_LOGGING
3082  step->debug_name = GNUNET_strdup ("all to all");
3083 #endif
3084 
3085  for (i = 0; i < n; i++)
3086  {
3087  uint16_t p1;
3088  uint16_t p2;
3089 
3090  p1 = me;
3091  p2 = i;
3092  arrange_peers (&p1, &p2, n);
3093  task = ((struct TaskEntry) {
3094  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL, p1, p2, -1, -1 },
3095  .step = step,
3096  .start = task_start_reconcile,
3097  .cancel = task_cancel_reconcile,
3098  });
3099  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3100  task.cls.setop.output_set = task.cls.setop.input_set;
3101  task.cls.setop.do_not_remove = GNUNET_YES;
3102  put_task (session->taskmap, &task);
3103  }
3104 
3105  round += 1;
3106  prev_step = step;
3107  step = create_step (session, round, GNUNET_NO);;
3108 #ifdef GNUNET_EXTRA_LOGGING
3109  step->debug_name = GNUNET_strdup ("all to all 2");
3110 #endif
3111  step_depend_on (step, prev_step);
3112 
3113 
3114  for (i = 0; i < n; i++)
3115  {
3116  uint16_t p1;
3117  uint16_t p2;
3118 
3119  p1 = me;
3120  p2 = i;
3121  arrange_peers (&p1, &p2, n);
3122  task = ((struct TaskEntry) {
3123  .key = (struct TaskKey) { PHASE_KIND_ALL_TO_ALL_2, p1, p2, -1, -1 },
3124  .step = step,
3125  .start = task_start_reconcile,
3126  .cancel = task_cancel_reconcile,
3127  });
3128  task.cls.setop.input_set = (struct SetKey) { SET_KIND_CURRENT, 0 };
3129  task.cls.setop.output_set = task.cls.setop.input_set;
3130  task.cls.setop.do_not_remove = GNUNET_YES;
3131  put_task (session->taskmap, &task);
3132  }
3133 
3134  round += 1;
3135 
3136  prev_step = step;
3137  step = NULL;
3138 
3139 
3140  /* Byzantine union */
3141 
3142  /* sequential repetitions of the gradecasts */
3143  for (i = 0; i < t + 1; i++)
3144  {
3145  struct Step *step_rep_start;
3146  struct Step *step_rep_end;
3147 
3148  /* Every repetition is in a separate round. */