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

multi-peer set reconciliation More...

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

Go to the source code of this file.

Data Structures

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

multi-peer set reconciliation

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

Definition in file gnunet-service-consensus.c.

Typedef Documentation

◆ TaskFunc

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

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

2379 {
2380  GNUNET_assert (GNUNET_NO == task->is_finished);
2381  task->is_finished = GNUNET_YES;
2382 
2383  task->step->finished_tasks++;
2384 
2386  "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
2387  task->step->session->local_peer_idx,
2388  debug_str_task_key (&task->key),
2389  (unsigned int) task->step->finished_tasks,
2390  (unsigned int) task->step->tasks_len);
2391 
2392  if (task->step->finished_tasks == task->step->tasks_len)
2393  finish_step (task->step);
2394 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 2337 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().

2338 {
2339  struct Step *step;
2340 
2341  step = session->steps_head;
2342 
2343  while (NULL != step)
2344  {
2345  if ( (GNUNET_NO == step->is_running) && (0 == step->pending_prereq) && (GNUNET_NO == step->is_finished) )
2346  {
2347  size_t i;
2348 
2349  GNUNET_assert (0 == step->finished_tasks);
2350 
2351 #ifdef GNUNET_EXTRA_LOGGING
2352  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Running step `%s' of round %d with %d tasks and %d subordinates\n",
2353  session->local_peer_idx,
2354  step->debug_name,
2355  step->round, step->tasks_len, step->subordinates_len);
2356 #endif
2357 
2358  step->is_running = GNUNET_YES;
2359  for (i = 0; i < step->tasks_len; i++)
2360  start_task (session, step->tasks[i]);
2361 
2362  /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
2363  if ( (step->finished_tasks == step->tasks_len) && (GNUNET_NO == step->is_finished))
2364  finish_step (step);
2365 
2366  /* Running the next ready steps will be triggered by task completion */
2367  return;
2368  }
2369  step = step->next;
2370  }
2371 
2372  return;
2373 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 550 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().

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

◆ setname()

static const char* setname ( uint16_t  kind)
static

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

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

Referenced by diffname().

570 {
571  switch (kind)
572  {
573  case SET_KIND_CURRENT: return "CURRENT";
574  case SET_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
575  case SET_KIND_NONE: return "NONE";
576  default: return "(unknown)";
577  }
578 }
Here is the caller graph for this function:

◆ rfnname()

static const char* rfnname ( uint16_t  kind)
static

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

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

Referenced by diffname().

582 {
583  switch (kind)
584  {
585  case RFN_KIND_NONE: return "NONE";
586  case RFN_KIND_ECHO: return "ECHO";
587  case RFN_KIND_CONFIRM: return "CONFIRM";
588  default: return "(unknown)";
589  }
590 }
Here is the caller graph for this function:

◆ diffname()

static const char* diffname ( uint16_t  kind)
static

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

594 {
595  switch (kind)
596  {
597  case DIFF_KIND_NONE: return "NONE";
598  case DIFF_KIND_LEADER_CONSENSUS: return "LEADER_CONSENSUS";
599  case DIFF_KIND_GRADECAST_RESULT: return "GRADECAST_RESULT";
600  case DIFF_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
601  default: return "(unknown)";
602  }
603 }
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 681 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().

683 {
684  struct TaskEntry *task = (struct TaskEntry *) cls;
685  struct ConsensusSession *session = task->step->session;
686  struct GNUNET_MQ_Envelope *ev;
687 
688  if (NULL != element)
689  {
691  const struct ConsensusElement *ce;
692 
694  ce = element->data;
695 
696  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "marker is %u\n", (unsigned) ce->marker);
697 
698  if (0 != ce->marker)
699  return GNUNET_YES;
700 
702  "P%d: sending element %s to client\n",
703  session->local_peer_idx,
704  debug_str_element (element));
705 
706  ev = GNUNET_MQ_msg_extra (m, element->size - sizeof (struct ConsensusElement),
708  m->element_type = ce->payload_type;
709  GNUNET_memcpy (&m[1], &ce[1], element->size - sizeof (struct ConsensusElement));
710  GNUNET_MQ_send (session->client_mq, ev);
711  }
712  else
713  {
715  "P%d: finished iterating elements for client\n",
716  session->local_peer_idx);
718  GNUNET_MQ_send (session->client_mq, ev);
719  }
720  return GNUNET_YES;
721 }
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
const void * data
Actual data of the element.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
#define GNUNET_memcpy(dst, src, n)
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:85
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:80
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 725 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().

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

◆ lookup_diff()

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

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

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

◆ lookup_rfn()

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

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

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

◆ diff_insert()

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

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

776 {
777  struct DiffElementInfo *di;
778  struct GNUNET_HashCode hash;
779 
780  GNUNET_assert ( (1 == weight) || (-1 == weight));
781 
783  "diff_insert with element size %u\n",
784  element->size);
785 
787  "hashing element\n");
788 
789  GNUNET_SET_element_hash (element, &hash);
790 
792  "hashed element\n");
793 
794  di = GNUNET_CONTAINER_multihashmap_get (diff->changes, &hash);
795 
796  if (NULL == di)
797  {
798  di = GNUNET_new (struct DiffElementInfo);
799  di->element = GNUNET_SET_element_dup (element);
802  &hash, di,
804  }
805 
806  di->weight = weight;
807 }
#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:78
#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:1242
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:1219
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 811 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().

813 {
814  GNUNET_assert (commit_peer < rfn->num_peers);
815 
816  rfn->peer_commited[commit_peer] = GNUNET_YES;
817 }
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:80
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 821 of file gnunet-service-consensus.c.

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

Referenced by set_result_cb().

823 {
824  GNUNET_assert (contested_peer < rfn->num_peers);
825 
826  rfn->peer_contested[contested_peer] = GNUNET_YES;
827 }
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:80
Here is the caller graph for this function:

◆ rfn_noncontested()

static uint16_t rfn_noncontested ( struct ReferendumEntry rfn)
static

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

832 {
833  uint16_t i;
834  uint16_t ret;
835 
836  ret = 0;
837  for (i = 0; i < rfn->num_peers; i++)
838  if ( (GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO == rfn->peer_contested[i]) )
839  ret++;
840 
841  return ret;
842 }
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:81
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_YES
Definition: gnunet_common.h:80
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 846 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().

850 {
851  struct RfnElementInfo *ri;
852  struct GNUNET_HashCode hash;
853 
854  GNUNET_assert (voting_peer < rfn->num_peers);
855 
856  /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
857  since VOTE_KEEP is implicit in not voting. */
858  GNUNET_assert ( (VOTE_ADD == vote) || (VOTE_REMOVE == vote) );
859 
860  GNUNET_SET_element_hash (element, &hash);
862 
863  if (NULL == ri)
864  {
865  ri = GNUNET_new (struct RfnElementInfo);
866  ri->element = GNUNET_SET_element_dup (element);
867  ri->votes = GNUNET_new_array (rfn->num_peers, int);
870  &hash, ri,
872  }
873 
874  ri->votes[voting_peer] = GNUNET_YES;
875  ri->proposal = vote;
876 }
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:78
#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:1242
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:1219
#define GNUNET_YES
Definition: gnunet_common.h:80
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 880 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().

881 {
882  uint16_t me = task->step->session->local_peer_idx;
883  if (task->key.peer1 == me)
884  return task->key.peer2;
885  return task->key.peer1;
886 }
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 890 of file gnunet-service-consensus.c.

Referenced by set_result_cb().

891 {
892  uint64_t a = *(uint64_t *) pa;
893  uint64_t b = *(uint64_t *) pb;
894 
895  if (a == b)
896  return 0;
897  if (a < b)
898  return -1;
899  return 1;
900 }
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 913 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().

917 {
918  struct TaskEntry *task = cls;
919  struct ConsensusSession *session = task->step->session;
920  struct SetEntry *output_set = NULL;
921  struct DiffEntry *output_diff = NULL;
922  struct ReferendumEntry *output_rfn = NULL;
923  unsigned int other_idx;
924  struct SetOpCls *setop;
925  const struct ConsensusElement *consensus_element = NULL;
926 
927  if (NULL != element)
928  {
930  "P%u: got element of type %u, status %u\n",
931  session->local_peer_idx,
932  (unsigned) element->element_type,
933  (unsigned) status);
935  consensus_element = element->data;
936  }
937 
938  setop = &task->cls.setop;
939 
940 
942  "P%u: got set result for {%s}, status %u\n",
943  session->local_peer_idx,
944  debug_str_task_key (&task->key),
945  status);
946 
947  if (GNUNET_NO == task->is_started)
948  {
949  GNUNET_break_op (0);
950  return;
951  }
952 
953  if (GNUNET_YES == task->is_finished)
954  {
955  GNUNET_break_op (0);
956  return;
957  }
958 
959  other_idx = task_other_peer (task);
960 
961  if (SET_KIND_NONE != setop->output_set.set_kind)
962  {
963  output_set = lookup_set (session, &setop->output_set);
964  GNUNET_assert (NULL != output_set);
965  }
966 
967  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
968  {
969  output_diff = lookup_diff (session, &setop->output_diff);
970  GNUNET_assert (NULL != output_diff);
971  }
972 
973  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
974  {
975  output_rfn = lookup_rfn (session, &setop->output_rfn);
976  GNUNET_assert (NULL != output_rfn);
977  }
978 
979  if (GNUNET_YES == session->peers_blacklisted[other_idx])
980  {
981  /* Peer might have been blacklisted
982  by a gradecast running in parallel, ignore elements from now */
984  return;
986  return;
987  }
988 
989  if ( (NULL != consensus_element) && (0 != consensus_element->marker) )
990  {
992  "P%u: got some marker\n",
993  session->local_peer_idx);
994  if ( (GNUNET_YES == setop->transceive_contested) &&
995  (CONSENSUS_MARKER_CONTESTED == consensus_element->marker) )
996  {
997  GNUNET_assert (NULL != output_rfn);
998  rfn_contest (output_rfn, task_other_peer (task));
999  return;
1000  }
1001 
1002  if (CONSENSUS_MARKER_SIZE == consensus_element->marker)
1003  {
1004 
1006  "P%u: got size marker\n",
1007  session->local_peer_idx);
1008 
1009 
1010  struct ConsensusSizeElement *cse = (void *) consensus_element;
1011 
1012  if (cse->sender_index == other_idx)
1013  {
1014  if (NULL == session->first_sizes_received)
1015  session->first_sizes_received = GNUNET_new_array (session->num_peers, uint64_t);
1016  session->first_sizes_received[other_idx] = GNUNET_ntohll (cse->size);
1017 
1018  uint64_t *copy = GNUNET_memdup (session->first_sizes_received, sizeof (uint64_t) * session->num_peers);
1019  qsort (copy, session->num_peers, sizeof (uint64_t), cmp_uint64_t);
1020  session->lower_bound = copy[session->num_peers / 3 + 1];
1022  "P%u: lower bound %llu\n",
1023  session->local_peer_idx,
1024  (long long) session->lower_bound);
1025  GNUNET_free (copy);
1026  }
1027  return;
1028  }
1029 
1030  return;
1031  }
1032 
1033  switch (status)
1034  {
1036  GNUNET_assert (NULL != consensus_element);
1038  "Adding element in Task {%s}\n",
1039  debug_str_task_key (&task->key));
1040  if (NULL != output_set)
1041  {
1042  // FIXME: record pending adds, use callback
1043  GNUNET_SET_add_element (output_set->h,
1044  element,
1045  NULL,
1046  NULL);
1047 #ifdef GNUNET_EXTRA_LOGGING
1049  "P%u: adding element %s into set {%s} of task {%s}\n",
1050  session->local_peer_idx,
1051  debug_str_element (element),
1052  debug_str_set_key (&setop->output_set),
1053  debug_str_task_key (&task->key));
1054 #endif
1055  }
1056  if (NULL != output_diff)
1057  {
1058  diff_insert (output_diff, 1, element);
1059 #ifdef GNUNET_EXTRA_LOGGING
1061  "P%u: adding element %s into diff {%s} of task {%s}\n",
1062  session->local_peer_idx,
1063  debug_str_element (element),
1064  debug_str_diff_key (&setop->output_diff),
1065  debug_str_task_key (&task->key));
1066 #endif
1067  }
1068  if (NULL != output_rfn)
1069  {
1070  rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element);
1071 #ifdef GNUNET_EXTRA_LOGGING
1073  "P%u: adding element %s into rfn {%s} of task {%s}\n",
1074  session->local_peer_idx,
1075  debug_str_element (element),
1076  debug_str_rfn_key (&setop->output_rfn),
1077  debug_str_task_key (&task->key));
1078 #endif
1079  }
1080  // XXX: add result to structures in task
1081  break;
1083  GNUNET_assert (NULL != consensus_element);
1084  if (GNUNET_YES == setop->do_not_remove)
1085  break;
1086  if (CONSENSUS_MARKER_CONTESTED == consensus_element->marker)
1087  break;
1089  "Removing element in Task {%s}\n",
1090  debug_str_task_key (&task->key));
1091  if (NULL != output_set)
1092  {
1093  // FIXME: record pending adds, use callback
1094  GNUNET_SET_remove_element (output_set->h,
1095  element,
1096  NULL,
1097  NULL);
1098 #ifdef GNUNET_EXTRA_LOGGING
1100  "P%u: removing element %s from set {%s} of task {%s}\n",
1101  session->local_peer_idx,
1102  debug_str_element (element),
1103  debug_str_set_key (&setop->output_set),
1104  debug_str_task_key (&task->key));
1105 #endif
1106  }
1107  if (NULL != output_diff)
1108  {
1109  diff_insert (output_diff, -1, element);
1110 #ifdef GNUNET_EXTRA_LOGGING
1112  "P%u: removing element %s from diff {%s} of task {%s}\n",
1113  session->local_peer_idx,
1114  debug_str_element (element),
1115  debug_str_diff_key (&setop->output_diff),
1116  debug_str_task_key (&task->key));
1117 #endif
1118  }
1119  if (NULL != output_rfn)
1120  {
1121  rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element);
1122 #ifdef GNUNET_EXTRA_LOGGING
1124  "P%u: removing element %s from rfn {%s} of task {%s}\n",
1125  session->local_peer_idx,
1126  debug_str_element (element),
1127  debug_str_rfn_key (&setop->output_rfn),
1128  debug_str_task_key (&task->key));
1129 #endif
1130  }
1131  break;
1133  // XXX: check first if any changes to the underlying
1134  // set are still pending
1136  "P%u: Finishing setop in Task {%s} (%u/%u)\n",
1137  session->local_peer_idx,
1138  debug_str_task_key (&task->key),
1139  (unsigned int) task->step->finished_tasks,
1140  (unsigned int) task->step->tasks_len);
1141  if (NULL != output_rfn)
1142  {
1143  rfn_commit (output_rfn, task_other_peer (task));
1144  }
1145  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1146  {
1147  session->first_size = current_size;
1148  }
1149  finish_task (task);
1150  break;
1152  // XXX: cleanup
1153  GNUNET_break_op (0);
1154  finish_task (task);
1155  return;
1156  default:
1157  /* not reached */
1158  GNUNET_assert (0);
1159  }
1160 }
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:733
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:686
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:81
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:80
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 1323 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().

1325 {
1326  struct SetEntry *set;
1327  struct SetOpCls *setop = &task->cls.setop;
1328 
1329  GNUNET_assert (NULL != setop->op);
1330  set = lookup_set (session, &setop->input_set);
1331  GNUNET_assert (NULL != set);
1332 
1333  if ( (GNUNET_YES == setop->transceive_contested) && (GNUNET_YES == set->is_contested) )
1334  {
1335  struct GNUNET_SET_Element element;
1336  struct ConsensusElement ce = { 0 };
1338  element.data = &ce;
1339  element.size = sizeof (struct ConsensusElement);
1340  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1341  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1342  }
1343 
1344  if (PHASE_KIND_ALL_TO_ALL_2 == task->key.kind)
1345  {
1346  struct GNUNET_SET_Element element;
1347  struct ConsensusSizeElement cse = {
1348  .size = 0,
1349  .sender_index = 0
1350  };
1351  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inserting size marker\n");
1353  cse.size = GNUNET_htonll (session->first_size);
1354  cse.sender_index = session->local_peer_idx;
1355  element.data = &cse;
1356  element.size = sizeof (struct ConsensusSizeElement);
1357  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1358  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1359  }
1360 
1361 #ifdef EVIL
1362  {
1363  unsigned int i;
1364  struct Evilness evil;
1365 
1366  get_evilness (session, &evil);
1367  if (EVILNESS_NONE != evil.type)
1368  {
1369  /* Useful for evaluation */
1371  "is evil",
1372  1,
1373  GNUNET_NO);
1374  }
1375  switch (evil.type)
1376  {
1377  case EVILNESS_CRAM_ALL:
1378  case EVILNESS_CRAM_LEAD:
1379  case EVILNESS_CRAM_ECHO:
1380  /* We're not cramming elements in the
1381  all-to-all round, since that would just
1382  add more elements to the result set, but
1383  wouldn't test robustness. */
1384  if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1385  {
1386  GNUNET_SET_commit (setop->op, set->h);
1387  break;
1388  }
1389  if ((EVILNESS_CRAM_LEAD == evil.type) &&
1390  ((PHASE_KIND_GRADECAST_LEADER != task->key.kind) || SET_KIND_CURRENT != set->key.set_kind))
1391  {
1392  GNUNET_SET_commit (setop->op, set->h);
1393  break;
1394  }
1395  if (EVILNESS_CRAM_ECHO == evil.type && (PHASE_KIND_GRADECAST_ECHO != task->key.kind))
1396  {
1397  GNUNET_SET_commit (setop->op, set->h);
1398  break;
1399  }
1400  for (i = 0; i < evil.num; i++)
1401  {
1402  struct GNUNET_SET_Element element;
1403  struct ConsensusStuffedElement se = {
1404  .ce.payload_type = 0,
1405  .ce.marker = 0,
1406  };
1407  element.data = &se;
1408  element.size = sizeof (struct ConsensusStuffedElement);
1409  element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1410 
1411  if (EVILNESS_SUB_REPLACEMENT == evil.subtype)
1412  {
1413  /* Always generate a new element. */
1415  }
1416  else if (EVILNESS_SUB_NO_REPLACEMENT == evil.subtype)
1417  {
1418  /* Always cram the same elements, derived from counter. */
1419  GNUNET_CRYPTO_hash (&i, sizeof (i), &se.rand);
1420  }
1421  else
1422  {
1423  GNUNET_assert (0);
1424  }
1425  GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1426 #ifdef GNUNET_EXTRA_LOGGING
1428  "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n",
1429  session->local_peer_idx,
1430  debug_str_element (&element),
1431  debug_str_set_key (&setop->input_set),
1432  debug_str_task_key (&task->key));
1433 #endif
1434  }
1436  "# stuffed elements",
1437  evil.num,
1438  GNUNET_NO);
1439  GNUNET_SET_commit (setop->op, set->h);
1440  break;
1441  case EVILNESS_SLACK:
1443  "P%u: evil peer: slacking\n",
1444  (unsigned int) session->local_peer_idx);
1445  /* Do nothing. */
1446  case EVILNESS_SLACK_A2A:
1447  if ( (PHASE_KIND_ALL_TO_ALL_2 == task->key.kind ) ||
1448  (PHASE_KIND_ALL_TO_ALL == task->key.kind) )
1449  {
1450  struct GNUNET_SET_Handle *empty_set;
1452  GNUNET_SET_commit (setop->op, empty_set);
1453  GNUNET_SET_destroy (empty_set);
1454  }
1455  else
1456  {
1457  GNUNET_SET_commit (setop->op, set->h);
1458  }
1459  break;
1460  case EVILNESS_NONE:
1461  GNUNET_SET_commit (setop->op, set->h);
1462  break;
1463  }
1464  }
1465 #else
1466  if (GNUNET_NO == session->peers_blacklisted[task_other_peer (task)])
1467  {
1468  GNUNET_SET_commit (setop->op, set->h);
1469  }
1470  else
1471  {
1472  /* For our testcases, we don't want the blacklisted
1473  peers to wait. */
1475  setop->op = NULL;
1476  finish_task (task);
1477  }
1478 #endif
1479 }
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:686
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:656
#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:81
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:771
struct ConsensusElement ce
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:138
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
static uint16_t task_other_peer(struct TaskEntry *task)
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of the consensus service.
struct SetKey input_set
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
Opaque handle to a set.
Definition: set_api.c: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:1124
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:515
struct GNUNET_SET_OperationHandle * op
#define GNUNET_YES
Definition: gnunet_common.h:80
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 1483 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().

1485 {
1486  struct GNUNET_HashCode hash;
1487 
1488  GNUNET_assert (NULL != diff);
1489 
1490  GNUNET_CRYPTO_hash (&diff->key, sizeof (struct DiffKey), &hash);
1492  GNUNET_CONTAINER_multihashmap_put (session->diffmap, &hash, diff,
1494 }
#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:78
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
struct DiffKey key
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_CONTAINER_MultiHashMap * diffmap
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ put_set()

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

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

1499 {
1500  struct GNUNET_HashCode hash;
1501 
1502  GNUNET_assert (NULL != set->h);
1503 
1505  "Putting set %s\n",
1506  debug_str_set_key (&set->key));
1507 
1508  GNUNET_CRYPTO_hash (&set->key, sizeof (struct SetKey), &hash);
1510  GNUNET_CONTAINER_multihashmap_put (session->setmap, &hash, set,
1512 }
If a value with the given key exists, replace it.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_SET_Handle * h
struct GNUNET_CONTAINER_MultiHashMap * setmap
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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 1516 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().

1518 {
1519  struct GNUNET_HashCode hash;
1520 
1521  GNUNET_CRYPTO_hash (&rfn->key, sizeof (struct RfnKey), &hash);
1523  GNUNET_CONTAINER_multihashmap_put (session->rfnmap, &hash, rfn,
1525 }
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:78
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_cancel_reconcile()

static void task_cancel_reconcile ( struct TaskEntry task)
static

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

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

1531 {
1532  /* not implemented yet */
1533  GNUNET_assert (0);
1534 }
#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 1538 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().

1542 {
1544  struct DiffElementInfo *di;
1545 
1547 
1548  while (GNUNET_YES ==
1550  NULL,
1551  (const void **) &di))
1552  {
1553  if (di->weight > 0)
1554  {
1555  rfn_vote (rfn, voting_peer, VOTE_ADD, di->element);
1556  }
1557  if (di->weight < 0)
1558  {
1559  rfn_vote (rfn, voting_peer, VOTE_REMOVE, di->element);
1560  }
1561  }
1562 
1564 }
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:80
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 1568 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().

1569 {
1570  struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1571 
1573 
1574  return d;
1575 }
Weighted diff.
#define GNUNET_NO
Definition: gnunet_common.h:81
#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 1579 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.

1581 {
1582  struct DiffEntry *diff_new;
1584  struct DiffElementInfo *di;
1585 
1586  diff_new = diff_create ();
1587 
1589  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, (const void **) &di))
1590  {
1591  diff_insert (diff_new, di->weight, di->element);
1592  }
1594 
1596  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, (const void **) &di))
1597  {
1598  diff_insert (diff_new, di->weight, di->element);
1599  }
1601 
1602  return diff_new;
1603 }
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:80
Here is the call graph for this function:

◆ rfn_create()

struct ReferendumEntry* rfn_create ( uint16_t  size)

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

1608 {
1609  struct ReferendumEntry *rfn;
1610 
1611  rfn = GNUNET_new (struct ReferendumEntry);
1613  rfn->peer_commited = GNUNET_new_array (size, int);
1614  rfn->peer_contested = GNUNET_new_array (size, int);
1615  rfn->num_peers = size;
1616 
1617  return rfn;
1618 }
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:81
#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 1637 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().

1641 {
1642  uint16_t votes_yes = 0;
1643  uint16_t num_commited = 0;
1644  uint16_t i;
1645 
1647  "Computing rfn majority for element %s of rfn {%s}\n",
1648  debug_str_element (ri->element),
1649  debug_str_rfn_key (&rfn->key));
1650 
1651  for (i = 0; i < rfn->num_peers; i++)
1652  {
1653  if (GNUNET_NO == rfn->peer_commited[i])
1654  continue;
1655  num_commited++;
1656 
1657  if (GNUNET_YES == ri->votes[i])
1658  votes_yes++;
1659  }
1660 
1661  if (votes_yes > (num_commited) / 2)
1662  {
1663  *ret_vote = ri->proposal;
1664  *ret_majority = votes_yes;
1665  }
1666  else
1667  {
1668  *ret_vote = VOTE_STAY;
1669  *ret_majority = num_commited - votes_yes;
1670  }
1671 }
int * peer_commited
Stores, for every peer in the session, whether the peer finished the whole referendum.
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 1682 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().

1683 {
1684  struct SetCopyCls *scc = cls;
1685  struct TaskEntry *task = scc->task;
1686  struct SetKey dst_set_key = scc->dst_set_key;
1687  struct SetEntry *set;
1688  struct SetHandle *sh = GNUNET_new (struct SetHandle);
1689 
1690  sh->h = copy;
1692  task->step->session->set_handles_tail,
1693  sh);
1694 
1695  GNUNET_free (scc);
1696  set = GNUNET_new (struct SetEntry);
1697  set->h = copy;
1698  set->key = dst_set_key;
1699  put_set (task->step->session, set);
1700 
1701  task->start (task);
1702 }
#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 1710 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().

1713 {
1714  struct SetEntry *src_set;
1715  struct SetCopyCls *scc = GNUNET_new (struct SetCopyCls);
1716 
1718  "Copying set {%s} to {%s} for task {%s}\n",
1719  debug_str_set_key (src_set_key),
1720  debug_str_set_key (dst_set_key),
1721  debug_str_task_key (&task->key));
1722 
1723  scc->task = task;
1724  scc->dst_set_key = *dst_set_key;
1725  src_set = lookup_set (task->step->session, src_set_key);
1726  GNUNET_assert (NULL != src_set);
1727  GNUNET_SET_copy_lazy (src_set->h,
1728  set_copy_cb,
1729  scc);
1730 }
#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:1190
static void set_copy_cb(void *cls, struct GNUNET_SET_Handle *copy)
struct SetKey dst_set_key
struct TaskKey key
struct Step * step
#define GNUNET_log(kind,...)
struct TaskEntry * task
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_mutation_done()

static void set_mutation_done ( void *  cls)
static

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

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

Referenced by task_start_apply_round(), and task_start_eval_echo().

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

◆ try_finish_step_early()

static void try_finish_step_early ( struct Step step)
static

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

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

Referenced by task_start_apply_round().

1763 {
1764  unsigned int i;
1765 
1766  if (GNUNET_YES == step->is_running)
1767  return;
1768  if (GNUNET_YES == step->is_finished)
1769  return;
1770  if (GNUNET_NO == step->early_finishable)
1771  return;
1772 
1773  step->is_finished = GNUNET_YES;
1774 
1775 #ifdef GNUNET_EXTRA_LOGGING
1777  "Finishing step `%s' early.\n",
1778  step->debug_name);
1779 #endif
1780 
1781  for (i = 0; i < step->subordinates_len; i++)
1782  {
1783  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1784  step->subordinates[i]->pending_prereq--;
1785 #ifdef GNUNET_EXTRA_LOGGING
1787  "Decreased pending_prereq to %u for step `%s'.\n",
1788  (unsigned int) step->subordinates[i]->pending_prereq,
1789  step->subordinates[i]->debug_name);
1790 
1791 #endif
1793  }
1794 
1795  // XXX: maybe schedule as task to avoid recursion?
1796  run_ready_steps (step->session);
1797 }
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:81
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:80
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 1801 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().

