GNUnet 0.22.2
gnunet-service-consensus.c File Reference

multi-peer set reconciliation More...

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

Go to the source code of this file.

Data Structures

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

Typedefs

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

Enumerations

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

Functions

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

36{
41 VOTE_STAY = 0,
45 VOTE_ADD = 1,
49 VOTE_REMOVE = 2,
50};
@ 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 53 of file gnunet-service-consensus.c.

54{
58};
@ 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 61 of file gnunet-service-consensus.c.

62{
76};
@ 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 79 of file gnunet-service-consensus.c.

80{
81 SET_KIND_NONE = 0,
89};
@ 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 91 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 99 of file gnunet-service-consensus.c.

Function Documentation

◆ finish_task()

static void finish_task ( struct TaskEntry task)
static

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

2493{
2495 task->is_finished = GNUNET_YES;
2496 task->step->finished_tasks++;
2498 "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
2499 task->step->session->local_peer_idx,
2500 debug_str_task_key (&task->key),
2501 (unsigned int) task->step->finished_tasks,
2502 (unsigned int) task->step->tasks_len);
2503
2504 if (task->step->finished_tasks == task->step->tasks_len)
2505 finish_step (task->step);
2506}
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 2451 of file gnunet-service-consensus.c.

2452{
2453 struct Step *step;
2454
2455 step = session->steps_head;
2456
2457 while (NULL != step)
2458 {
2459 if ((GNUNET_NO == step->is_running) && (0 == step->pending_prereq) &&
2460 (GNUNET_NO == step->is_finished))
2461 {
2462 GNUNET_assert (0 == step->finished_tasks);
2463
2464#ifdef GNUNET_EXTRA_LOGGING
2466 "P%u: Running step `%s' of round %d with %d tasks and %d subordinates\n",
2468 step->debug_name,
2469 step->round, step->tasks_len, step->subordinates_len);
2470#endif
2471
2472 step->is_running = GNUNET_YES;
2473 for (size_t i = 0; i < step->tasks_len; i++)
2474 start_task (session, step->tasks[i]);
2475
2476 /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
2477 if ((step->finished_tasks == step->tasks_len) && (GNUNET_NO ==
2478 step->is_finished))
2479 finish_step (step);
2480
2481 /* Running the next ready steps will be triggered by task completion */
2482 return;
2483 }
2484 step = step->next;
2485 }
2486
2487 return;
2488}
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 549 of file gnunet-service-consensus.c.

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

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 577 of file gnunet-service-consensus.c.

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

References SET_KIND_CURRENT, SET_KIND_LEADER_PROPOSAL, and SET_KIND_NONE.

◆ rfnname()

static const char * rfnname ( uint16_t  kind)
static

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

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

References RFN_KIND_CONFIRM, RFN_KIND_ECHO, and RFN_KIND_NONE.

◆ diffname()

static const char * diffname ( uint16_t  kind)
static

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

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

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 708 of file gnunet-service-consensus.c.

710{
711 struct TaskEntry *task = (struct TaskEntry *) cls;
712 struct ConsensusSession *session = task->step->session;
713 struct GNUNET_MQ_Envelope *ev;
714
715 if (NULL != element)
716 {
718 const struct ConsensusElement *ce;
719
721 element->element_type);
722 ce = element->data;
723
724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "marker is %u\n",
725 (unsigned) ce->marker);
726
727 if (0 != ce->marker)
728 return GNUNET_YES;
729
731 "P%d: sending element %s to client\n",
732 session->local_peer_idx,
733 debug_str_element (element));
734
736 element->size - sizeof(struct ConsensusElement),
738 m->element_type = ce->payload_type;
739 GNUNET_memcpy (&m[1],
740 &ce[1],
741 element->size - sizeof(struct ConsensusElement));
742 GNUNET_MQ_send (session->client_mq,
743 ev);
744 }
745 else
746 {
748 "P%d: finished iterating elements for client\n",
749 session->local_peer_idx);
752 GNUNET_MQ_send (session->client_mq,
753 ev);
754 }
755 return GNUNET_YES;
756}
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:103
#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:305
#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:61
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:85
#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 760 of file gnunet-service-consensus.c.

762{
763 struct GNUNET_HashCode hash;
764
766 "P%u: looking up set {%s}\n",
767 session->local_peer_idx,
768 debug_str_set_key (key));
769
770 GNUNET_assert (SET_KIND_NONE != key->set_kind);
772 sizeof(struct SetKey),
773 &hash);
775 &hash);
776}
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 780 of file gnunet-service-consensus.c.

782{
783 struct GNUNET_HashCode hash;
784
786 "P%u: looking up diff {%s}\n",
787 session->local_peer_idx,
788 debug_str_diff_key (key));
789 GNUNET_assert (DIFF_KIND_NONE != key->diff_kind);
791 sizeof(struct DiffKey),
792 &hash);
794 &hash);
795}
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 799 of file gnunet-service-consensus.c.

801{
802 struct GNUNET_HashCode hash;
803
805 "P%u: looking up rfn {%s}\n",
806 session->local_peer_idx,
807 debug_str_rfn_key (key));
808 GNUNET_assert (RFN_KIND_NONE != key->rfn_kind);
810 sizeof(struct RfnKey),
811 &hash);
813 &hash);
814}
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 818 of file gnunet-service-consensus.c.

821{
822 struct DiffElementInfo *di;
823 struct GNUNET_HashCode hash;
824
825 GNUNET_assert ((1 == weight) || (-1 == weight));
826
828 "diff_insert with element size %u\n",
829 element->size);
830
832 "hashing element\n");
833
834 GNUNET_SET_element_hash (element, &hash);
835
837 "hashed element\n");
838
839 di = GNUNET_CONTAINER_multihashmap_get (diff->changes, &hash);
840
841 if (NULL == di)
842 {
843 di = GNUNET_new (struct DiffElementInfo);
844 di->element = GNUNET_SET_element_dup (element);
847 &hash,
848 di,
850 }
851
852 di->weight = weight;
853}
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 857 of file gnunet-service-consensus.c.

