GNUnet 0.21.1
gnunet-service-consensus.c File Reference

multi-peer set reconciliation More...

Include dependency graph for gnunet-service-consensus.c:

Go to the source code of this file.

Data Structures

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

multi-peer set reconciliation

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

Definition in file gnunet-service-consensus.c.

Typedef Documentation

◆ TaskFunc

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

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

Enumeration Type Documentation

◆ ReferendumVote

Enumerator
VOTE_STAY 

Vote that nothing should change.

This option is never voted explicitly.

VOTE_ADD 

Vote that an element should be added.

VOTE_REMOVE 

Vote that an element should be removed.

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

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

◆ EarlyStoppingPhase

Enumerator
EARLY_STOPPING_NONE 
EARLY_STOPPING_ONE_MORE 
EARLY_STOPPING_DONE 

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

56{
60};
@ EARLY_STOPPING_DONE
@ EARLY_STOPPING_NONE
@ EARLY_STOPPING_ONE_MORE

◆ PhaseKind

enum PhaseKind
Enumerator
PHASE_KIND_ALL_TO_ALL 
PHASE_KIND_ALL_TO_ALL_2 
PHASE_KIND_GRADECAST_LEADER 
PHASE_KIND_GRADECAST_ECHO 
PHASE_KIND_GRADECAST_ECHO_GRADE 
PHASE_KIND_GRADECAST_CONFIRM 
PHASE_KIND_GRADECAST_CONFIRM_GRADE 
PHASE_KIND_APPLY_REP 

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

PHASE_KIND_FINISH 

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

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

◆ SetKind

enum SetKind
Enumerator
SET_KIND_NONE 
SET_KIND_CURRENT 
SET_KIND_LAST_GRADECAST 

Last result set from a gradecast.

SET_KIND_LEADER_PROPOSAL 
SET_KIND_ECHO_RESULT 

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

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

◆ DiffKind

enum DiffKind
Enumerator
DIFF_KIND_NONE 
DIFF_KIND_LEADER_PROPOSAL 
DIFF_KIND_LEADER_CONSENSUS 
DIFF_KIND_GRADECAST_RESULT 

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

◆ RfnKind

enum RfnKind
Enumerator
RFN_KIND_NONE 
RFN_KIND_ECHO 
RFN_KIND_CONFIRM 
RFN_KIND_GRADECAST_RESULT 

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

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

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

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

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

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

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

◆ run_ready_steps()

static void run_ready_steps ( struct ConsensusSession session)
static

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

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

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

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

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

◆ phasename()

static const char * phasename ( uint16_t  phase)
static

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

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

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

◆ setname()

static const char * setname ( uint16_t  kind)
static

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

580{
581 switch (kind)
582 {
583 case SET_KIND_CURRENT: return "CURRENT";
584
585 case SET_KIND_LEADER_PROPOSAL: return "LEADER_PROPOSAL";
586
587 case SET_KIND_NONE: return "NONE";
588
589 default: return "(unknown)";
590 }
591}

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

◆ rfnname()

static const char * rfnname ( uint16_t  kind)
static

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

596{
597 switch (kind)
598 {
599 case RFN_KIND_NONE: return "NONE";
600
601 case RFN_KIND_ECHO: return "ECHO";
602
603 case RFN_KIND_CONFIRM: return "CONFIRM";
604
605 default: return "(unknown)";
606 }
607}

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

◆ diffname()

static const char * diffname ( uint16_t  kind)
static

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

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

References DIFF_KIND_GRADECAST_RESULT, DIFF_KIND_LEADER_CONSENSUS, DIFF_KIND_LEADER_PROPOSAL, and DIFF_KIND_NONE.

◆ send_to_client_iter()

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

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

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

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

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

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

Referenced by task_start_finish().

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

◆ lookup_set()

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

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

764{
765 struct GNUNET_HashCode hash;
766
768 "P%u: looking up set {%s}\n",
769 session->local_peer_idx,
770 debug_str_set_key (key));
771
772 GNUNET_assert (SET_KIND_NONE != key->set_kind);
774 sizeof(struct SetKey),
775 &hash);
777 &hash);
778}
struct GNUNET_HashCode key
The key used in the DHT.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
struct GNUNET_CONTAINER_MultiHashMap * setmap
A 512-bit hashcode.

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

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

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

◆ lookup_diff()

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

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

784{
785 struct GNUNET_HashCode hash;
786
788 "P%u: looking up diff {%s}\n",
789 session->local_peer_idx,
790 debug_str_diff_key (key));
791 GNUNET_assert (DIFF_KIND_NONE != key->diff_kind);
793 sizeof(struct DiffKey),
794 &hash);
796 &hash);
797}
struct GNUNET_CONTAINER_MultiHashMap * diffmap

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

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

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