1802 {
1803  unsigned int i;
1804 
1805  GNUNET_assert (step->finished_tasks == step->tasks_len);
1806  GNUNET_assert (GNUNET_YES == step->is_running);
1807  GNUNET_assert (GNUNET_NO == step->is_finished);
1808 
1809 #ifdef GNUNET_EXTRA_LOGGING
1811  "All tasks of step `%s' with %u subordinates finished.\n",
1812  step->debug_name,
1813  step->subordinates_len);
1814 #endif
1815 
1816  for (i = 0; i < step->subordinates_len; i++)
1817  {
1818  GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
1819  step->subordinates[i]->pending_prereq--;
1820 #ifdef GNUNET_EXTRA_LOGGING
1822  "Decreased pending_prereq to %u for step `%s'.\n",
1823  (unsigned int) step->subordinates[i]->pending_prereq,
1824  step->subordinates[i]->debug_name);
1825 
1826 #endif
1827  }
1828 
1829  step->is_finished = GNUNET_YES;
1830 
1831  // XXX: maybe schedule as task to avoid recursion?
1832  run_ready_steps (step->session);
1833 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ConsensusSession * session
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 1844 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().

1845 {
1846  struct ConsensusSession *session = task->step->session;
1847  struct SetKey sk_in;
1848  struct SetKey sk_out;
1849  struct RfnKey rk_in;
1850  struct SetEntry *set_out;
1851  struct ReferendumEntry *rfn_in;
1853  struct RfnElementInfo *ri;
1854  struct SetMutationProgressCls *progress_cls;
1855  uint16_t worst_majority = UINT16_MAX;
1856 
1857  sk_in = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition };
1858  rk_in = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1859  sk_out = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition + 1 };
1860 
1861  set_out = lookup_set (session, &sk_out);
1862  if (NULL == set_out)
1863  {
1864  create_set_copy_for_task (task, &sk_in, &sk_out);
1865  return;
1866  }
1867 
1868  rfn_in = lookup_rfn (session, &rk_in);
1869  GNUNET_assert (NULL != rfn_in);
1870 
1871  progress_cls = GNUNET_new (struct SetMutationProgressCls);
1872  progress_cls->task = task;
1873 
1875 
1876  while (GNUNET_YES ==
1878  NULL,
1879  (const void **) &ri))
1880  {
1881  uint16_t majority_num;
1882  enum ReferendumVote majority_vote;
1883 
1884  rfn_majority (rfn_in, ri, &majority_num, &majority_vote);
1885 
1886  if (worst_majority > majority_num)
1887  worst_majority = majority_num;
1888 
1889  switch (majority_vote)
1890  {
1891  case VOTE_ADD:
1892  progress_cls->num_pending++;
1894  GNUNET_SET_add_element (set_out->h,
1895  ri->element,
1897  progress_cls));
1899  "P%u: apply round: adding element %s with %u-majority.\n",
1900  session->local_peer_idx,
1901  debug_str_element (ri->element), majority_num);
1902  break;
1903  case VOTE_REMOVE:
1904  progress_cls->num_pending++;
1906  GNUNET_SET_remove_element (set_out->h,
1907  ri->element,
1909  progress_cls));
1911  "P%u: apply round: deleting element %s with %u-majority.\n",
1912  session->local_peer_idx,
1913  debug_str_element (ri->element), majority_num);
1914  break;
1915  case VOTE_STAY:
1917  "P%u: apply round: keeping element %s with %u-majority.\n",
1918  session->local_peer_idx,
1919  debug_str_element (ri->element), majority_num);
1920  // do nothing
1921  break;
1922  default:
1923  GNUNET_assert (0);
1924  break;
1925  }
1926  }
1927 
1928  if (0 == progress_cls->num_pending)
1929  {
1930  // call closure right now, no pending ops
1931  GNUNET_free (progress_cls);
1932  finish_task (task);
1933  }
1934 
1935  {
1936  uint16_t thresh = (session->num_peers / 3) * 2;
1937 
1938  if (worst_majority >= thresh)
1939  {
1940  switch (session->early_stopping)
1941  {
1942  case EARLY_STOPPING_NONE:
1945  "P%u: Stopping early (after one more superround)\n",
1946  session->local_peer_idx);
1947  break;
1949  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: finishing steps due to early finish\n",
1950  session->local_peer_idx);
1952  {
1953  struct Step *step;
1954  for (step = session->steps_head; NULL != step; step = step->next)
1955  try_finish_step_early (step);
1956  }
1957  break;
1958  case EARLY_STOPPING_DONE:
1959  /* We shouldn't be here anymore after early stopping */
1960  GNUNET_break (0);
1961  break;
1962  default:
1963  GNUNET_assert (0);
1964  break;
1965  }
1966  }
1967  else if (EARLY_STOPPING_NONE != session->early_stopping)
1968  {
1969  // Our assumption about the number of bad peers
1970  // has been broken.
1971  GNUNET_break_op (0);
1972  }
1973  else
1974  {
1975  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: NOT finishing early (majority not good enough)\n",
1976  session->local_peer_idx);
1977  }
1978  }
1980 }
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:733
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:686
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:78
#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:80
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 1984 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().