859{
860 GNUNET_assert (commit_peer < rfn->num_peers);
861
862 rfn->peer_commited[commit_peer] = GNUNET_YES;
863}
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 867 of file gnunet-service-consensus.c.

869{
870 GNUNET_assert (contested_peer < rfn->num_peers);
871
872 rfn->peer_contested[contested_peer] = GNUNET_YES;
873}
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 877 of file gnunet-service-consensus.c.

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

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 892 of file gnunet-service-consensus.c.

896{
897 struct RfnElementInfo *ri;
898 struct GNUNET_HashCode hash;
899
900 GNUNET_assert (voting_peer < rfn->num_peers);
901
902 /* Explicit voting only makes sense with VOTE_ADD or VOTE_REMOTE,
903 since VOTE_KEEP is implicit in not voting. */
904 GNUNET_assert ((VOTE_ADD == vote) || (VOTE_REMOVE == vote));
905
906 GNUNET_SET_element_hash (element, &hash);
908
909 if (NULL == ri)
910 {
911 ri = GNUNET_new (struct RfnElementInfo);
912 ri->element = GNUNET_SET_element_dup (element);
913 ri->votes = GNUNET_new_array (rfn->num_peers, int);
916 &hash, ri,
918 }
919
920 ri->votes[voting_peer] = GNUNET_YES;
921 ri->proposal = vote;
922}
#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 926 of file gnunet-service-consensus.c.

927{
928 uint16_t me = task->step->session->local_peer_idx;
929
930 if (task->key.peer1 == me)
931 return task->key.peer2;
932 return task->key.peer1;
933}
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 937 of file gnunet-service-consensus.c.

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

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 960 of file gnunet-service-consensus.c.

964{
965 struct TaskEntry *task = cls;
966 struct ConsensusSession *session = task->step->session;
967 struct SetEntry *output_set = NULL;
968 struct DiffEntry *output_diff = NULL;
969 struct ReferendumEntry *output_rfn = NULL;
970 unsigned int other_idx;
971 struct SetOpCls *setop;
972 const struct ConsensusElement *consensus_element = NULL;
973
974 if (NULL != element)
975 {
977 "P%u: got element of type %u, status %u\n",
978 session->local_peer_idx,
979 (unsigned) element->element_type,
980 (unsigned) status);
982 element->element_type);
983 consensus_element = element->data;
984 }
985
986 setop = &task->cls.setop;
987
988
990 "P%u: got set result for {%s}, status %u\n",
991 session->local_peer_idx,
992 debug_str_task_key (&task->key),
993 status);
994
995 if (GNUNET_NO == task->is_started)
996 {
997 GNUNET_break_op (0);
998 return;
999 }
1000
1001 if (GNUNET_YES == task->is_finished)
1002 {
1003 GNUNET_break_op (0);
1004 return;
1005 }
1006
1007 other_idx = task_other_peer (task);
1008
1009 if (SET_KIND_NONE != setop->output_set.set_kind)
1010 {
1011 output_set = lookup_set (session,
1012 &setop->output_set);
1013 GNUNET_assert (NULL != output_set);
1014 }
1015
1016 if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
1017 {
1018 output_diff = lookup_diff (session, &setop->output_diff);
1019 GNUNET_assert (NULL != output_diff);
1020 }
1021
1022 if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
1023 {
1024 output_rfn = lookup_rfn (session, &setop->output_rfn);
1025 GNUNET_assert (NULL != output_rfn);
1026 }
1027
1028 if (GNUNET_YES == session->peers_blacklisted[other_idx])
1029 {
1030 /* Peer might have been blacklisted
1031 by a gradecast running in parallel, ignore elements from now */
1033 return;
1035 return;
1036 }
1037
1038 if ((NULL != consensus_element) && (0 != consensus_element->marker))
1039 {
1041 "P%u: got some marker\n",
1042 session->local_peer_idx);
1043 if ((GNUNET_YES == setop->transceive_contested) &&
1044 (CONSENSUS_MARKER_CONTESTED == consensus_element->marker))
1045 {
1046 GNUNET_assert (NULL != output_rfn);
1047 rfn_contest (output_rfn, task_other_peer (task));
1048 return;
1049 }
1050
1051 if (CONSENSUS_MARKER_SIZE == consensus_element->marker)
1052 {
1054 "P%u: got size marker\n",
1055 session->local_peer_idx);
1056
1057 {
1058 struct ConsensusSizeElement *cse = (void *) consensus_element;
1059 uint64_t *copy;
1060
1061 if (cse->sender_index == other_idx)
1062 {
1063 if (NULL == session->first_sizes_received)
1065 ,
1066 uint64_t);
1067 session->first_sizes_received[other_idx] = GNUNET_ntohll (cse->size);
1068
1069 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
1083 return;
1084 }
1085
1086 switch (status)
1087 {
1089 GNUNET_assert (NULL != consensus_element);
1091 "Adding element in Task {%s}\n",
1092 debug_str_task_key (&task->key));
1093 if (NULL != output_set)
1094 {
1095 // FIXME: record pending adds, use callback
1096 GNUNET_SET_add_element (output_set->h,
1097 element,
1098 NULL,
1099 NULL);
1100#ifdef GNUNET_EXTRA_LOGGING
1102 "P%u: adding element %s into set {%s} of task {%s}\n",
1103 session->local_peer_idx,
1104 debug_str_element (element),
1105 debug_str_set_key (&setop->output_set),
1106 debug_str_task_key (&task->key));
1107#endif
1108 }
1109 if (NULL != output_diff)
1110 {
1111 diff_insert (output_diff, 1, element);
1112#ifdef GNUNET_EXTRA_LOGGING
1114 "P%u: adding element %s into diff {%s} of task {%s}\n",
1115 session->local_peer_idx,
1116 debug_str_element (element),
1117 debug_str_diff_key (&setop->output_diff),
1118 debug_str_task_key (&task->key));
1119#endif
1120 }
1121 if (NULL != output_rfn)
1122 {
1123 rfn_vote (output_rfn, task_other_peer (task), VOTE_ADD, element);
1124#ifdef GNUNET_EXTRA_LOGGING
1126 "P%u: adding element %s into rfn {%s} of task {%s}\n",
1127 session->local_peer_idx,
1128 debug_str_element (element),
1129 debug_str_rfn_key (&setop->output_rfn),
1130 debug_str_task_key (&task->key));
1131#endif
1132 }
1133 // XXX: add result to structures in task
1134 break;
1135
1137 GNUNET_assert (NULL != consensus_element);
1138 if (GNUNET_YES == setop->do_not_remove)
1139 break;
1140 if (CONSENSUS_MARKER_CONTESTED == consensus_element->marker)
1141 break;
1143 "Removing element in Task {%s}\n",
1144 debug_str_task_key (&task->key));
1145 if (NULL != output_set)
1146 {
1147 // FIXME: record pending adds, use callback
1148 GNUNET_SET_remove_element (output_set->h,
1149 element,
1150 NULL,
1151 NULL);
1152#ifdef GNUNET_EXTRA_LOGGING
1154 "P%u: removing element %s from set {%s} of task {%s}\n",
1155 session->local_peer_idx,
1156 debug_str_element (element),
1157 debug_str_set_key (&setop->output_set),
1158 debug_str_task_key (&task->key));
1159#endif
1160 }
1161 if (NULL != output_diff)
1162 {
1163 diff_insert (output_diff, -1, element);
1164#ifdef GNUNET_EXTRA_LOGGING
1166 "P%u: removing element %s from diff {%s} of task {%s}\n",
1167 session->local_peer_idx,
1168 debug_str_element (element),
1169 debug_str_diff_key (&setop->output_diff),
1170 debug_str_task_key (&task->key));
1171#endif
1172 }
1173 if (NULL != output_rfn)
1174 {
1175 rfn_vote (output_rfn, task_other_peer (task), VOTE_REMOVE, element);
1176#ifdef GNUNET_EXTRA_LOGGING
1178 "P%u: removing element %s from rfn {%s} of task {%s}\n",
1179 session->local_peer_idx,
1180 debug_str_element (element),
1181 debug_str_rfn_key (&setop->output_rfn),
1182 debug_str_task_key (&task->key));
1183#endif
1184 }
1185 break;
1186
1188 // XXX: check first if any changes to the underlying
1189 // set are still pending
1191 "P%u: Finishing setop in Task {%s} (%u/%u)\n",
1192 session->local_peer_idx,
1193 debug_str_task_key (&task->key),
1194 (unsigned int) task->step->finished_tasks,
1195 (unsigned int) task->step->tasks_len);
1196 if (NULL != output_rfn)
1197 {
1198 rfn_commit (output_rfn, task_other_peer (task));
1199 }
1200 if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1201 {
1202 session->first_size = current_size;
1203 }
1204 finish_task (task);
1205 break;
1206
1208 // XXX: cleanup
1209 GNUNET_break_op (0);
1210 finish_task (task);
1211 return;
1212
1213 default:
1214 /* not reached */
1215 GNUNET_assert (0);
1216 }
1217}
@ 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 1385 of file gnunet-service-consensus.c.

