From e2b2ab728217a64027232c7b8fbbb68ba13edd4a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 26 Feb 2017 23:05:29 +0100 Subject: [PATCH] wrap consensus elements in block type --- src/consensus/Makefile.am | 18 ++++ src/consensus/consensus_protocol.h | 21 ++++ src/consensus/gnunet-service-consensus.c | 73 ++++++++------ src/consensus/plugin_block_consensus.c | 117 +++++++++++++++++++++++ src/consensus/test_consensus.conf | 6 +- src/include/gnunet_block_lib.h | 14 ++- 6 files changed, 216 insertions(+), 33 deletions(-) create mode 100644 src/consensus/plugin_block_consensus.c diff --git a/src/consensus/Makefile.am b/src/consensus/Makefile.am index b6385ac71..2b1987fbc 100644 --- a/src/consensus/Makefile.am +++ b/src/consensus/Makefile.am @@ -5,6 +5,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ +plugindir = $(libdir)/gnunet + pkgcfg_DATA = \ consensus.conf @@ -67,6 +69,22 @@ libgnunetconsensus_la_LIBADD = \ libgnunetconsensus_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) + +plugin_LTLIBRARIES = \ + libgnunet_plugin_block_consensus.la + +libgnunet_plugin_block_consensus_la_SOURCES = \ + plugin_block_consensus.c +libgnunet_plugin_block_consensus_la_LIBADD = \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/block/libgnunetblockgroup.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_plugin_block_consensus_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + + if HAVE_TESTING check_PROGRAMS = \ test_consensus_api diff --git a/src/consensus/consensus_protocol.h b/src/consensus/consensus_protocol.h index fb3bde628..101b8aee7 100644 --- a/src/consensus/consensus_protocol.h +++ b/src/consensus/consensus_protocol.h @@ -87,6 +87,27 @@ struct GNUNET_CONSENSUS_RoundContextMessage uint16_t is_contested; }; + +/** + * Consensus element, either marker or payload. + */ +struct ConsensusElement +{ + /** + * Payload element_type, only valid + * if this is not a marker element. + */ + uint16_t payload_type; + + /** + * Is this a marker element? + */ + uint8_t is_contested_marker; + + /* rest: element data */ +}; + + GNUNET_NETWORK_STRUCT_END #endif diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c index 4036d2b11..9d5d35c94 100644 --- a/src/consensus/gnunet-service-consensus.c +++ b/src/consensus/gnunet-service-consensus.c @@ -26,6 +26,7 @@ #include "platform.h" #include "gnunet_util_lib.h" +#include "gnunet_block_lib.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_set_service.h" @@ -34,8 +35,6 @@ #include "consensus_protocol.h" #include "consensus.h" -#define ELEMENT_TYPE_CONTESTED_MARKER (GNUNET_CONSENSUS_ELEMENT_TYPE_USER_MAX + 1) - enum ReferendumVote { @@ -65,11 +64,6 @@ enum EarlyStoppingPhase GNUNET_NETWORK_STRUCT_BEGIN - -struct ContestedPayload -{ -}; - /** * Tuple of integers that together * identify a task uniquely. @@ -669,16 +663,22 @@ send_to_client_iter (void *cls, if (NULL != element) { struct GNUNET_CONSENSUS_ElementMessage *m; + const struct ConsensusElement *ce; + + GNUNET_assert (GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT == element->element_type); + ce = element->data; + + GNUNET_assert (GNUNET_NO == ce->is_contested_marker); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: sending element %s to client\n", session->local_peer_idx, debug_str_element (element)); - ev = GNUNET_MQ_msg_extra (m, element->size, + ev = GNUNET_MQ_msg_extra (m, element->size - sizeof (struct ConsensusElement), GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT); - m->element_type = htons (element->element_type); - GNUNET_memcpy (&m[1], element->data, element->size); + m->element_type = ce->payload_type; + GNUNET_memcpy (&m[1], &ce[1], element->size - sizeof (struct ConsensusElement)); GNUNET_MQ_send (session->client_mq, ev); } else @@ -878,6 +878,13 @@ set_result_cb (void *cls, struct ReferendumEntry *output_rfn = NULL; unsigned int other_idx; struct SetOpCls *setop; + const struct ConsensusElement *consensus_element = NULL; + + if (NULL != element) + { + GNUNET_assert (GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT == element->element_type); + consensus_element = element->data; + } setop = &task->cls.setop; @@ -932,7 +939,8 @@ set_result_cb (void *cls, if ( (GNUNET_SET_STATUS_ADD_LOCAL == status) || (GNUNET_SET_STATUS_ADD_REMOTE == status) ) { - if ( (GNUNET_YES == setop->transceive_contested) && (ELEMENT_TYPE_CONTESTED_MARKER == element->element_type) ) + if ( (GNUNET_YES == setop->transceive_contested) && + (GNUNET_YES == consensus_element->is_contested_marker) ) { GNUNET_assert (NULL != output_rfn); rfn_contest (output_rfn, task_other_peer (task)); @@ -943,6 +951,7 @@ set_result_cb (void *cls, switch (status) { case GNUNET_SET_STATUS_ADD_LOCAL: + GNUNET_assert (NULL != consensus_element); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding element in Task {%s}\n", debug_str_task_key (&task->key)); @@ -989,9 +998,10 @@ set_result_cb (void *cls, // XXX: add result to structures in task break; case GNUNET_SET_STATUS_ADD_REMOTE: + GNUNET_assert (NULL != consensus_element); if (GNUNET_YES == setop->do_not_remove) break; - if (ELEMENT_TYPE_CONTESTED_MARKER == element->element_type) + if (GNUNET_YES == consensus_element->is_contested_marker) break; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing element in Task {%s}\n", @@ -1318,10 +1328,11 @@ commit_set (struct ConsensusSession *session, if ( (GNUNET_YES == setop->transceive_contested) && (GNUNET_YES == set->is_contested) ) { struct GNUNET_SET_Element element; - struct ContestedPayload payload; - element.data = &payload; - element.size = sizeof (struct ContestedPayload); - element.element_type = ELEMENT_TYPE_CONTESTED_MARKER; + struct ConsensusElement ce = { 0 }; + ce.is_contested_marker = GNUNET_YES; + element.data = &ce; + element.size = sizeof (struct ConsensusElement); + element.element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT; GNUNET_SET_add_element (set->h, &element, NULL, NULL); } if (GNUNET_NO == session->peers_blacklisted[task_other_peer (task)]) @@ -3041,9 +3052,9 @@ handle_client_insert (void *cls, const struct GNUNET_CONSENSUS_ElementMessage *msg) { struct ConsensusSession *session = cls; - struct GNUNET_SET_Element *element; ssize_t element_size; struct GNUNET_SET_Handle *initial_set; + struct ConsensusElement *ce; if (GNUNET_YES == session->conclude_started) { @@ -3051,12 +3062,18 @@ handle_client_insert (void *cls, GNUNET_SERVICE_client_drop (session->client); return; } + element_size = ntohs (msg->header.size) - sizeof (struct GNUNET_CONSENSUS_ElementMessage); - element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size); - element->element_type = msg->element_type; - element->size = element_size; - GNUNET_memcpy (&element[1], &msg[1], element_size); - element->data = &element[1]; + ce = GNUNET_malloc (sizeof (struct ConsensusElement) + element_size); + GNUNET_memcpy (&ce[1], &msg[1], element_size); + ce->payload_type = msg->element_type; + + struct GNUNET_SET_Element element = { + .element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, + .size = sizeof (struct ConsensusElement) + element_size, + .data = ce, + }; + { struct SetKey key = { SET_KIND_CURRENT, 0, 0 }; struct SetEntry *entry; @@ -3066,26 +3083,22 @@ handle_client_insert (void *cls, GNUNET_assert (NULL != entry); initial_set = entry->h; } + session->num_client_insert_pending++; GNUNET_SET_add_element (initial_set, - element, + &element, &client_insert_done, session); #ifdef GNUNET_EXTRA_LOGGING { - struct GNUNET_HashCode hash; - - GNUNET_SET_element_hash (element, - &hash); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: element %s added\n", session->local_peer_idx, - GNUNET_h2s (&hash)); + debug_str_element (&element)); } #endif - GNUNET_free (element); + GNUNET_free (ce); GNUNET_SERVICE_client_continue (session->client); } diff --git a/src/consensus/plugin_block_consensus.c b/src/consensus/plugin_block_consensus.c new file mode 100644 index 000000000..399e85feb --- /dev/null +++ b/src/consensus/plugin_block_consensus.c @@ -0,0 +1,117 @@ +/* + This file is part of GNUnet + Copyright (C) 2017 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @file consensus/plugin_block_consensus.c + * @brief consensus block, either nested block or marker + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_block_plugin.h" +#include "gnunet_block_group_lib.h" + + +/** + * Function called to validate a reply or a request. For + * request evaluation, simply pass "NULL" for the reply_block. + * + * @param cls closure + * @param type block type + * @param group block group to use + * @param eo control flags + * @param query original query (hash) + * @param xquery extrended query data (can be NULL, depending on type) + * @param xquery_size number of bytes in xquery + * @param reply_block response to validate + * @param reply_block_size number of bytes in reply block + * @return characterization of result + */ +static enum GNUNET_BLOCK_EvaluationResult +block_plugin_consensus_evaluate (void *cls, + enum GNUNET_BLOCK_Type type, + struct GNUNET_BLOCK_Group *group, + enum GNUNET_BLOCK_EvaluationOptions eo, + const struct GNUNET_HashCode *query, + const void *xquery, + size_t xquery_size, + const void *reply_block, + size_t reply_block_size) +{ + return GNUNET_BLOCK_EVALUATION_OK_MORE; +} + + +/** + * Function called to obtain the key for a block. + * + * @param cls closure + * @param type block type + * @param block block to get the key for + * @param block_size number of bytes in block + * @param key set to the key (query) for the given block + * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported + * (or if extracting a key from a block of this type does not work) + */ +static int +block_plugin_consensus_get_key (void *cls, + enum GNUNET_BLOCK_Type type, + const void *block, + size_t block_size, + struct GNUNET_HashCode *key) +{ + return GNUNET_SYSERR; +} + + +/** + * Entry point for the plugin. + */ +void * +libgnunet_plugin_block_consensus_init (void *cls) +{ + static enum GNUNET_BLOCK_Type types[] = + { + GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, + GNUNET_BLOCK_TYPE_ANY /* end of list */ + }; + struct GNUNET_BLOCK_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); + api->evaluate = &block_plugin_consensus_evaluate; + api->get_key = &block_plugin_consensus_get_key; + api->types = types; + return api; +} + + +/** + * Exit point from the plugin. + */ +void * +libgnunet_plugin_block_consensus_done (void *cls) +{ + struct GNUNET_TRANSPORT_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + +/* end of plugin_block_consensus.c */ diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf index 8f144fa5e..c3077b65d 100644 --- a/src/consensus/test_consensus.conf +++ b/src/consensus/test_consensus.conf @@ -2,9 +2,11 @@ GNUNET_TEST_HOME = /tmp/test-consensus/ [consensus] -OPTIONS = -L INFO +#OPTIONS = -L INFO BINARY = gnunet-service-evil-consensus +PREFIX = valgrind + #EVIL_SPEC = 0;cram-all;noreplace;5 #EVIL_SPEC = 0;cram;5/1;cram;5 #EVIL_SPEC = 0;cram;5/1;cram;5/2;cram;5 @@ -37,7 +39,7 @@ PLUGINS = unix OPTIONS = -LERROR [set] -OPTIONS = -L INFO +#OPTIONS = -L INFO #PREFIX = valgrind --leak-check=full #PREFIX = valgrind diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h index a40f33699..3e36f11f0 100644 --- a/src/include/gnunet_block_lib.h +++ b/src/include/gnunet_block_lib.h @@ -119,7 +119,19 @@ enum GNUNET_BLOCK_Type /** * Block to store a cadet regex accepting state */ - GNUNET_BLOCK_TYPE_REGEX_ACCEPT = 23 + GNUNET_BLOCK_TYPE_REGEX_ACCEPT = 23, + + /** + * Block for testing set/consensus. If first byte of the block + * is non-zero, the block is considered invalid. + */ + GNUNET_BLOCK_TYPE_SET_TEST = 24, + + /** + * Block type for consensus elements. + * Contains either special marker elements or a nested block. + */ + GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT = 25, }; -- 2.25.1