1985 {
1986  struct ConsensusSession *session = task->step->session;
1987  struct ReferendumEntry *output_rfn;
1988  struct ReferendumEntry *input_rfn;
1989  struct DiffEntry *input_diff;
1990  struct RfnKey rfn_key;
1991  struct DiffKey diff_key;
1993  struct RfnElementInfo *ri;
1994  unsigned int gradecast_confidence = 2;
1995 
1996  rfn_key = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1997  output_rfn = lookup_rfn (session, &rfn_key);
1998  if (NULL == output_rfn)
1999  {
2000  output_rfn = rfn_create (session->num_peers);
2001  output_rfn->key = rfn_key;
2002  put_rfn (session, output_rfn);
2003  }
2004 
2005  diff_key = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, task->key.repetition, task->key.leader };
2006  input_diff = lookup_diff (session, &diff_key);
2007  GNUNET_assert (NULL != input_diff);
2008 
2009  rfn_key = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition, task->key.leader };
2010  input_rfn = lookup_rfn (session, &rfn_key);
2011  GNUNET_assert (NULL != input_rfn);
2012 
2014 
2015  apply_diff_to_rfn (input_diff, output_rfn, task->key.leader, session->num_peers);
2016 
2017  while (GNUNET_YES ==
2019  NULL,
2020  (const void **) &ri))
2021  {
2022  uint16_t majority_num;
2023  enum ReferendumVote majority_vote;
2024 
2025  // XXX: we need contested votes and non-contested votes here
2026  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2027 
2028  if (majority_num <= session->num_peers / 3)
2029  majority_vote = VOTE_REMOVE;
2030 
2031  switch (majority_vote)
2032  {
2033  case VOTE_STAY:
2034  break;
2035  case VOTE_ADD:
2036  rfn_vote (output_rfn, task->key.leader, VOTE_ADD, ri->element);
2037  break;
2038  case VOTE_REMOVE:
2039  rfn_vote (output_rfn, task->key.leader, VOTE_REMOVE, ri->element);
2040  break;
2041  default:
2042  GNUNET_assert (0);
2043  break;
2044  }
2045  }
2047 
2048  {
2049  uint16_t noncontested;
2050  noncontested = rfn_noncontested (input_rfn);
2051  if (noncontested < (session->num_peers / 3) * 2)
2052  {
2053  gradecast_confidence = GNUNET_MIN(1, gradecast_confidence);
2054  }
2055  if (noncontested < (session->num_peers / 3) + 1)
2056  {
2057  gradecast_confidence = 0;
2058  }
2059  }
2060 
2061  if (gradecast_confidence >= 1)
2062  rfn_commit (output_rfn, task->key.leader);
2063 
2064  if (gradecast_confidence <= 1)
2065  session->peers_blacklisted[task->key.leader] = GNUNET_YES;
2066 
2067  finish_task (task);
2068 }
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:83
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:80
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 2072 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().