1387{
1388 struct SetEntry *set;
1389 struct SetOpCls *setop = &task->cls.setop;
1390
1391 GNUNET_assert (NULL != setop->op);
1392 set = lookup_set (session, &setop->input_set);
1393 GNUNET_assert (NULL != set);
1394
1395 if ((GNUNET_YES == setop->transceive_contested) && (GNUNET_YES ==
1396 set->is_contested))
1397 {
1398 struct GNUNET_SET_Element element;
1399 struct ConsensusElement ce = { 0 };
1400
1402 element.data = &ce;
1403 element.size = sizeof(struct ConsensusElement);
1404 element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1405 GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1406 }
1407
1408 if (PHASE_KIND_ALL_TO_ALL_2 == task->key.kind)
1409 {
1410 struct GNUNET_SET_Element element;
1411 struct ConsensusSizeElement cse = {
1412 .size = 0,
1413 .sender_index = 0
1414 };
1415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inserting size marker\n");
1417 cse.size = GNUNET_htonll (session->first_size);
1418 cse.sender_index = session->local_peer_idx;
1419 element.data = &cse;
1420 element.size = sizeof(struct ConsensusSizeElement);
1421 element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1422 GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1423 }
1424
1425#ifdef EVIL
1426 {
1427 struct Evilness evil;
1428
1429 get_evilness (session, &evil);
1430 if (EVILNESS_NONE != evil.type)
1431 {
1432 /* Useful for evaluation */
1434 "is evil",
1435 1,
1436 GNUNET_NO);
1437 }
1438 switch (evil.type)
1439 {
1440 case EVILNESS_CRAM_ALL:
1441 case EVILNESS_CRAM_LEAD:
1442 case EVILNESS_CRAM_ECHO:
1443 /* We're not cramming elements in the
1444 all-to-all round, since that would just
1445 add more elements to the result set, but
1446 wouldn't test robustness. */
1447 if (PHASE_KIND_ALL_TO_ALL == task->key.kind)
1448 {
1449 GNUNET_SET_commit (setop->op, set->h);
1450 break;
1451 }
1452 if ((EVILNESS_CRAM_LEAD == evil.type) &&
1453 ((PHASE_KIND_GRADECAST_LEADER != task->key.kind) ||
1454 (SET_KIND_CURRENT != set->key.set_kind) ))
1455 {
1456 GNUNET_SET_commit (setop->op, set->h);
1457 break;
1458 }
1459 if ((EVILNESS_CRAM_ECHO == evil.type) && (PHASE_KIND_GRADECAST_ECHO !=
1460 task->key.kind))
1461 {
1462 GNUNET_SET_commit (setop->op, set->h);
1463 break;
1464 }
1465 for (unsigned int i = 0; i < evil.num; i++)
1466 {
1467 struct GNUNET_SET_Element element;
1468 struct ConsensusStuffedElement se = {
1469 .ce.payload_type = 0,
1470 .ce.marker = 0,
1471 };
1472 element.data = &se;
1473 element.size = sizeof(struct ConsensusStuffedElement);
1474 element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT;
1475
1476 if (EVILNESS_SUB_REPLACEMENT == evil.subtype)
1477 {
1478 /* Always generate a new element. */
1480 &se.rand);
1481 }
1482 else if (EVILNESS_SUB_NO_REPLACEMENT == evil.subtype)
1483 {
1484 /* Always cram the same elements, derived from counter. */
1485 GNUNET_CRYPTO_hash (&i, sizeof(i), &se.rand);
1486 }
1487 else
1488 {
1489 GNUNET_assert (0);
1490 }
1491 GNUNET_SET_add_element (set->h, &element, NULL, NULL);
1492#ifdef GNUNET_EXTRA_LOGGING
1494 "P%u: evil peer: cramming element %s into set {%s} of task {%s}\n",
1495 session->local_peer_idx,
1496 debug_str_element (&element),
1497 debug_str_set_key (&setop->input_set),
1498 debug_str_task_key (&task->key));
1499#endif
1500 }
1502 "# stuffed elements",
1503 evil.num,
1504 GNUNET_NO);
1505 GNUNET_SET_commit (setop->op, set->h);
1506 break;
1507
1508 case EVILNESS_SLACK:
1510 "P%u: evil peer: slacking\n",
1511 (unsigned int) session->local_peer_idx);
1512
1513 /* Do nothing. */
1514 case EVILNESS_SLACK_A2A:
1515 if ((PHASE_KIND_ALL_TO_ALL_2 == task->key.kind) ||
1516 (PHASE_KIND_ALL_TO_ALL == task->key.kind))
1517 {
1518 struct GNUNET_SET_Handle *empty_set;
1520 GNUNET_SET_commit (setop->op, empty_set);
1521 GNUNET_SET_destroy (empty_set);
1522 }
1523 else
1524 {
1525 GNUNET_SET_commit (setop->op,
1526 set->h);
1527 }
1528 break;
1529
1530 case EVILNESS_NONE:
1531 GNUNET_SET_commit (setop->op,
1532 set->h);
1533 break;
1534 }
1535 }
1536#else
1537 if (GNUNET_NO == session->peers_blacklisted[task_other_peer (task)])
1538 {
1539 GNUNET_SET_commit (setop->op, set->h);
1540 }
1541 else
1542 {
1543 /* For our testcases, we don't want the blacklisted
1544 peers to wait. */
1546 setop->op = NULL;
1547 finish_task (task);
1548 }
1549#endif
1550}
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 1554 of file gnunet-service-consensus.c.