◆ lookup_rfn()

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

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

803{
804 struct GNUNET_HashCode hash;
805
807 "P%u: looking up rfn {%s}\n",
808 session->local_peer_idx,
809 debug_str_rfn_key (key));
810 GNUNET_assert (RFN_KIND_NONE != key->rfn_kind);
812 sizeof(struct RfnKey),
813 &hash);
815 &hash);
816}
struct GNUNET_CONTAINER_MultiHashMap * rfnmap

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

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

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

◆ diff_insert()

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

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

823{
824 struct DiffElementInfo *di;
825 struct GNUNET_HashCode hash;
826
827 GNUNET_assert ((1 == weight) || (-1 == weight));
828
830 "diff_insert with element size %u\n",
831 element->size);
832
834 "hashing element\n");
835
836 GNUNET_SET_element_hash (element, &hash);
837
839 "hashed element\n");
840
841 di = GNUNET_CONTAINER_multihashmap_get (diff->changes, &hash);
842
843 if (NULL == di)
844 {
845 di = GNUNET_new (struct DiffElementInfo);
846 di->element = GNUNET_SET_element_dup (element);
849 &hash,
850 di,
852 }
853
854 di->weight = weight;
855}
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
@ GNUNET_OK
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SET_Element * GNUNET_SET_element_dup(const struct GNUNET_SET_Element *element)
Create a copy of an element.
Definition: set_api.c:1168
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1184
int weight
Positive weight for 'add', negative weights for 'remove'.
const struct GNUNET_SET_Element * element
struct GNUNET_CONTAINER_MultiHashMap * changes

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

Referenced by set_result_cb().

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

◆ rfn_commit()

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

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

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

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

Referenced by set_result_cb(), and task_start_grade().

Here is the caller graph for this function:

◆ rfn_contest()

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

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

871{
872 GNUNET_assert (contested_peer < rfn->num_peers);
873
874 rfn->peer_contested[contested_peer] = GNUNET_YES;
875}
int * peer_contested
Contestation state of the peer.

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

Referenced by set_result_cb().

Here is the caller graph for this function:

◆ rfn_noncontested()

static uint16_t rfn_noncontested ( struct ReferendumEntry rfn)
static

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

880{
881 uint16_t ret;
882
883 ret = 0;
884 for (uint16_t i = 0; i < rfn->num_peers; i++)
885 if ((GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO ==
886 rfn->peer_contested[i]))
887 ret++;
888
889 return ret;
890}
static int ret
Final status code.
Definition: gnunet-arm.c:94

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

Referenced by task_start_grade().

Here is the caller graph for this function:

◆ rfn_vote()

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

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

898{
899 struct RfnElementInfo *ri;
900 struct GNUNET_HashCode hash;
901
902 GNUNET_assert (voting_peer < rfn->num_peers);
903
904 /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
905 since VOTE_KEEP is implicit in not voting. */
906 GNUNET_assert ((VOTE_ADD == vote) || (VOTE_REMOVE == vote));
907
908 GNUNET_SET_element_hash (element, &hash);
910
911 if (NULL == ri)
912 {
913 ri = GNUNET_new (struct RfnElementInfo);
914 ri->element = GNUNET_SET_element_dup (element);
915 ri->votes = GNUNET_new_array (rfn->num_peers, int);
918 &hash, ri,
920 }
921
922 ri->votes[voting_peer] = GNUNET_YES;
923 ri->proposal = vote;
924}
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
struct GNUNET_CONTAINER_MultiHashMap * rfn_elements
enum ReferendumVote proposal
Proposal for this element, can only be VOTE_ADD or VOTE_REMOVE.
int * votes
GNUNET_YES if the peer votes for the proposal.
const struct GNUNET_SET_Element * element

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

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

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

◆ task_other_peer()

static uint16_t task_other_peer ( struct TaskEntry task)
static

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

929{
930 uint16_t me = task->step->session->local_peer_idx;
931
932 if (task->key.peer1 == me)
933 return task->key.peer2;
934 return task->key.peer1;
935}
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
int16_t peer1
Number of the first peer in canonical order.
int16_t peer2
Number of the second peer in canonical order.

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

Referenced by commit_set(), and set_result_cb().

Here is the caller graph for this function:

◆ cmp_uint64_t()

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

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

940{
941 uint64_t a = *(uint64_t *) pa;
942 uint64_t b = *(uint64_t *) pb;
943
944 if (a == b)
945 return 0;
946 if (a < b)
947 return -1;
948 return 1;
949}

Referenced by set_result_cb().

Here is the caller graph for this function:

◆ set_result_cb()

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

Callback for set operation results.

Called for each element in the result set.

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

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

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

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

Referenced by set_listen_cb(), and task_start_reconcile().

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

◆ commit_set()

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