2073 {
2074  struct SetEntry *input;
2075  struct SetOpCls *setop = &task->cls.setop;
2076  struct ConsensusSession *session = task->step->session;
2077 
2078  input = lookup_set (session, &setop->input_set);
2079  GNUNET_assert (NULL != input);
2080  GNUNET_assert (NULL != input->h);
2081 
2082  /* We create the outputs for the operation here
2083  (rather than in the set operation callback)
2084  because we want something valid in there, even
2085  if the other peer doesn't talk to us */
2086 
2087  if (SET_KIND_NONE != setop->output_set.set_kind)
2088  {
2089  /* If we don't have an existing output set,
2090  we clone the input set. */
2091  if (NULL == lookup_set (session, &setop->output_set))
2092  {
2093  create_set_copy_for_task (task, &setop->input_set, &setop->output_set);
2094  return;
2095  }
2096  }
2097 
2098  if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
2099  {
2100  if (NULL == lookup_rfn (session, &setop->output_rfn))
2101  {
2102  struct ReferendumEntry *rfn;
2103 
2105  "P%u: output rfn <%s> missing, creating.\n",
2106  session->local_peer_idx,
2107  debug_str_rfn_key (&setop->output_rfn));
2108 
2109  rfn = rfn_create (session->num_peers);
2110  rfn->key = setop->output_rfn;
2111  put_rfn (session, rfn);
2112  }
2113  }
2114 
2115  if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
2116  {
2117  if (NULL == lookup_diff (session, &setop->output_diff))
2118  {
2119  struct DiffEntry *diff;
2120 
2121  diff = diff_create ();
2122  diff->key = setop->output_diff;
2123  put_diff (session, diff);
2124  }
2125  }
2126 
2127  if ( (task->key.peer1 == session->local_peer_idx) && (task->key.peer2 == session->local_peer_idx) )
2128  {
2129  /* XXX: mark the corresponding rfn as commited if necessary */
2130  finish_task (task);
2131  return;
2132  }
2133 
2134  if (task->key.peer1 == session->local_peer_idx)
2135  {
2137 
2139  "P%u: Looking up set {%s} to run remote union\n",
2140  session->local_peer_idx,
2141  debug_str_set_key (&setop->input_set));
2142 
2143  rcm.header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
2144  rcm.header.size = htons (sizeof (struct GNUNET_CONSENSUS_RoundContextMessage));
2145 
2146  rcm.kind = htons (task->key.kind);
2147  rcm.peer1 = htons (task->key.peer1);
2148  rcm.peer2 = htons (task->key.peer2);
2149  rcm.leader = htons (task->key.leader);
2150  rcm.repetition = htons (task->key.repetition);
2151  rcm.is_contested = htons (0);
2152 
2153  GNUNET_assert (NULL == setop->op);
2154  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: initiating set op with P%u, our set is %s\n",
2155  session->local_peer_idx, task->key.peer2, debug_str_set_key (&setop->input_set));
2156 
2157  struct GNUNET_SET_Option opts[] = {
2158  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2160  };
2161 
2162  // XXX: maybe this should be done while
2163  // setting up tasks alreays?
2164  setop->op = GNUNET_SET_prepare (&session->peers[task->key.peer2],
2165  &session->global_id,
2166  &rcm.header,
2168  opts,
2169  set_result_cb,
2170  task);
2171 
2172  commit_set (session, task);
2173  }
2174  else if (task->key.peer2 == session->local_peer_idx)
2175  {
2176  /* Wait for the other peer to contact us */
2177  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting set op with P%u\n",
2178  session->local_peer_idx, task->key.peer1);
2179 
2180  if (NULL != setop->op)
2181  {
2182  commit_set (session, task);
2183  }
2184  }
2185  else
2186  {
2187  /* We made an error while constructing the task graph. */
2188  GNUNET_assert (0);
2189  }
2190 }
#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:812
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 2194 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().