1556{
1557 struct GNUNET_HashCode hash;
1558
1559 GNUNET_CRYPTO_hash (&diff->key,
1560 sizeof(struct DiffKey),
1561 &hash);
1564 &hash,
1565 diff,
1567}
@ 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 1571 of file gnunet-service-consensus.c.

1573{
1574 struct GNUNET_HashCode hash;
1575
1576 GNUNET_assert (NULL != set->h);
1578 "Putting set %s\n",
1579 debug_str_set_key (&set->key));
1580 GNUNET_CRYPTO_hash (&set->key,
1581 sizeof(struct SetKey),
1582 &hash);
1585 &hash,
1586 set,
1588}
@ 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 1592 of file gnunet-service-consensus.c.

1594{
1595 struct GNUNET_HashCode hash;
1596
1597 GNUNET_CRYPTO_hash (&rfn->key, sizeof(struct RfnKey), &hash);
1600 &hash,
1601 rfn,
1603}

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 1607 of file gnunet-service-consensus.c.

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

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 1615 of file gnunet-service-consensus.c.

1619{
1621 struct DiffElementInfo *di;
1622
1624
1625 while (GNUNET_YES ==
1627 NULL,
1628 (const void **) &di))
1629 {
1630 if (di->weight > 0)
1631 {
1632 rfn_vote (rfn, voting_peer, VOTE_ADD, di->element);
1633 }
1634 if (di->weight < 0)
1635 {
1636 rfn_vote (rfn, voting_peer, VOTE_REMOVE, di->element);
1637 }
1638 }
1639
1641}
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 1645 of file gnunet-service-consensus.c.

1646{
1647 struct DiffEntry *d = GNUNET_new (struct DiffEntry);
1648
1650 GNUNET_NO);
1651
1652 return d;
1653}
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()

static struct ReferendumEntry * rfn_create ( uint16_t  size)
static

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

1700{
1701 struct ReferendumEntry *rfn;
1702
1703 rfn = GNUNET_new (struct ReferendumEntry);
1705 rfn->peer_commited = GNUNET_new_array (size, int);
1706 rfn->peer_contested = GNUNET_new_array (size, int);
1707 rfn->num_peers = size;
1708
1709 return rfn;
1710}
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 1731 of file gnunet-service-consensus.c.

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

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 1775 of file gnunet-service-consensus.c.

1777{
1778 struct SetCopyCls *scc = cls;
1779 struct TaskEntry *task = scc->task;
1780 struct SetKey dst_set_key = scc->dst_set_key;
1781 struct SetEntry *set;
1782 struct SetHandle *sh = GNUNET_new (struct SetHandle);
1783
1784 sh->h = copy;
1787 sh);
1788
1789 GNUNET_free (scc);
1790 set = GNUNET_new (struct SetEntry);
1791 set->h = copy;
1792 set->key = dst_set_key;
1793 put_set (task->step->session, set);
1794
1795 task->start (task);
1796}
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 1804 of file gnunet-service-consensus.c.