Commit the appropriate set for a task.

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

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

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

Referenced by set_listen_cb(), and task_start_reconcile().

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

◆ put_diff()

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

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

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

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

Referenced by task_start_reconcile().

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

◆ put_set()

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

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

1572{
1573 struct GNUNET_HashCode hash;
1574
1575 GNUNET_assert (NULL != set->h);
1577 "Putting set %s\n",
1578 debug_str_set_key (&set->key));
1579 GNUNET_CRYPTO_hash (&set->key,
1580 sizeof(struct SetKey),
1581 &hash);
1584 &hash,
1585 set,
1587}
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
@ GNUNET_SYSERR

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

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

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

◆ put_rfn()

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

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

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

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

Referenced by task_start_grade(), and task_start_reconcile().

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

◆ task_cancel_reconcile()

static void task_cancel_reconcile ( struct TaskEntry task)
static

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

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

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

Here is the caller graph for this function:

◆ apply_diff_to_rfn()

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

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

1618{
1620 struct DiffElementInfo *di;
1621
1623
1624 while (GNUNET_YES ==
1626 NULL,
1627 (const void **) &di))
1628 {
1629 if (di->weight > 0)
1630 {
1631 rfn_vote (rfn, voting_peer, VOTE_ADD, di->element);
1632 }
1633 if (di->weight < 0)
1634 {
1635 rfn_vote (rfn, voting_peer, VOTE_REMOVE, di->element);
1636 }
1637 }
1638
1640}
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator's position.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.

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

Referenced by task_start_grade().

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

◆ diff_create()

static struct DiffEntry * diff_create ( void  )
static

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

1645{
1646 struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1647
1649 GNUNET_NO);
1650
1651 return d;
1652}
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.

References d, GNUNET_CONTAINER_multihashmap_create(), GNUNET_new, and GNUNET_NO.

Referenced by task_start_reconcile().

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

◆ rfn_create()

struct ReferendumEntry * rfn_create ( uint16_t  size)

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

1699{
1700 struct ReferendumEntry *rfn;
1701
1702 rfn = GNUNET_new (struct ReferendumEntry);
1704 rfn->peer_commited = GNUNET_new_array (size, int);
1705 rfn->peer_contested = GNUNET_new_array (size, int);
1706 rfn->num_peers = size;
1707
1708 return rfn;
1709}
static unsigned int size
Size of the "table".
Definition: peer.c:68

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

Referenced by task_start_grade(), and task_start_reconcile().

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

◆ rfn_majority()

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

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

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

1734{
1735 uint16_t votes_yes = 0;
1736 uint16_t num_commited = 0;
1737
1739 "Computing rfn majority for element %s of rfn {%s}\n",
1740 debug_str_element (ri->element),
1741 debug_str_rfn_key (&rfn->key));
1742
1743 for (uint16_t i = 0; i < rfn->num_peers; i++)
1744 {
1745 if (GNUNET_NO == rfn->peer_commited[i])
1746 continue;
1747 num_commited++;
1748
1749 if (GNUNET_YES == ri->votes[i])
1750 votes_yes++;
1751 }
1752
1753 if (votes_yes > (num_commited) / 2)
1754 {
1755 *ret_vote = ri->proposal;
1756 *ret_majority = votes_yes;
1757 }
1758 else
1759 {
1760 *ret_vote = VOTE_STAY;
1761 *ret_majority = num_commited - votes_yes;
1762 }
1763}

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

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

Here is the caller graph for this function:

◆ set_copy_cb()

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

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

1776{
1777 struct SetCopyCls *scc = cls;
1778 struct TaskEntry *task = scc->task;
1779 struct SetKey dst_set_key = scc->dst_set_key;
1780 struct SetEntry *set;
1781 struct SetHandle *sh = GNUNET_new (struct SetHandle);
1782
1783 sh->h = copy;
1786 sh);
1787
1788 GNUNET_free (scc);
1789 set = GNUNET_new (struct SetEntry);
1790 set->h = copy;
1791 set->key = dst_set_key;
1792 put_set (task->step->session, set);
1793
1794 task->start (task);
1795}
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
static void put_set(struct ConsensusSession *session, struct SetEntry *set)
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct SetHandle * set_handles_tail
struct SetHandle * set_handles_head
struct SetKey dst_set_key
struct TaskEntry * task

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

Referenced by create_set_copy_for_task().

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

◆ create_set_copy_for_task()

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

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

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