2195 {
2197  struct ReferendumEntry *input_rfn;
2198  struct RfnElementInfo *ri;
2199  struct SetEntry *output_set;
2200  struct SetMutationProgressCls *progress_cls;
2201  struct ConsensusSession *session = task->step->session;
2202  struct SetKey sk_in;
2203  struct SetKey sk_out;
2204  struct RfnKey rk_in;
2205 
2206  sk_in = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, task->key.repetition, task->key.leader };
2207  sk_out = (struct SetKey) { SET_KIND_ECHO_RESULT, task->key.repetition, task->key.leader };
2208  output_set = lookup_set (session, &sk_out);
2209  if (NULL == output_set)
2210  {
2211  create_set_copy_for_task (task, &sk_in, &sk_out);
2212  return;
2213  }
2214 
2215 
2216  {
2217  // FIXME: should be marked as a shallow copy, so
2218  // we can destroy everything correctly
2219  struct SetEntry *last_set = GNUNET_new (struct SetEntry);
2220  last_set->h = output_set->h;
2221  last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
2222  put_set (session, last_set);
2223  }
2224 
2226  "Evaluating referendum in Task {%s}\n",
2227  debug_str_task_key (&task->key));
2228 
2229  progress_cls = GNUNET_new (struct SetMutationProgressCls);
2230  progress_cls->task = task;
2231 
2232  rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition, task->key.leader };
2233  input_rfn = lookup_rfn (session, &rk_in);
2234 
2235  GNUNET_assert (NULL != input_rfn);
2236 
2238  GNUNET_assert (NULL != iter);
2239 
2240  while (GNUNET_YES ==
2242  NULL,
2243  (const void **) &ri))
2244  {
2245  enum ReferendumVote majority_vote;
2246  uint16_t majority_num;
2247 
2248  rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2249 
2250  if (majority_num < session->num_peers / 3)
2251  {
2252  /* It is not the case that all nonfaulty peers
2253  echoed the same value. Since we're doing a set reconciliation, we
2254  can't simply send "nothing" for the value. Thus we mark our 'confirm'
2255  reconciliation as contested. Other peers might not know that the
2256  leader is faulty, thus we still re-distribute in the confirmation
2257  round. */
2258  output_set->is_contested = GNUNET_YES;
2259  }
2260 
2261  switch (majority_vote)
2262  {
2263  case VOTE_ADD:
2264  progress_cls->num_pending++;
2266  GNUNET_SET_add_element (output_set->h,
2267  ri->element,
2269  progress_cls));
2270  break;
2271  case VOTE_REMOVE:
2272  progress_cls->num_pending++;
2274  GNUNET_SET_remove_element (output_set->h,
2275  ri->element,
2277  progress_cls));
2278  break;
2279  case VOTE_STAY:
2280  /* Nothing to do. */
2281  break;
2282  default:
2283  /* not reached */
2284  GNUNET_assert (0);
2285  }
2286  }
2287 
2289 
2290  if (0 == progress_cls->num_pending)
2291  {
2292  // call closure right now, no pending ops
2293  GNUNET_free (progress_cls);
2294  finish_task (task);
2295  }
2296 }
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:733
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:686
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:78
#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:80
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 2300 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().