1807{
1808 struct SetEntry *src_set;
1809 struct SetCopyCls *scc = GNUNET_new (struct SetCopyCls);
1810
1812 "Copying set {%s} to {%s} for task {%s}\n",
1813 debug_str_set_key (src_set_key),
1814 debug_str_set_key (dst_set_key),
1815 debug_str_task_key (&task->key));
1816
1817 scc->task = task;
1818 scc->dst_set_key = *dst_set_key;
1819 src_set = lookup_set (task->step->session, src_set_key);
1820 GNUNET_assert (NULL != src_set);
1821 GNUNET_SET_copy_lazy (src_set->h,
1823 scc);
1824}
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 1838 of file gnunet-service-consensus.c.

1839{
1840 struct SetMutationProgressCls *pc = cls;
1841
1842 GNUNET_assert (pc->num_pending > 0);
1843
1844 pc->num_pending--;
1845
1846 if (0 == pc->num_pending)
1847 {
1848 struct TaskEntry *task = pc->task;
1849 GNUNET_free (pc);
1850 finish_task (task);
1851 }
1852}
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 1856 of file gnunet-service-consensus.c.

1857{
1858 if (GNUNET_YES == step->is_running)
1859 return;
1860 if (GNUNET_YES == step->is_finished)
1861 return;
1862 if (GNUNET_NO == step->early_finishable)
1863 return;
1864
1865 step->is_finished = GNUNET_YES;
1866
1867#ifdef GNUNET_EXTRA_LOGGING
1869 "Finishing step `%s' early.\n",
1870 step->debug_name);
1871#endif
1872
1873 for (unsigned int i = 0; i < step->subordinates_len; i++)
1874 {
1876 step->subordinates[i]->pending_prereq--;
1877#ifdef GNUNET_EXTRA_LOGGING
1879 "Decreased pending_prereq to %u for step `%s'.\n",
1880 (unsigned int) step->subordinates[i]->pending_prereq,
1881 step->subordinates[i]->debug_name);
1882#endif
1884 }
1885
1886 // XXX: maybe schedule as task to avoid recursion?
1887 run_ready_steps (step->session);
1888}
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 1892 of file gnunet-service-consensus.c.

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

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 1931 of file gnunet-service-consensus.c.

1932{
1933 struct ConsensusSession *session = task->step->session;
1934 struct SetKey sk_in;
1935 struct SetKey sk_out;
1936 struct RfnKey rk_in;
1937 struct SetEntry *set_out;
1938 struct ReferendumEntry *rfn_in;
1940 struct RfnElementInfo *ri;
1941 struct SetMutationProgressCls *progress_cls;
1942 uint16_t worst_majority = UINT16_MAX;
1943
1944 sk_in = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition };
1945 rk_in = (struct RfnKey) { RFN_KIND_GRADECAST_RESULT, task->key.repetition };
1946 sk_out = (struct SetKey) { SET_KIND_CURRENT, task->key.repetition + 1 };
1947
1948 set_out = lookup_set (session, &sk_out);
1949 if (NULL == set_out)
1950 {
1952 &sk_in,
1953 &sk_out);
1954 return;
1955 }
1956
1957 rfn_in = lookup_rfn (session, &rk_in);
1958 GNUNET_assert (NULL != rfn_in);
1959
1960 progress_cls = GNUNET_new (struct SetMutationProgressCls);
1961 progress_cls->task = task;
1962
1964
1965 while (GNUNET_YES ==
1967 NULL,
1968 (const void **) &ri))
1969 {
1970 uint16_t majority_num;
1971 enum ReferendumVote majority_vote;
1972
1973 rfn_majority (rfn_in, ri, &majority_num, &majority_vote);
1974
1975 if (worst_majority > majority_num)
1976 worst_majority = majority_num;
1977
1978 switch (majority_vote)
1979 {
1980 case VOTE_ADD:
1981 progress_cls->num_pending++;
1983 GNUNET_SET_add_element (set_out->h,
1984 ri->element,
1986 progress_cls));
1988 "P%u: apply round: adding element %s with %u-majority.\n",
1989 session->local_peer_idx,
1990 debug_str_element (ri->element), majority_num);
1991 break;
1992
1993 case VOTE_REMOVE:
1994 progress_cls->num_pending++;
1996 GNUNET_SET_remove_element (set_out->h,
1997 ri->element,
1999 progress_cls));
2001 "P%u: apply round: deleting element %s with %u-majority.\n",
2002 session->local_peer_idx,
2003 debug_str_element (ri->element), majority_num);
2004 break;
2005
2006 case VOTE_STAY:
2008 "P%u: apply round: keeping element %s with %u-majority.\n",
2009 session->local_peer_idx,
2010 debug_str_element (ri->element), majority_num);
2011 // do nothing
2012 break;
2013
2014 default:
2015 GNUNET_assert (0);
2016 break;
2017 }
2018 }
2019
2020 if (0 == progress_cls->num_pending)
2021 {
2022 // call closure right now, no pending ops
2023 GNUNET_free (progress_cls);
2024 finish_task (task);
2025 }
2026
2027 {
2028 uint16_t thresh = (session->num_peers / 3) * 2;
2029
2030 if (worst_majority >= thresh)
2031 {
2032 switch (session->early_stopping)
2033 {
2037 "P%u: Stopping early (after one more superround)\n",
2038 session->local_peer_idx);
2039 break;
2040
2043 "P%u: finishing steps due to early finish\n",
2044 session->local_peer_idx);
2046 {
2047 struct Step *step;
2048 for (step = session->steps_head; NULL != step; step = step->next)
2049 try_finish_step_early (step);
2050 }
2051 break;
2052
2054 /* We shouldn't be here anymore after early stopping */
2055 GNUNET_break (0);
2056 break;
2057
2058 default:
2059 GNUNET_assert (0);
2060 break;
2061 }
2062 }
2064 {
2065 // Our assumption about the number of bad peers
2066 // has been broken.
2067 GNUNET_break_op (0);
2068 }
2069 else
2070 {
2072 "P%u: NOT finishing early (majority not good enough)\n",
2074 }
2075 }
2077}
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 2081 of file gnunet-service-consensus.c.

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