1806{
1807 struct SetEntry *src_set;
1808 struct SetCopyCls *scc = GNUNET_new (struct SetCopyCls);
1809
1811 "Copying set {%s} to {%s} for task {%s}\n",
1812 debug_str_set_key (src_set_key),
1813 debug_str_set_key (dst_set_key),
1814 debug_str_task_key (&task->key));
1815
1816 scc->task = task;
1817 scc->dst_set_key = *dst_set_key;
1818 src_set = lookup_set (task->step->session, src_set_key);
1819 GNUNET_assert (NULL != src_set);
1820 GNUNET_SET_copy_lazy (src_set->h,
1822 scc);
1823}
static void set_copy_cb(void *cls, struct GNUNET_SET_Handle *copy)
void GNUNET_SET_copy_lazy(struct GNUNET_SET_Handle *set, GNUNET_SET_CopyReadyCallback cb, void *cls)
Definition: set_api.c:1139

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

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

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

◆ set_mutation_done()

static void set_mutation_done ( void *  cls)
static

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

1838{
1839 struct SetMutationProgressCls *pc = cls;
1840
1841 GNUNET_assert (pc->num_pending > 0);
1842
1843 pc->num_pending--;
1844
1845 if (0 == pc->num_pending)
1846 {
1847 struct TaskEntry *task = pc->task;
1848 GNUNET_free (pc);
1849 finish_task (task);
1850 }
1851}
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.

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

Referenced by task_start_apply_round(), and task_start_eval_echo().

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

◆ try_finish_step_early()

static void try_finish_step_early ( struct Step step)
static

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

1856{
1857 if (GNUNET_YES == step->is_running)
1858 return;
1859 if (GNUNET_YES == step->is_finished)
1860 return;
1861 if (GNUNET_NO == step->early_finishable)
1862 return;
1863
1864 step->is_finished = GNUNET_YES;
1865
1866#ifdef GNUNET_EXTRA_LOGGING
1868 "Finishing step `%s' early.\n",
1869 step->debug_name);
1870#endif
1871
1872 for (unsigned int i = 0; i < step->subordinates_len; i++)
1873 {
1875 step->subordinates[i]->pending_prereq--;
1876#ifdef GNUNET_EXTRA_LOGGING
1878 "Decreased pending_prereq to %u for step `%s'.\n",
1879 (unsigned int) step->subordinates[i]->pending_prereq,
1880 step->subordinates[i]->debug_name);
1881#endif
1883 }
1884
1885 // XXX: maybe schedule as task to avoid recursion?
1886 run_ready_steps (step->session);
1887}
static void try_finish_step_early(struct Step *step)
static void run_ready_steps(struct ConsensusSession *session)
int early_finishable
When we're doing an early finish, how should this step be treated? If GNUNET_YES, the step will be ma...
struct Step ** subordinates

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

Referenced by task_start_apply_round(), and try_finish_step_early().

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

◆ finish_step()

static void finish_step ( struct Step step)
static

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

1892{
1893 GNUNET_assert (step->finished_tasks == step->tasks_len);
1896
1897#ifdef GNUNET_EXTRA_LOGGING
1899 "All tasks of step `%s' with %u subordinates finished.\n",
1900 step->debug_name,
1901 step->subordinates_len);
1902#endif
1903
1904 for (unsigned int i = 0; i < step->subordinates_len; i++)
1905 {
1907 step->subordinates[i]->pending_prereq--;
1908#ifdef GNUNET_EXTRA_LOGGING
1910 "Decreased pending_prereq to %u for step `%s'.\n",
1911 (unsigned int) step->subordinates[i]->pending_prereq,
1912 step->subordinates[i]->debug_name);
1913#endif
1914 }
1915
1916 step->is_finished = GNUNET_YES;
1917
1918 // XXX: maybe schedule as task to avoid recursion?
1919 run_ready_steps (step->session);
1920}

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

Referenced by finish_task(), and run_ready_steps().

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

◆ task_start_apply_round()

static void task_start_apply_round ( struct TaskEntry task)
static

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

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

Parameters
taskthe task with context information

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

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

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

Referenced by construct_task_graph().

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

◆ task_start_grade()

static void task_start_grade ( struct TaskEntry task)
static

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