2301 {
2302  struct SetEntry *final_set;
2303  struct ConsensusSession *session = task->step->session;
2304 
2305  final_set = lookup_set (session, &task->cls.finish.input_set);
2306 
2307  GNUNET_assert (NULL != final_set);
2308 
2309 
2310  GNUNET_SET_iterate (final_set->h,
2312  task);
2313 }
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:1168
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 2316 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().

2317 {
2318  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: starting task {%s}\n", session->local_peer_idx, debug_str_task_key (&task->key));
2319 
2320  GNUNET_assert (GNUNET_NO == task->is_started);
2321  GNUNET_assert (GNUNET_NO == task->is_finished);
2322  GNUNET_assert (NULL != task->start);
2323 
2324  task->start (task);
2325 
2326  task->is_started = GNUNET_YES;
2327 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 2405 of file gnunet-service-consensus.c.

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

Referenced by handle_client_join().

2406 {
2407  int i;
2408  for (i = 0; i < session->num_peers; i++)
2409  if (0 == GNUNET_memcmp (peer, &session->peers[i]))
2410  return i;
2411  return -1;
2412 }
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 2425 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().

2427 {
2428  const char *salt = "gnunet-service-consensus/session_id";
2429 
2431  GNUNET_CRYPTO_kdf (&session->global_id,
2432  sizeof (struct GNUNET_HashCode),
2433  salt,
2434  strlen (salt),
2435  session->peers,
2436  session->num_peers * sizeof (struct GNUNET_PeerIdentity),
2437  local_session_id,
2438  sizeof (struct GNUNET_HashCode),
2439  NULL));
2440 }
#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:80
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ peer_id_cmp()

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