2177{
2178 struct SetEntry *input;
2179 struct SetOpCls *setop = &task->cls.setop;
2180 struct ConsensusSession *session = task->step->session;
2181
2182 input = lookup_set (session, &setop->input_set);
2183 GNUNET_assert (NULL != input);
2184 GNUNET_assert (NULL != input->h);
2185
2186 /* We create the outputs for the operation here
2187 (rather than in the set operation callback)
2188 because we want something valid in there, even
2189 if the other peer doesn't talk to us */
2190
2191 if (SET_KIND_NONE != setop->output_set.set_kind)
2192 {
2193 /* If we don't have an existing output set,
2194 we clone the input set. */
2195 if (NULL == lookup_set (session, &setop->output_set))
2196 {
2198 &setop->input_set,
2199 &setop->output_set);
2200 return;
2201 }
2202 }
2203
2204 if (RFN_KIND_NONE != setop->output_rfn.rfn_kind)
2205 {
2206 if (NULL == lookup_rfn (session, &setop->output_rfn))
2207 {
2208 struct ReferendumEntry *rfn;
2209
2211 "P%u: output rfn <%s> missing, creating.\n",
2212 session->local_peer_idx,
2213 debug_str_rfn_key (&setop->output_rfn));
2214
2215 rfn = rfn_create (session->num_peers);
2216 rfn->key = setop->output_rfn;
2217 put_rfn (session, rfn);
2218 }
2219 }
2220
2221 if (DIFF_KIND_NONE != setop->output_diff.diff_kind)
2222 {
2223 if (NULL == lookup_diff (session, &setop->output_diff))
2224 {
2225 struct DiffEntry *diff;
2226
2227 diff = diff_create ();
2228 diff->key = setop->output_diff;
2229 put_diff (session, diff);
2230 }
2231 }
2232
2233 if ((task->key.peer1 == session->local_peer_idx) && (task->key.peer2 ==
2234 session->local_peer_idx))
2235 {
2236 /* XXX: mark the corresponding rfn as committed if necessary */
2237 finish_task (task);
2238 return;
2239 }
2240
2241 if (task->key.peer1 == session->local_peer_idx)
2242 {
2244
2246 "P%u: Looking up set {%s} to run remote union\n",
2247 session->local_peer_idx,
2248 debug_str_set_key (&setop->input_set));
2249 rcm.header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
2250 rcm.header.size = htons (sizeof(rcm));
2251 rcm.kind = htons (task->key.kind);
2252 rcm.peer1 = htons (task->key.peer1);
2253 rcm.peer2 = htons (task->key.peer2);
2254 rcm.leader = htons (task->key.leader);
2255 rcm.repetition = htons (task->key.repetition);
2256 rcm.is_contested = htons (0);
2257
2258 GNUNET_assert (NULL == setop->op);
2260 "P%u: initiating set op with P%u, our set is %s\n",
2261 session->local_peer_idx,
2262 task->key.peer2,
2263 debug_str_set_key (&setop->input_set));
2264
2265 {
2266 struct GNUNET_SET_Option opts[] = {
2267 { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2269 };
2270
2271 // XXX: maybe this should be done while
2272 // setting up tasks alreays?
2273 setop->op = GNUNET_SET_prepare (&session->peers[task->key.peer2],
2274 &session->global_id,
2275 &rcm.header,
2277 opts,
2279 task);
2280
2281 commit_set (session, task);
2282 }
2283 }
2284 else if (task->key.peer2 == session->local_peer_idx)
2285 {
2286 /* Wait for the other peer to contact us */
2287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting set op with P%u\n",
2288 session->local_peer_idx, task->key.peer1);
2289
2290 if (NULL != setop->op)
2291 {
2292 commit_set (session, task);
2293 }
2294 }
2295 else
2296 {
2297 /* We made an error while constructing the task graph. */
2298 GNUNET_assert (0);
2299 }
2300}
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 2304 of file gnunet-service-consensus.c.

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

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 2416 of file gnunet-service-consensus.c.

2417{
2418 struct SetEntry *final_set;
2419 struct ConsensusSession *session = task->step->session;
2420
2421 final_set = lookup_set (session,
2422 &task->cls.finish.input_set);
2423 GNUNET_assert (NULL != final_set);
2424 GNUNET_SET_iterate (final_set->h,
2426 task);
2427}
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 2431 of file gnunet-service-consensus.c.

2433{
2435 "P%u: starting task {%s}\n",
2436 session->local_peer_idx,
2437 debug_str_task_key (&task->key));
2440 GNUNET_assert (NULL != task->start);
2441 task->start (task);
2442 task->is_started = GNUNET_YES;
2443}

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 2517 of file gnunet-service-consensus.c.

2519{
2520 for (int i = 0; i < session->num_peers; i++)
2521 if (0 == GNUNET_memcmp (peer, &session->peers[i]))
2522 return i;
2523 return -1;
2524}
#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 2537 of file gnunet-service-consensus.c.

2539{
2540 const char *salt = "gnunet-service-consensus/session_id";
2541
2543 GNUNET_CRYPTO_kdf (&session->global_id,
2544 sizeof(struct GNUNET_HashCode),
2545 salt,
2546 strlen (salt),
2547 session->peers,
2548 session->num_peers * sizeof(struct
2550 local_session_id,
2551 sizeof(struct GNUNET_HashCode),
2552 NULL));
2553}
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calculations.
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:62
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 2564 of file gnunet-service-consensus.c.