2081{
2082 struct ConsensusSession *session = task->step->session;
2083 struct ReferendumEntry *output_rfn;
2084 struct ReferendumEntry *input_rfn;
2085 struct DiffEntry *input_diff;
2086 struct RfnKey rfn_key;
2087 struct DiffKey diff_key;
2089 struct RfnElementInfo *ri;
2090 unsigned int gradecast_confidence = 2;
2091
2092 rfn_key = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
2093 output_rfn = lookup_rfn (session, &rfn_key);
2094 if (NULL == output_rfn)
2095 {
2096 output_rfn = rfn_create (session->num_peers);
2097 output_rfn->key = rfn_key;
2098 put_rfn (session, output_rfn);
2099 }
2100
2101 diff_key = (struct DiffKey) { DIFF_KIND_LEADER_PROPOSAL, task->key.repetition,
2102 task->key.leader };
2103 input_diff = lookup_diff (session, &diff_key);
2104 GNUNET_assert (NULL != input_diff);
2105
2106 rfn_key = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2107 task->key.leader };
2108 input_rfn = lookup_rfn (session, &rfn_key);
2109 GNUNET_assert (NULL != input_rfn);
2110
2112 input_rfn->rfn_elements);
2113
2114 apply_diff_to_rfn (input_diff, output_rfn, task->key.leader,
2115 session->num_peers);
2116
2117 while (GNUNET_YES ==
2119 NULL,
2120 (const void **) &ri))
2121 {
2122 uint16_t majority_num;
2123 enum ReferendumVote majority_vote;
2124
2125 // XXX: we need contested votes and non-contested votes here
2126 rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2127
2128 if (majority_num <= session->num_peers / 3)
2129 majority_vote = VOTE_REMOVE;
2130
2131 switch (majority_vote)
2132 {
2133 case VOTE_STAY:
2134 break;
2135
2136 case VOTE_ADD:
2137 rfn_vote (output_rfn, task->key.leader, VOTE_ADD, ri->element);
2138 break;
2139
2140 case VOTE_REMOVE:
2141 rfn_vote (output_rfn, task->key.leader, VOTE_REMOVE, ri->element);
2142 break;
2143
2144 default:
2145 GNUNET_assert (0);
2146 break;
2147 }
2148 }
2150
2151 {
2152 uint16_t noncontested;
2153 noncontested = rfn_noncontested (input_rfn);
2154 if (noncontested < (session->num_peers / 3) * 2)
2155 {
2156 gradecast_confidence = GNUNET_MIN (1, gradecast_confidence);
2157 }
2158 if (noncontested < (session->num_peers / 3) + 1)
2159 {
2160 gradecast_confidence = 0;
2161 }
2162 }
2163
2164 if (gradecast_confidence >= 1)
2165 rfn_commit (output_rfn, task->key.leader);
2166
2167 if (gradecast_confidence <= 1)
2168 session->peers_blacklisted[task->key.leader] = GNUNET_YES;
2169
2170 finish_task (task);
2171}
static void apply_diff_to_rfn(struct DiffEntry *diff, struct ReferendumEntry *rfn, uint16_t voting_peer, uint16_t num_peers)
static void put_rfn(struct ConsensusSession *session, struct ReferendumEntry *rfn)
static uint16_t rfn_noncontested(struct ReferendumEntry *rfn)
struct ReferendumEntry * rfn_create(uint16_t size)
#define GNUNET_MIN(a, b)
int16_t leader
Leader in the gradecast phase.

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

Referenced by construct_task_graph_gradecast().

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

◆ task_start_reconcile()

static void task_start_reconcile ( struct TaskEntry task)
static

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

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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

◆ task_start_eval_echo()

static void task_start_eval_echo ( struct TaskEntry task)
static

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

2302{
2304 struct ReferendumEntry *input_rfn;
2305 struct RfnElementInfo *ri;
2306 struct SetEntry *output_set;
2307 struct SetMutationProgressCls *progress_cls;
2308 struct ConsensusSession *session = task->step->session;
2309 struct SetKey sk_in;
2310 struct SetKey sk_out;
2311 struct RfnKey rk_in;
2312
2313 sk_in = (struct SetKey) { SET_KIND_LEADER_PROPOSAL, task->key.repetition,
2314 task->key.leader };
2315 sk_out = (struct SetKey) { SET_KIND_ECHO_RESULT, task->key.repetition,
2316 task->key.leader };
2317 output_set = lookup_set (session, &sk_out);
2318 if (NULL == output_set)
2319 {
2321 &sk_in,
2322 &sk_out);
2323 return;
2324 }
2325
2326 {
2327 // FIXME: should be marked as a shallow copy, so
2328 // we can destroy everything correctly
2329 struct SetEntry *last_set = GNUNET_new (struct SetEntry);
2330
2331 last_set->h = output_set->h;
2332 last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
2333 put_set (session, last_set);
2334 }
2335
2337 "Evaluating referendum in Task {%s}\n",
2338 debug_str_task_key (&task->key));
2339
2340 progress_cls = GNUNET_new (struct SetMutationProgressCls);
2341 progress_cls->task = task;
2342 rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
2343 task->key.leader };
2344 input_rfn = lookup_rfn (session, &rk_in);
2345 GNUNET_assert (NULL != input_rfn);
2347 input_rfn->rfn_elements);
2348 GNUNET_assert (NULL != iter);
2349
2350 while (GNUNET_YES ==
2352 NULL,
2353 (const void **) &ri))
2354 {
2355 enum ReferendumVote majority_vote;
2356 uint16_t majority_num;
2357
2358 rfn_majority (input_rfn, ri, &majority_num, &majority_vote);
2359
2360 if (majority_num < session->num_peers / 3)
2361 {
2362 /* It is not the case that all nonfaulty peers
2363 echoed the same value. Since we're doing a set reconciliation, we
2364 can't simply send "nothing" for the value. Thus we mark our 'confirm'
2365 reconciliation as contested. Other peers might not know that the
2366 leader is faulty, thus we still re-distribute in the confirmation
2367 round. *///
2368 output_set->is_contested = GNUNET_YES;
2369 }
2370
2371 switch (majority_vote)
2372 {
2373 case VOTE_ADD:
2374 progress_cls->num_pending++;
2376 GNUNET_SET_add_element (output_set->h,
2377 ri->element,
2379 progress_cls));
2380 break;
2381
2382 case VOTE_REMOVE:
2383 progress_cls->num_pending++;
2385 GNUNET_SET_remove_element (output_set->h,
2386 ri->element,
2388 progress_cls));
2389 break;
2390
2391 case VOTE_STAY:
2392 /* Nothing to do. */
2393 break;
2394
2395 default:
2396 /* not reached */
2397 GNUNET_assert (0);
2398 }
2399 }
2400
2402
2403 if (0 == progress_cls->num_pending)
2404 {
2405 // call closure right now, no pending ops
2406 GNUNET_free (progress_cls);
2407 finish_task (task);
2408 }
2409}

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