Compare two peer identities.

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

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

Referenced by initialize_session_peer_list().

2452 {
2453  return memcmp (h1, h2, sizeof (struct GNUNET_PeerIdentity));
2454 }
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 2465 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().

2467 {
2468  const struct GNUNET_PeerIdentity *msg_peers
2469  = (const struct GNUNET_PeerIdentity *) &join_msg[1];
2470  int local_peer_in_list;
2471 
2472  session->num_peers = ntohl (join_msg->num_peers);
2473 
2474  /* Peers in the join message, may or may not include the local peer,
2475  Add it if it is missing. */
2476  local_peer_in_list = GNUNET_NO;
2477  for (unsigned int i = 0; i < session->num_peers; i++)
2478  {
2479  if (0 == GNUNET_memcmp (&msg_peers[i],
2480  &my_peer))
2481  {
2482  local_peer_in_list = GNUNET_YES;
2483  break;
2484  }
2485  }
2486  if (GNUNET_NO == local_peer_in_list)
2487  session->num_peers++;
2488 
2489  session->peers = GNUNET_new_array (session->num_peers,
2490  struct GNUNET_PeerIdentity);
2491  if (GNUNET_NO == local_peer_in_list)
2492  session->peers[session->num_peers - 1] = my_peer;
2493 
2494  GNUNET_memcpy (session->peers,
2495  msg_peers,
2496  ntohl (join_msg->num_peers) * sizeof (struct GNUNET_PeerIdentity));
2497  qsort (session->peers,
2498  session->num_peers,
2499  sizeof (struct GNUNET_PeerIdentity),
2500  &peer_id_cmp);
2501 }
static int peer_id_cmp(const void *h1, const void *h2)
Compare two peer identities.
#define GNUNET_NO
Definition: gnunet_common.h:81
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_memcpy(dst, src, n)
#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:80
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 2505 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().

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