2566{
2567 return memcmp (h1, h2, sizeof(struct GNUNET_PeerIdentity));
2568}

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 2579 of file gnunet-service-consensus.c.

2582{
2583 const struct GNUNET_PeerIdentity *msg_peers
2584 = (const struct GNUNET_PeerIdentity *) &join_msg[1];
2585 int local_peer_in_list;
2586
2587 session->num_peers = ntohl (join_msg->num_peers);
2588
2589 /* Peers in the join message, may or may not include the local peer,
2590 Add it if it is missing. */
2591 local_peer_in_list = GNUNET_NO;
2592 for (unsigned int i = 0; i < session->num_peers; i++)
2593 {
2594 if (0 == GNUNET_memcmp (&msg_peers[i],
2595 &my_peer))
2596 {
2597 local_peer_in_list = GNUNET_YES;
2598 break;
2599 }
2600 }
2601 if (GNUNET_NO == local_peer_in_list)
2602 session->num_peers++;
2603
2604 session->peers = GNUNET_new_array (session->num_peers,
2605 struct GNUNET_PeerIdentity);
2606 if (GNUNET_NO == local_peer_in_list)
2607 session->peers[session->num_peers - 1] = my_peer;
2608 GNUNET_memcpy (session->peers,
2609 msg_peers,
2610 ntohl (join_msg->num_peers)
2611 * sizeof(struct GNUNET_PeerIdentity));
2612 qsort (session->peers,
2613 session->num_peers,
2614 sizeof (struct GNUNET_PeerIdentity),
2615 &peer_id_cmp);
2616}
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 2620 of file gnunet-service-consensus.c.

2622{
2623 struct GNUNET_HashCode hash;
2624
2626 sizeof(struct TaskKey),
2627 &hash);
2629 "Looking up task hash %s\n",
2630 GNUNET_h2s (&hash));
2632 &hash);
2633}
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 2652 of file gnunet-service-consensus.c.

2656{
2657 struct ConsensusSession *session = cls;
2658 struct TaskKey tk;
2659 struct TaskEntry *task;
2661
2662 if (NULL == context_msg)
2663 {
2664 GNUNET_break_op (0);
2665 return;
2666 }
2667
2669 context_msg->type))
2670 {
2671 GNUNET_break_op (0);
2672 return;
2673 }
2674
2675 if (sizeof(struct GNUNET_CONSENSUS_RoundContextMessage) != ntohs (
2676 context_msg->size))
2677 {
2678 GNUNET_break_op (0);
2679 return;
2680 }
2681
2682 cm = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg;
2683
2684 tk = ((struct TaskKey) {
2685 .kind = ntohs (cm->kind),
2686 .peer1 = ntohs (cm->peer1),
2687 .peer2 = ntohs (cm->peer2),
2688 .repetition = ntohs (cm->repetition),
2689 .leader = ntohs (cm->leader),
2690 });
2691
2692 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: got req for task %s\n",
2693 session->local_peer_idx, debug_str_task_key (&tk));
2694
2695 task = lookup_task (session, &tk);
2696
2697 if (NULL == task)
2698 {
2699 GNUNET_break_op (0);
2700 return;
2701 }
2702
2703 if (GNUNET_YES == task->is_finished)
2704 {
2705 GNUNET_break_op (0);
2706 return;
2707 }
2708
2709 if (task->key.peer2 != session->local_peer_idx)
2710 {
2711 /* We're being asked, so we must be the 2nd peer. */
2712 GNUNET_break_op (0);
2713 return;
2714 }
2715
2716 GNUNET_assert (! ((task->key.peer1 == session->local_peer_idx) &&
2717 (task->key.peer2 == session->local_peer_idx)));
2718
2719 {
2720 struct GNUNET_SET_Option opts[] = {
2721 { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
2723 };
2724
2727 opts,
2729 task);
2730 }
2731 /* If the task hasn't been started yet,
2732 we wait for that until we commit. */
2733
2734 if (GNUNET_YES == task->is_started)
2735 {
2736 commit_set (session, task);
2737 }
2738}
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
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.
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'.

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 2742 of file gnunet-service-consensus.c.