Referenced by construct_task_graph_gradecast().

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

◆ task_start_finish()

static void task_start_finish ( struct TaskEntry task)
static

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

2414{
2415 struct SetEntry *final_set;
2416 struct ConsensusSession *session = task->step->session;
2417
2418 final_set = lookup_set (session,
2419 &task->cls.finish.input_set);
2420 GNUNET_assert (NULL != final_set);
2421 GNUNET_SET_iterate (final_set->h,
2423 task);
2424}
static int send_to_client_iter(void *cls, const struct GNUNET_SET_Element *element)
Send the final result set of the consensus to the client, element by element.
int GNUNET_SET_iterate(struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *iter_cls)
Iterate over all elements in the given set.
Definition: set_api.c:1117
struct SetKey input_set
struct FinishCls finish

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

Referenced by construct_task_graph().

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

◆ start_task()

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

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

2430{
2432 "P%u: starting task {%s}\n",
2433 session->local_peer_idx,
2434 debug_str_task_key (&task->key));
2437 GNUNET_assert (NULL != task->start);
2438 task->start (task);
2439 task->is_started = GNUNET_YES;
2440}

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

Referenced by run_ready_steps().

Here is the caller graph for this function:

◆ get_peer_idx()

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

Search peer in the list of peers in session.

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

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

2516{
2517 for (int i = 0; i < session->num_peers; i++)
2518 if (0 == GNUNET_memcmp (peer, &session->peers[i]))
2519 return i;
2520 return -1;
2521}
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.

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

Referenced by handle_client_join().

Here is the caller graph for this function:

◆ compute_global_id()

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

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

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

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

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

2536{
2537 const char *salt = "gnunet-service-consensus/session_id";
2538
2540 GNUNET_CRYPTO_kdf (&session->global_id,
2541 sizeof(struct GNUNET_HashCode),
2542 salt,
2543 strlen (salt),
2544 session->peers,
2545 session->num_peers * sizeof(struct
2547 local_session_id,
2548 sizeof(struct GNUNET_HashCode),
2549 NULL));
2550}
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
Definition: gnunet-scrypt.c:34
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:70
The identity of the host (wraps the signing key of the peer).

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

Referenced by handle_client_join().

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

◆ peer_id_cmp()

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

Compare two peer identities (for qsort()).

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

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

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

Referenced by initialize_session_peer_list().

Here is the caller graph for this function:

◆ initialize_session_peer_list()

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

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

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

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

2579{
2580 const struct GNUNET_PeerIdentity *msg_peers
2581 = (const struct GNUNET_PeerIdentity *) &join_msg[1];
2582 int local_peer_in_list;
2583
2584 session->num_peers = ntohl (join_msg->num_peers);
2585
2586 /* Peers in the join message, may or may not include the local peer,
2587 Add it if it is missing. */
2588 local_peer_in_list = GNUNET_NO;
2589 for (unsigned int i = 0; i < session->num_peers; i++)
2590 {
2591 if (0 == GNUNET_memcmp (&msg_peers[i],
2592 &my_peer))
2593 {
2594 local_peer_in_list = GNUNET_YES;
2595 break;
2596 }
2597 }
2598 if (GNUNET_NO == local_peer_in_list)
2599 session->num_peers++;
2600
2601 session->peers = GNUNET_new_array (session->num_peers,
2602 struct GNUNET_PeerIdentity);
2603 if (GNUNET_NO == local_peer_in_list)
2604 session->peers[session->num_peers - 1] = my_peer;
2605 GNUNET_memcpy (session->peers,
2606 msg_peers,
2607 ntohl (join_msg->num_peers)
2608 * sizeof(struct GNUNET_PeerIdentity));
2609 qsort (session->peers,
2610 session->num_peers,
2611 sizeof (struct GNUNET_PeerIdentity),
2612 &peer_id_cmp);
2613}
static int peer_id_cmp(const void *h1, const void *h2)
Compare two peer identities (for qsort()).
static struct GNUNET_PeerIdentity my_peer
Peer that runs this service.
uint32_t num_peers
Number of peers (at the end of this message) that want to participate in the consensus.
Definition: consensus.h:48

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