◆ set_listen_cb()

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

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

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

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

2538 {
2539  struct ConsensusSession *session = cls;
2540  struct TaskKey tk;
2541  struct TaskEntry *task;
2543 
2544  if (NULL == context_msg)
2545  {
2546  GNUNET_break_op (0);
2547  return;
2548  }
2549 
2550  if (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT != ntohs (context_msg->type))
2551  {
2552  GNUNET_break_op (0);
2553  return;
2554  }
2555 
2556  if (sizeof (struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs (context_msg->size))
2557  {
2558  GNUNET_break_op (0);
2559  return;
2560  }
2561 
2562  cm = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg;
2563 
2564  tk = ((struct TaskKey) {
2565  .kind = ntohs (cm->kind),
2566  .peer1 = ntohs (cm->peer1),
2567  .peer2 = ntohs (cm->peer2),
2568  .repetition = ntohs (cm->repetition),
2569  .leader = ntohs (cm->leader),
2570  });
2571 
2572  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2573  session->local_peer_idx, debug_str_task_key (&tk));
2574 
2575  task = lookup_task (session, &tk);
2576 
2577  if (NULL == task)
2578  {
2579  GNUNET_break_op (0);
2580  return;
2581  }
2582 
2583  if (GNUNET_YES == task->is_finished)
2584  {
2585  GNUNET_break_op (0);
2586  return;
2587  }
2588 
2589  if (task->key.peer2 != session->local_peer_idx)
2590  {
2591  /* We're being asked, so we must be thne 2nd peer. */
2592  GNUNET_break_op (0);
2593  return;
2594  }
2595 
2596  GNUNET_assert (! ((task->key.peer1 == session->local_peer_idx) &&
2597  (task->key.peer2 == session->local_peer_idx)));
2598 
2599  struct GNUNET_SET_Option opts[] = {
2600  { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2602  };
2603 
2604  task->cls.setop.op = GNUNET_SET_accept (request,
2606  opts,
2607  set_result_cb,
2608  task);
2609 
2610  /* If the task hasn't been started yet,
2611  we wait for that until we commit. */
2612 
2613  if (GNUNET_YES == task->is_started)
2614  {
2615  commit_set (session, task);
2616  }
2617 }
#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:80
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:1081
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 2622 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().

2624 {
2625  struct GNUNET_HashCode round_hash;
2626  struct Step *s;
2627 
2628  GNUNET_assert (NULL != t->step);
2629 
2630  t = GNUNET_memdup (t, sizeof (struct TaskEntry));
2631 
2632  s = t->step;
2633 
2634  if (s->tasks_len == s->tasks_cap)
2635  {
2636  unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2638  s->tasks_cap,
2639  target_size);
2640  }
2641 
2642 #ifdef GNUNET_EXTRA_LOGGING
2643  GNUNET_assert (NULL != s->debug_name);
2644  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2645  debug_str_task_key (&t->key),
2646  s->debug_name);
2647 #endif
2648 
2649  s->tasks[s->tasks_len] = t;
2650  s->tasks_len++;
2651 
2652  GNUNET_CRYPTO_hash (&t->key, sizeof (struct TaskKey), &round_hash);
2654  GNUNET_CONTAINER_multihashmap_put (taskmap, &round_hash, t,
2656 }
#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:78
unsigned int tasks_len
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
A 512-bit hashcode.
char * debug_name
Human-readable name for the task, used for debugging.
struct TaskKey key
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct TaskEntry ** tasks
Tasks that this step is composed of.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Tuple of integers that together identify a task uniquely.
struct Step * step
#define GNUNET_log(kind,...)
unsigned int tasks_cap
Here is the call graph for this function:
Here is the caller graph for this function:

◆ install_step_timeouts()

static void install_step_timeouts ( struct ConsensusSession session)
static

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

Referenced by handle_client_conclude().

2661 {
2662  /* Given the fully constructed task graph
2663  with rounds for tasks, we can give the tasks timeouts. */
2664 
2665  // unsigned int max_round;
2666 
2667  /* XXX: implement! */
2668 }
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 2676 of file gnunet-service-consensus.c.

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

2677 {
2678  uint16_t a;
2679  uint16_t b;
2680 
2681  GNUNET_assert (*p1 < n);
2682  GNUNET_assert (*p2 < n);
2683 
2684  if (*p1 < *p2)
2685  {
2686  a = *p1;
2687  b = *p2;
2688  }
2689  else
2690  {
2691  a = *p2;
2692  b = *p1;
2693  }
2694 
2695  /* For uniformly random *p1, *p2,
2696  this condition is true with 50% chance */
2697  if (((b - a) + n) % n <= n / 2)
2698  {
2699  *p1 = a;
2700  *p2 = b;
2701  }
2702  else
2703  {
2704  *p1 = b;
2705  *p2 = a;
2706  }
2707 }
#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 2714 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().

2715 {
2716  /* We're not checking for cyclic dependencies,
2717  but this is a cheap sanity check. */
2718  GNUNET_assert (step != dep);
2719  GNUNET_assert (NULL != step);
2720  GNUNET_assert (NULL != dep);
2721  GNUNET_assert (dep->round <= step->round);
2722 
2723 #ifdef GNUNET_EXTRA_LOGGING
2724  /* Make sure we have complete debugging information.
2725  Also checks that we don't screw up too badly
2726  constructing the task graph. */
2727  GNUNET_assert (NULL != step->debug_name);
2728  GNUNET_assert (NULL != dep->debug_name);
2730  "Making step `%s' depend on `%s'\n",
2731  step->debug_name,
2732  dep->debug_name);
2733 #endif
2734 
2735  if (dep->subordinates_cap == dep->subordinates_len)
2736  {
2737  unsigned int target_size = 3 * (dep->subordinates_cap + 1) / 2;
2739  dep->subordinates_cap,
2740  target_size);
2741  }
2742 
2744 
2745  dep->subordinates[dep->subordinates_len] = step;
2746  dep->subordinates_len++;
2747 
2748  step->pending_prereq++;
2749 }
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 2753 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().

2754 {
2755  struct Step *step;
2756  step = GNUNET_new (struct Step);
2757  step->session = session;
2758  step->round = round;
2761  session->steps_tail,
2762  step);
2763  return step;
2764 }
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 2772 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().

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

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