2744{
2745 struct GNUNET_HashCode round_hash;
2746 struct Step *s;
2747
2748 GNUNET_assert (NULL != t->step);
2749 t = GNUNET_memdup (t, sizeof(struct TaskEntry));
2750 s = t->step;
2751 if (s->tasks_len == s->tasks_cap)
2752 {
2753 unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
2755 s->tasks_cap,
2756 target_size);
2757 }
2758
2759#ifdef GNUNET_EXTRA_LOGGING
2760 GNUNET_assert (NULL != s->debug_name);
2761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting task <%s> into step `%s'\n",
2762 debug_str_task_key (&t->key),
2763 s->debug_name);
2764#endif
2765
2766 s->tasks[s->tasks_len] = t;
2767 s->tasks_len++;
2768
2769 GNUNET_CRYPTO_hash (&t->key,
2770 sizeof(struct TaskKey),
2771 &round_hash);
2774 &round_hash,
2775 t,
2777}
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 2781 of file gnunet-service-consensus.c.

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

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 2796 of file gnunet-service-consensus.c.

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

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 2836 of file gnunet-service-consensus.c.

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

2879{
2880 struct Step *step;
2881
2882 step = GNUNET_new (struct Step);
2883 step->session = session;
2884 step->round = round;
2888 step);
2889 return step;
2890}
#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 2897 of file gnunet-service-consensus.c.

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

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

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

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 3259 of file gnunet-service-consensus.c.

3261{
3262 struct ConsensusSession *session = cls;
3263 struct ConsensusSession *other_session;
3264
3266 m);
3267 compute_global_id (session,
3268 &m->session_id);
3269
3270 /* Check if some local client already owns the session.
3271 It is only legal to have a session with an existing global id
3272 if all other sessions with this global id are finished.*/
3273 for (other_session = sessions_head;
3274 NULL != other_session;
3275 other_session = other_session->next)
3276 {
3277 if ( (other_session != session) &&
3278 (0 == GNUNET_CRYPTO_hash_cmp (&session->global_id,
3279 &other_session->global_id)) )
3280 break;
3281 }
3282
3283 session->conclude_deadline
3284 = GNUNET_TIME_absolute_ntoh (m->deadline);
3285 session->conclude_start
3286 = GNUNET_TIME_absolute_ntoh (m->start);
3287 session->local_peer_idx = get_peer_idx (&my_peer,
3288 session);
3289 GNUNET_assert (-1 != session->local_peer_idx);
3290
3292 "Joining consensus session %s containing %u peers as %u with timeout %s\n",
3293 GNUNET_h2s (&m->session_id),
3294 session->num_peers,
3295 session->local_peer_idx,
3298 session->conclude_deadline)
3299 ,
3300 GNUNET_YES));
3301
3302 session->set_listener
3305 &session->global_id,
3307 session);
3308
3310 GNUNET_NO);
3312 GNUNET_NO);
3314 GNUNET_NO);
3316 GNUNET_NO);
3317
3318 {
3319 struct SetEntry *client_set = GNUNET_new (struct SetEntry);
3320 struct SetHandle *sh = GNUNET_new (struct SetHandle);
3321
3322 client_set->h = GNUNET_SET_create (cfg,
3324 sh->h = client_set->h;
3326 session->set_handles_tail,
3327 sh);
3328 client_set->key = ((struct SetKey) { SET_KIND_CURRENT, 0, 0 });
3329 put_set (session,
3330 client_set);
3331 }
3332
3333 session->peers_blacklisted = GNUNET_new_array (session->num_peers,
3334 int);
3335
3336 /* Just construct the task graph,
3337 but don't run anything until the client calls conclude. */
3338 construct_task_graph (session);
3340}
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:218
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
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:579
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:741
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:423
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 3351 of file gnunet-service-consensus.c.

3353{
3354 return GNUNET_OK;
3355}

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 3365 of file gnunet-service-consensus.c.

3367{
3368 struct ConsensusSession *session = cls;
3369 ssize_t element_size;
3370 struct GNUNET_SET_Handle *initial_set;
3371 struct ConsensusElement *ce;
3372
3373 if (GNUNET_YES == session->conclude_started)
3374 {
3375 GNUNET_break (0);
3377 return;
3378 }
3379 element_size = ntohs (msg->header.size) - sizeof(*msg);
3380 ce = GNUNET_malloc (sizeof(struct ConsensusElement) + element_size);
3381 GNUNET_memcpy (&ce[1],
3382 &msg[1],
3383 element_size);
3384 ce->payload_type = msg->element_type;
3385
3386 {
3387 struct SetKey key = { SET_KIND_CURRENT, 0, 0 };
3388 struct SetEntry *entry;
3389
3390 entry = lookup_set (session,
3391 &key);
3392 GNUNET_assert (NULL != entry);
3393 initial_set = entry->h;
3394 }
3395
3396 session->num_client_insert_pending++;
3397
3398 {
3399 struct GNUNET_SET_Element element = {
3401 .size = sizeof(struct ConsensusElement) + element_size,
3402 .data = ce,
3403 };
3404
3405 GNUNET_SET_add_element (initial_set,
3406 &element,
3407 NULL,
3408 NULL);
3409#ifdef GNUNET_EXTRA_LOGGING
3411 "P%u: element %s added\n",
3412 session->local_peer_idx,
3413 debug_str_element (&element));
3414#endif
3415 }
3416 GNUNET_free (ce);
3418}
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:2418
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 3428 of file gnunet-service-consensus.c.

3430{
3431 struct ConsensusSession *session = cls;
3432
3433 if (GNUNET_YES == session->conclude_started)
3434 {
3435 /* conclude started twice */
3436 GNUNET_break (0);
3438 return;
3439 }
3441 "conclude requested\n");
3442 session->conclude_started = GNUNET_YES;
3443 install_step_timeouts (session);
3444 run_ready_steps (session);
3446}
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 3455 of file gnunet-service-consensus.c.

3456{
3458 "shutting down\n");
3460 GNUNET_NO);
3461 statistics = NULL;
3462}
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 3473 of file gnunet-service-consensus.c.

3476{
3477 cfg = c;
3478 if (GNUNET_OK !=
3480 &my_peer))
3481 {
3483 "Could not retrieve host identity\n");
3485 return;
3486 }
3487 statistics = GNUNET_STATISTICS_create ("consensus",
3488 cfg);
3490 NULL);
3491}
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:1339
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 3503 of file gnunet-service-consensus.c.

3506{
3507 struct ConsensusSession *session = GNUNET_new (struct ConsensusSession);
3508
3509 session->client = c;
3510 session->client_mq = mq;
3513 session);
3514 return session;
3515}
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 3526 of file gnunet-service-consensus.c.

3529{
3530 struct ConsensusSession *session = internal_cls;
3531
3532 if (NULL != session->set_listener)
3533 {
3535 session->set_listener = NULL;
3536 }
3539 session);
3540 while (session->set_handles_head)
3541 {
3542 struct SetHandle *sh = session->set_handles_head;
3543
3544 session->set_handles_head = sh->next;
3546 GNUNET_free (sh);
3547 }
3548 GNUNET_free (session);
3549}
#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 ( GNUNET_OS_project_data_gnunet()  ,
"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 517 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 522 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 527 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 532 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 537 of file gnunet-service-consensus.c.

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