Referenced by handle_client_join().

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

◆ lookup_task()

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

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

2619{
2620 struct GNUNET_HashCode hash;
2621
2623 sizeof(struct TaskKey),
2624 &hash);
2626 "Looking up task hash %s\n",
2627 GNUNET_h2s (&hash));
2629 &hash);
2630}
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
struct GNUNET_CONTAINER_MultiHashMap * taskmap
Tuple of integers that together identify a task uniquely.

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

Referenced by set_listen_cb().

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

◆ set_listen_cb()

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

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

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

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

2653{
2654 struct ConsensusSession *session = cls;
2655 struct TaskKey tk;
2656 struct TaskEntry *task;
2658
2659 if (NULL == context_msg)
2660 {
2661 GNUNET_break_op (0);
2662 return;
2663 }
2664
2666 context_msg->type))
2667 {
2668 GNUNET_break_op (0);
2669 return;
2670 }
2671
2672 if (sizeof(struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs (
2673 context_msg->size))
2674 {
2675 GNUNET_break_op (0);
2676 return;
2677 }
2678
2679 cm = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg;
2680
2681 tk = ((struct TaskKey) {
2682 .kind = ntohs (cm->kind),
2683 .peer1 = ntohs (cm->peer1),
2684 .peer2 = ntohs (cm->peer2),
2685 .repetition = ntohs (cm->repetition),
2686 .leader = ntohs (cm->leader),
2687 });
2688
2689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2690 session->local_peer_idx, debug_str_task_key (&tk));
2691
2692 task = lookup_task (session, &tk);
2693
2694 if (NULL == task)
2695 {
2696 GNUNET_break_op (0);
2697 return;
2698 }
2699
2700 if (GNUNET_YES == task->is_finished)
2701 {
2702 GNUNET_break_op (0);
2703 return;
2704 }
2705
2706 if (task->key.peer2 != session->local_peer_idx)
2707 {
2708 /* We're being asked, so we must be the 2nd peer. */
2709 GNUNET_break_op (0);
2710 return;
2711 }
2712
2713 GNUNET_assert (! ((task->key.peer1 == session->local_peer_idx) &&
2714 (task->key.peer2 == session->local_peer_idx)));
2715
2716 struct GNUNET_SET_Option opts[] = {
2717 { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2719 };
2720
2723 opts,
2725 task);
2726
2727 /* If the task hasn't been started yet,
2728 we wait for that until we commit. */
2729
2730 if (GNUNET_YES == task->is_started)
2731 {
2732 commit_set (session, task);
2733 }
2734}
static struct TaskEntry * lookup_task(const struct ConsensusSession *session, const struct TaskKey *key)
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
struct GNUNET_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen().
Definition: set_api.c:1030
int16_t repetition
Repetition of the gradecast phase.
int16_t peer1
Number of the first peer in canonical order.
int16_t leader
Leader in the gradecast phase.
int16_t peer2
Number of the second peer in canonical order.
uint16_t kind
A value from 'enum PhaseKind'.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

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

Referenced by handle_client_join().

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

◆ put_task()

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

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

2740{
2741 struct GNUNET_HashCode round_hash;
2742 struct Step *s;
2743
2744 GNUNET_assert (NULL != t->step);
2745 t = GNUNET_memdup (t, sizeof(struct TaskEntry));
2746 s = t->step;
2747 if (s->tasks_len == s->tasks_cap)
2748 {
2749 unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2751 s->tasks_cap,
2752 target_size);
2753 }
2754
2755#ifdef GNUNET_EXTRA_LOGGING
2756 GNUNET_assert (NULL != s->debug_name);
2757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2758 debug_str_task_key (&t->key),
2759 s->debug_name);
2760#endif
2761
2762 s->tasks[s->tasks_len] = t;
2763 s->tasks_len++;
2764
2765 GNUNET_CRYPTO_hash (&t->key,
2766 sizeof(struct TaskKey),
2767 &round_hash);
2770 &round_hash,
2771 t,
2773}
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
unsigned int tasks_cap

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

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

◆ install_step_timeouts()

static void install_step_timeouts ( struct ConsensusSession session)
static

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

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

Referenced by handle_client_conclude().

Here is the caller graph for this function:

◆ arrange_peers()

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

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

2795{
2796 uint16_t a;
2797 uint16_t b;
2798
2799 GNUNET_assert (*p1 < n);
2800 GNUNET_assert (*p2 < n);
2801
2802 if (*p1 < *p2)
2803 {
2804 a = *p1;
2805 b = *p2;
2806 }
2807 else
2808 {
2809 a = *p2;
2810 b = *p1;
2811 }
2812
2813 /* For uniformly random *p1, *p2,
2814 this condition is true with 50% chance */
2815 if (((b - a) + n) % n <= n / 2)
2816 {
2817 *p1 = a;
2818 *p2 = b;
2819 }
2820 else
2821 {
2822 *p1 = b;
2823 *p2 = a;
2824 }
2825}

References GNUNET_assert.

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

Here is the caller graph for this function:

◆ step_depend_on()

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

Record dep as a dependency of step.

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

2834{
2835 /* We're not checking for cyclic dependencies,
2836 but this is a cheap sanity check. */
2837 GNUNET_assert (step != dep);
2838 GNUNET_assert (NULL != step);
2839 GNUNET_assert (NULL != dep);
2840 GNUNET_assert (dep->round <= step->round);
2841
2842#ifdef GNUNET_EXTRA_LOGGING
2843 /* Make sure we have complete debugging information.
2844 Also checks that we don't screw up too badly
2845 constructing the task graph. */
2846 GNUNET_assert (NULL != step->debug_name);
2847 GNUNET_assert (NULL != dep->debug_name);
2849 "Making step `%s' depend on `%s'\n",
2850 step->debug_name,
2851 dep->debug_name);
2852#endif
2853
2854 if (dep->subordinates_cap == dep->subordinates_len)
2855 {
2856 unsigned int target_size = 3 * (dep->subordinates_cap + 1) / 2;
2858 dep->subordinates_cap,
2859 target_size);
2860 }
2861
2863
2864 dep->subordinates[dep->subordinates_len] = step;
2865 dep->subordinates_len++;
2866
2867 step->pending_prereq++;
2868}
unsigned int subordinates_cap

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

Here is the caller graph for this function:

◆ create_step()

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

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

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

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

Referenced by construct_task_graph(), and construct_task_graph_gradecast().

Here is the caller graph for this function:

◆ construct_task_graph_gradecast()

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

Construct the task graph for a single gradecast.

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

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

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

Referenced by construct_task_graph().

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

◆ construct_task_graph()

static void construct_task_graph ( struct ConsensusSession session)
static

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

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

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

Referenced by handle_client_join().

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

◆ check_client_join()

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

Check join message.

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

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

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

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, and m.

◆ handle_client_join()

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

Called when a client wants to join a consensus session.

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

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

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

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

Here is the call graph for this function:

◆ check_client_insert()

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

Called when a client performs an insert operation.

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

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

3349{
3350 return GNUNET_OK;
3351}

References GNUNET_OK.

◆ handle_client_insert()

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

Called when a client performs an insert operation.

Parameters
clsclient handle
msgmessage sent by the client

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

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

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

Here is the call graph for this function:

◆ handle_client_conclude()

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

Called when a client performs the conclude operation.

Parameters
clsclient handle
messagemessage sent by the client

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

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

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

Here is the call graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

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

Parameters
clsclosure

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

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

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

Referenced by run().

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

◆ run()

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

Start processing consensus requests.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

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

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

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

Here is the call graph for this function:

◆ client_connect_cb()

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

Callback called when a client connects to the service.

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

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

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

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

◆ client_disconnect_cb()

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

Callback called when a client disconnected from the service.

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

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

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

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

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( "consensus"  ,
GNUNET_SERVICE_OPTION_NONE  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_fixed_size(client_conclude, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE, struct GNUNET_MessageHeader, NULL)  ,
GNUNET_MQ_hd_var_size(client_insert, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT, struct GNUNET_CONSENSUS_ElementMessage, NULL)  ,
GNUNET_MQ_hd_var_size(client_join, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN, struct GNUNET_CONSENSUS_JoinMessage, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ sessions_head

struct ConsensusSession* sessions_head
static

Linked list of sessions this peer participates in.

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

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

◆ sessions_tail

struct ConsensusSession* sessions_tail
static

Linked list of sessions this peer participates in.

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

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Configuration of the consensus service.

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

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

◆ my_peer

struct GNUNET_PeerIdentity my_peer
static

Peer that runs this service.

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

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

◆ statistics

struct GNUNET_STATISTICS_Handle* statistics

Statistics handle.

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

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