<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.2.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-jesus-gfds-01" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.30.1 -->
  <front>
    <title abbrev="GFDS">A Generic Framework for Building Dynamic Decentralized Systems (GFDS)</title>
    <seriesInfo name="Internet-Draft" value="draft-jesus-gfds-01"/>
    <author initials="D." surname="Jesus" fullname="Diogo Jesus">
      <organization>TaRDIS</organization>
      <address>
        <postal>
          <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
        </postal>
        <email>da.jesus@fct.unl.pt</email>
      </address>
    </author>
    <author initials="J." surname="Leitão" fullname="João Leitão">
      <organization>TaRDIS</organization>
      <address>
        <postal>
          <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
        </postal>
        <email>jc.leitao@fct.unl.pt</email>
      </address>
    </author>
    <date year="2025" month="August" day="28"/>
    <keyword>decentralized systems</keyword>
    <keyword>dynamic environments</keyword>
    <keyword>swarms</keyword>
    <abstract>
      <?line 89?>

<t>Building and managing highly dynamic and heterogeneous decentralized systems can prove to be quite challenging due to the great complexity and scale of such environments.
This document specifies a Generic Framework for Building Dynamic Decentralized Systems (GFDS), which composes a reference architecture and execution model for developing and managing these systems, while providing high-level abstractions to users.</t>
    </abstract>
  </front>
  <middle>
    <?line 95?>

<section anchor="overview">
      <name>Overview</name>
      <t>Building decentralized systems is a complex and challenging task due to the inherent unpredictability and scale of such systems. These systems often consist of multiple nodes that may be located in different geographical regions and need to collaborate seamlessly to provide services or process data. The difficulty arises in managing issues like network latency, node failures, variable load distribution, or possibly node displacement in particular environments. Nevertheless, these systems need to remain highly available and responsive even when individual components experience failures, which requires robust fault tolerance and self-healing mechanisms.</t>
      <t>While achieving data consistency, synchronization, and ensuring that all nodes have a coherent view of the system in a centralized system would be relatively easy, due to the existence of a centralized unit in charge of maintaining a "source of truth" and handling concurrency, in a decentralized system where nodes behave freely, and may at any moment have their own perspective of the system, such goal is not trivial.  While centralized systems benefit from easier state management, they suffer from scalability limitations, single points of failure, and a lack of redundancy. Decentralized architectures, by their nature, mitigate some these issues but introduce added complexity due to the lack of centralized control.</t>
      <t>This document focuses on decentralized systems and explores strategies to simplify their development and management.</t>
      <t>Maintaining scalability and flexibility as the system evolves proves to be quite challenging. With growing demand, the system must be able to scale dynamically, by adding or removing nodes, without disrupting ongoing operations, which requires sophisticated orchestration, auto-reconfiguration and adaptability. Moreover, dealing with the complexities of data consistency, synchronization, and ensuring that all nodes have a coherent view of the system state introduces a level of complexity that can be difficult to manage.</t>
      <t>Developing frameworks and libraries for decentralized systems presents unique challenges. These frameworks must abstract the complexities of distributed architectures while maintaining flexibility and control for developers. While developers often need low-level access to aspects like network management, fault tolerance, and security, they also benefit from high-level abstractions that simplify common tasks such as inter-node communication and failure handling. Striking a balance between abstraction and control is crucial to ensure usability without compromising performance or system correctness.</t>
      <t>Existing network libraries, such as <xref target="Lib2p"/>, provide modular and flexible tools for building peer-to-peer networks but often have a steep learning curve and interoperability challenges. Moreover, while libp2p offers an extensive set of functionalities out of the box, these are not always easily adaptable to specific use cases, limiting flexibility for developers. Similarly, simulators like <xref target="PeerSim"/> allow rapid prototyping and testing of distributed systems but fail to accurately model real-world execution environments, leading to a <em>reality gap</em> between simulation and real-world deployment.</t>
      <t>To address these challenges, we propose the <strong>Generic Framework for Building Dynamic Decentralized Systems (GFDS)</strong>. GFDS provides a comprehensive set of tools, abstractions, and best practices to help developers design, deploy, and manage decentralized applications that are dynamic, resilient, scalable, and fault-tolerant.</t>
      <t>The framework is composed of an execution model, which details and controls the life-cycle of protocols (the base unit in the framework), and an architecture detailing a set of managers to handle the different components and their interactions while providing common APIs for enabling inter-protocol communication between the different elements in the stack.</t>
      <section anchor="document-structure">
        <name>Document Structure</name>
        <t>This document describes a Generic Framework for Building Dynamic Decentralized Systems and its structured as follows:</t>
        <ul spacing="normal">
          <li>
            <t><xref target="protocol"/> describes <em>protocols</em>-the base unit of interaction within the framework,</t>
          </li>
          <li>
            <t><xref target="architecture"/> describes the framework architecture, its different components and their interaction,</t>
          </li>
          <li>
            <t><xref target="executionmodel"/> details the execution model of the framework and the life cycle of protocols,</t>
          </li>
          <li>
            <t><xref target="api"/> describes the programming interfaces offered by the framework to handle interaction with the application level, inter-protocol interactions and inter-node communication,</t>
          </li>
          <li>
            <t><xref target="examples"/> provides real-world scenarios and examples.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>The following abbreviations are used throughout the document:</t>
      <ul spacing="normal">
        <li>
          <t>API: Application Programming Interface</t>
        </li>
        <li>
          <t>GFDS: Generic Framework for Building Dynamic Decentralized Systems</t>
        </li>
        <li>
          <t>CAS: Central Authentication Service</t>
        </li>
      </ul>
    </section>
    <section anchor="protocol">
      <name>Protocol Anatomy</name>
      <t>The main unit of interaction in the framework is the <em>protocol</em>.
Protocols are assigned an unique identifier and embed the logic implemented by the developer and use the abstractions provided by the framework to interact with other protocols being executed locally, as well as handling communication with other nodes. A process may execute an arbitrary number of protocols concurrently at any given time, and protocols can communicate with each other to cooperate and delegate tasks. Moreover, as it is very common in distributed protocols to capture certain behaviours, protocols can execute actions periodically through the use of timers (e.g., execute a garbage collection function).</t>
      <t>Each protocol is composed of the following concepts that dictate the anatomy and life cycle of a protocol:</t>
      <ul spacing="normal">
        <li>
          <t><strong>state</strong> describes the inner state of the protocol, containing the necessary data and data structures to ensure its correct behaviour. The state should be initialized in a specialized <em>init</em> function and can be mutated through interaction with other local protocols, periodic timers that alter the state of the protocol and, finally, communication with other nodes running the same protocol on different machines;</t>
        </li>
        <li>
          <t><strong>timer handlers</strong> are meant to execute periodic or scheduled tasks. When the timer expires, a handler is executed with user-defined logic. Additionally, protocols can cancel timers if they are no longer relevant (e.g., a timer set up by the lack of an acknowledgement can be cancelled if the acknowledged arrived in the meantime);</t>
        </li>
        <li>
          <t><strong>inter-protocol handlers</strong> are in charge of managing communication between protocols running on the same machine. These handlers are divided into two categories: one-to-one <em>requests/replies</em> and one-to-many <em>notifications</em>;</t>
        </li>
        <li>
          <t><strong>communication handlers</strong> which manage incoming and outgoing communications between different nodes. At the protocol level such information arrives in the form of messages;</t>
        </li>
        <li>
          <t><strong>discovery, resource and configuration handlers</strong> which deal with peer discovery, resource handling and configuration.</t>
        </li>
      </ul>
      <t>With most of the complexity abstracted by the framework, the developer can focus on the logic of the protocol, without having to worry about the low-level aspects associated with building large-scale systems (e.g., dealing with faults in the network layer).</t>
      <section anchor="protocol-init">
        <name>Protocol Initialization</name>
        <t>As described previously, each protocol should implement a special <em>init</em> function. This function is meant to be executed
exactly one time during the life-cycle of the protocol, and has four main purposes:</t>
        <ol spacing="normal" type="1"><li>
            <t>Initialize the protocol's state, namely, its control variables, local data structures, etc.,</t>
          </li>
          <li>
            <t>Setup self-configuration, resource and adaptive handlers,</t>
          </li>
          <li>
            <t>Choose the preferred transport preferences,</t>
          </li>
          <li>
            <t>Register the different handlers (i.e., timer, inter-protocol, discovery and inter-node communication handlers).</t>
          </li>
        </ol>
        <t>A typical protocol initialization would be structured as follows:</t>
        <artwork><![CDATA[
init(properties):
  // 1 - Setup initial state
 ...

 // 2 - Setup discovery, configuration and resource monitoring
 registerSelfConfiguration(properties, uponSelfConfig)

 registerAdaptiveConfiguration(properties, uponAdaptive)

 registerResourceMonitor(resources, uponResource)

 // 3 - Transport preferences
 preferences = {reliable, secure}
 registerCommunicationPreferences(preferences)

 // 4 - Handlers
 registerRequestHandler(BroadcastRequest, uponBroadcastRequest)
 ...

 registerReplyHandler(DeliverReply, uponDeliverReply)
 ...

 registerTimerHandler(GarbageCollectTimer, uponGarbageCollectTimer)
 ...

 registerDiscoveryHandler(uponParticipant)
 ...


 subscribeNotificationHandler(NeighborUpNotification, uponNeighborUpNotification)
 ...

 registerCommunicationHandler(BroadcastMessage, uponBroadcastMessage)
 ...
]]></artwork>
      </section>
      <section anchor="protocol-handlers">
        <name>Handlers</name>
        <t>Handlers operate as callback functions. During the initialization of a protocol, the developer is in charge of registering the handlers associated with the protocol and their respective callbacks. This guarantees that when an event is dispatched to the protocol by the framework (e.g., due to a request arriving from another protocol, a message in the network, etc.), the respective callback function associated with the event is rightfully triggered.</t>
        <t>In this section, we will focus on how handlers work at the protocol level. Further details regarding the architecture and internal life-cycle management of handlers by the runtime are provided in <xref target="architecture"/>.</t>
        <t>Each type of handler has specific information according to their different nature, but, their registration mostly consists of specifying two fields: 1) a type encapsulating the incoming information arriving at the handler, and 2) the <em>callback function</em> to be triggered when an event arrives. This can be depicted as follows, by analyzing a transmission example:</t>
        <artwork><![CDATA[
//Types definition
def BroadcastMessage {
 byte [] data,
 int hopCount,
 Peer origin

 //Omitting serializer
 ...
}

init(properties):
 ...
 registerCommunicationHandler(BroadcastMessage, uponBroadcastMessage)
 ...

uponBroadcastMessage(BroadcastMessage: msg, Peer: sender):
 //Handle data
]]></artwork>
        <t>Hence, at the protocol level, the developer solely worries about defining the correct types associated with each handler and the corresponding callback functions to manage event arrivals.</t>
        <section anchor="protocol-handlers-timer">
          <name>Timer-Handlers</name>
          <t>Timer-handlers allow the developer to set up tasks that should be executed periodically or after a certain amount of time has passed. This is especially helpful to model certain aspects of distributed systems, such as cases where some kind of verification has to be done periodically to ensure consistency, or to time-bound actions in certain aspects of a protocol.</t>
          <t>Thus, we propose the following API to interact with timers at the protocol level:</t>
          <artwork><![CDATA[
registerTimerHandler(TimerType: timerType, TimerHandler: function)

setupTimer(Timer: timer, long: timeout) -> long

setupPeriodicTimer(Timer: timer, long: first, long: period) -> long

cancelTimer(long: timerID)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerTimerHandler</em>, as the name implies, should only be invoked during protocol initialization and ensures that all the timers are correctly registered. The function receives the timer type (which encapsulates the information to be passed on as an argument) and the callback function to be triggered.</t>
            </li>
            <li>
              <t><em>setupTimer</em> sets up a timer that will be triggered after a timeout. After the timeout has passed the timer will cease to exist. The function returns a unique timerID that can be used to cancel the timer if needed.</t>
            </li>
            <li>
              <t><em>setupPeriodicSetupTimer</em> sets up a timer that will be triggered periodically (as indicated by the <em>period</em> parameter). It is possible to specify a timeout until the first trigger with the <em>first</em> parameter. Akin to <em>setupTimer</em>, this function also returns a unique timerID.</t>
            </li>
            <li>
              <t><em>cancelTimer</em> allows canceling a timer by passing its unique timerID. This can be extremely helpful in cases where a periodic action is no longer needed, or, for example, if a timeout is no longer required due to the arrival of data. Protocols should be able to set up and cancel timers during their life-cycle.</t>
            </li>
          </ul>
          <t>Below, we depict a simple example of synchronous communication among nodes:</t>
          <artwork><![CDATA[
//Types definition
def GarbageCollectionTimer(){
 long interval
}

def AckTimer(){
 string msgID
}

//Omitting state for clarity

init(properties):
 ...
 registerTimerHandler(GarbageCollectionTimer, uponGarbageCollectTimer)
 timer = GarbageCollectionTimer(1m)
 setupPeriodicTimer(timer, 10s, 100s);

 registerTimerHandler(AckTimer, uponAckTimer)
 ...

uponBroadcastMessage(BroadcastMessage: message, Peer: sender, Transport: transport):
 this.blocks.add(msg)
 setupTimer(AckTimer(msg.id), 10s)

//Executed every 100 seconds
uponGarbageCollectTimer(GarbageCollectTimer: timer):
 this.blocks.remove(msg -> Time.now - msg.timestamp > timer.interval)

//Executed 10s after setupTimer invocation
uponAckTimer(GarbageCollectTimer: timer):
 if (!this.acks.contains(timer.msgID))
 // run fault checks

]]></artwork>
        </section>
        <section anchor="protocol-handlers-ipc">
          <name>Inter-Protocol Handlers</name>
          <t>Inter-protocol handlers govern the interaction among protocols being executed in the same machine. Usually, each machine in a distributed system runs a stack of protocols (i.e., protocols for membership, propagation, storage, etc.) and they interact with each other to achieve composability and describe more complex behaviours. A simple example of this can be seen in a propagation protocol (e.g., multicast) that makes use of the neighbors provided by a lower-level protocol in charge of membership on top of an overlay network.</t>
          <t>As mentioned previously, these types of handlers are divided into two categories: <em>request/reply</em> handlers, meant for one-to-one interaction among protocols, and <em>notifications</em> with one-to-many semantics. The first is especially useful in scenarios where a protocol intends to request the execution of a certain task to another protocol (e.g., the storage protocol asking for the transmission of an object to the protocol in charge of propagation) and expects to receive a reply after the said task is completed. On the other hand, the second enables protocols to subscribe to
notifications, so that they are notified when a node triggers a new notification (e.g., a message arrived in a pub/sub protocol and every protocol that is interested in it should be notified).</t>
          <t>Regarding requests and their respective replies, we propose the following API:</t>
          <artwork><![CDATA[
registerRequestHandler(RequestType: requestType, RequestHandler: function)

sendRequest(Request: request, Protocol: destProtocol)
sendRequest(Request: request)

registerReplyHandler(ReplyType: replyType, ReplyHandler: function)

sendReply(Reply: reply, Protocol: destProtocol)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerRequestHandler</em> should only be invoked in the <em>init</em> function and ensures that all the requests are correctly registered. The function receives the request type (which encapsulates the information to be passed on as an argument to the handler) and the callback function to be triggered.</t>
            </li>
            <li>
              <t><em>sendRequest</em> allows a protocol to send a request to another protocol. The function receives an instance of the request and the corresponding destination protocol. A second variant doesn't receive the destination protocol and is solely used to request tasks to the framework (i.e., <xref target="protocol-disc-communication"/>)</t>
            </li>
            <li>
              <t><em>registerReplyHandler</em> is akin to <em>registerRequestHandler</em>, but for replies.</t>
            </li>
            <li>
              <t><em>sendReply</em> behaves similarly to <em>sendRequest</em>, thus allowing protocols to issue replies. Is to be noted that replies are usually issued as a response to requests issued by other protocols.</t>
            </li>
          </ul>
          <artwork><![CDATA[
subscribeNotificationHandler(NotificationType: notificationType, NotificationHandler: function)

triggerNotification(Notification: notification)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>subscribeNotificationHandler</em> should only be invoked in the <em>init</em> function and guarantees the correct subscription of the protocol to notifications. The function receives the notification type, and a callback to handle incoming notifications.</t>
            </li>
            <li>
              <t><em>triggerNotification</em> triggers a notification to be propagated to all protocols subscribed to it. The function receives an instance of the notification as an argument.</t>
            </li>
          </ul>
          <t>This semantic allows developers to fine-grain the specification of their protocols by using a declarative language that allows them to focus their efforts on implementing the algorithm logic.</t>
          <t>We provide a brief example of how this works, with a simple broadcast application:</t>
          <artwork><![CDATA[
//Types definition
def BroadcastRequest(){
 byte [] data
}

def DeliverReply(){
 byte [] data
}

def NeighborUpNotification(){
 Peer: peer
}

//Protocol state
state = {
 neighbors: Set<Peer>,
 myself: Peer
}

init(properties):
 ...
 registerRequestHandler(PingRequest,uponPingRequest)
 subscribeNotification(NeighborUpNotification,uponNeighborUpNotification)
 ...

uponPingRequest(PingRequest: request, Protocol: sourceProto):
 msg = BroadcastMessage(request.msg, this.myself)
 this.neighbors.forEach(peer -> sendMessage(msg, peer))
 sendReply(DeliverReply(request.msg), sourceProto)

uponNeighborUpNotification(NeighborUpNotification: notification):
 this.neighbors.add(notification.peer)
]]></artwork>
          <t>Note that, in the previous example, there was no registration of DeliverReply. This is because only the protocols wishing to receive that information, namely the protocol that sent the request, are obliged to register such handlers.</t>
        </section>
        <section anchor="protocol-disc-communication">
          <name>Discovery Handlers</name>
          <t>Discovery handlers are in charge of facilitating the discovery of nodes within the system, which is particularly relevant in decentralized systems where nodes need to connect dynamically without a central authority.</t>
          <t>At the protocol level, the framework should provide ways of informing the protocol when new participants are discovered:</t>
          <artwork><![CDATA[
registerDiscoveryHandler(DiscoveryHandler: function)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t>The <em>registerDiscoveryHandler</em> function should only be invoked within the init function and is responsible for registering the handler that receives discovery events from the event manager. This function processes a notification containing information about a node (e.g., its identifier, status, etc.). Unlike other events that may have multiple handlers (e.g., requests, notifications), there should be only one active discovery handler per protocol.</t>
            </li>
          </ul>
          <t>While the framework probes the system during initialization or at regular intervals to detect new nodes, protocols may require real-time access to the latest set of participants or may need to announce their presence to other nodes. To facilitate this, each protocol declares its intent to either discover other nodes or be discoverable through a service name.</t>
          <t>A service name serves as a label for the protocol and represents its offered functionalities. For example, a broadcast protocol might register itself with the service name "floodPropagation", signaling its role in message dissemination.</t>
          <t>To enable this functionality, the sendRequest construct is used to instruct the discovery manager to propagate this information.</t>
          <t>Thus, the framework provides developers with two mechanisms to report and retrieve such information:</t>
          <artwork><![CDATA[
sendRequest(Request: RequestProbe(String: serviceName))

sendRequest(Request: RequestAnnouncement(String: serviceName))
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>sendRequest(RequestProbe(serviceName))</em> sends a specialized request, RequestProbe, which queries the system for other nodes that offer the specified service.</t>
            </li>
            <li>
              <t><em>sendRequest(RequestAnnouncement(serviceName))</em> sends a specialized request, RequestAnnouncement, which announces the node as a provider of the specified service.</t>
            </li>
          </ul>
          <t>It is important to note that while discovery is relevant in some protocols, it remains an optional module that a protocol may choose to use or ignore by registering accordingly during initialization. For example, in a system with a large protocol stack, one protocol (e.g., a membership protocol) may handle discovery, while others receive this information through inter-protocol interactions. If a protocol does not require discovery notifications, it simply does not register the corresponding handlers.</t>
          <t>We can see the discovery mechanisms in action in the following example:</t>
          <artwork><![CDATA[
//Types definition
def AnnounceTimer {
  long interval
}

def BroadcastRequest{
 byte [] data
}

def DeliverReply(){
 byte [] data
}

//Protocol state
state = {
 neighbors: Set<Peer>,
 myself: Peer
}

init(properties):
 ...
 registerDiscoveryHandler(uponDiscovery)

 registerRequestHandler(PingRequest,uponPingRequest)
 subscribeNotification(NeighborUpNotification,uponNeighborUpNotification)

 registerTimerHandler(AnnounceTimer, uponAnnounceTimer)
 timer = AnnounceTimer(1m)
 setupPeriodicTimer(timer, 10s, 100s);
 ...

uponAnnounceTimer(AnnounceTimer: timer):
  request = RequestAnnouncement("pingPong")
  sendRequest(request)

uponPingRequest(PingRequest: request, Protocol: sourceProto):
 msg = BroadcastMessage(request.msg, this.myself)
 this.neighbors.forEach(peer -> sendMessage(msg, peer))
 sendReply(DeliverReply(request.msg), sourceProto)

uponDiscovery(DiscoveryNotification: notification):
 log("Discovery Method: {}", notification.serviceName)
 this.neighbors.add(notification.peer)

]]></artwork>
        </section>
        <section anchor="protocol-config-communication">
          <name>Configuration Handlers</name>
          <t>Self-configuration and adaptability refer to the ability of a component to automatically configure itself and change based on its environment, without requiring manual intervention. The first guides to the fact that, when a node initiates, it should be able to self-configure to join the system as an active node, while the second handles the adaptation of a node during runtime to match the current state of the system.</t>
          <t>To achieve this, we suggest the following design: Each protocol should define a set of state parameters that it considers to be <em>AutoConfigurable</em> and <em>Adaptive</em>. This way, during registration, the protocol will pass this information to the framework and the framework will handle the proper initialization and update of these parameters during execution. Parameters tagged with <em>AutoConfigurable</em> are meant to be configured during initialization by obtaining the configuration of other nodes already present in the system, while <em>Adaptive</em> parameters are meant to be properly managed and adapted (i.e., reconfigured) by the framework during runtime.</t>
          <t>With this said, at the protocol level, we propose the following functionalities and abstractions:</t>
          <artwork><![CDATA[
registerSelfConfiguration(Properties: properties, ConfigurationHandler: function)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerSelfConfiguration</em> indicates how the protocol will setup its initial configuration. The first argument, properties, encapsulates the parameters the node wishes to tag as <em>AutoConfigurable</em> so that they are properly set up by the framework. Finally, the last argument receives a handler to be executed as a callback when an event regarding configuration arrives at the protocol.</t>
            </li>
          </ul>
          <artwork><![CDATA[
registerAdaptiveConfiguration(Properties: properties, AdaptiveHandler: function)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerAdaptiveConfiguration</em> indicates how the framework will handle autonomic updates of the protocol parameters. The first argument, properties, encapsulates the parameters the node wishes to tag as <em>Adaptive</em>. The last argument receives a handler to be executed as a callback when an event regarding the reconfiguration of parameters arrives at the protocol.</t>
            </li>
          </ul>
          <t>The following example contains a simple application embedding these abstractions:</t>
          <artwork><![CDATA[
//Types definition
PayloadMessage {
 string payload
}

PublishRequest {
 string topic,
 string msg
}

state = {
 @AutoConfigurable
 long garbabeCollectTimer,

 @Adaptive
 long fanout,

 @AutoConfigurable
 @Adaptive
 long ttl,

 Set<PayloadMessage> data
}

init():
 //Omitting state initialization and handlers for simplicity

 ...
 registerSelfConfiguration(properties, uponSelfConfig)

 registerAdaptiveConfiguration( properties, uponAdaptive)
 ...

uponPublishRequest(PublishRequest: request, Protocol: sourceProto):
 payload = PayloadMessage(request.msg)
 data.add(request.msg)
 sendMessage(payload, p)

uponSelfConfig(SelfConfigParameters selfConfig):
 for p in state as AutoConfigurable:
  p = selfConfig.parameters.get(p)

uponAdaptive(AdaptiveParameters adaptive):
 for p in state as Adaptive:
  p = adaptive.parameters.get(p)

]]></artwork>
        </section>
        <section anchor="protocol-handlers-resources">
          <name>Resource Handlers</name>
          <t>In decentralized environments, resource constraints such as CPU, memory, bandwidth, or storage can significantly affect the performance and reliability of running protocols.</t>
          <t>To address this, the framework provides mechanisms to continuously monitor resource usage, generate notifications when predefined thresholds are exceeded, and allow protocols to adapt their behavior accordingly. We propose a design where protocols explicitly register the resources they are interested in—selected from a list maintained by the framework—and receive notifications when relevant changes occur.</t>
          <t>During initialization, protocols declare which resources they wish to monitor. At runtime, the resource manager continuously tracks the consumption of these resources and produces events in three situations: when explicitly requested by a protocol (e.g., resource samples), at periodic intervals, or when thresholds are reached (e.g., high CPU usage, low available bandwidth).</t>
          <t>These events enable protocols to record resource usage for analytics, or, in more advanced cases, to take corrective actions such as reducing message frequency, postponing non-critical tasks, or dropping optional computations.</t>
          <t>At the protocol level, the framework exposes the following abstraction:</t>
          <artwork><![CDATA[
registerResourceMonitor(Resources []: resourceTypes, ResourceHandler: function)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerResourceMonitor</em> specifies which resources the protocol intends to observe, and the handler function that will process the corresponding events.</t>
            </li>
          </ul>
          <t>The following example illustrates this mechanism:</t>
          <artwork><![CDATA[
init(properties):
 ...
 // Setup resource monitors
 resources = {CPU_LOAD, MEMORY_USAGE}
 registerResourceMonitor(resources, uponResourceSample)

 subscribeNotification(ResourceLimitWarningNotification, uponResourceLimitWarning)
 ...

uponResourceSample(ResourceEvent sample):
  file.append("Resource Sample: {} {}", sample.resourceType, sample.usage)

uponResourceLimitWarning(ResourceLimitWarning warning):
  log.warn("Resource {} Limit Warning, take action", warning.resourceType)
  //Protocol adapts accordingly

...
]]></artwork>
        </section>
        <section anchor="protocol-handlers-communication">
          <name>Communication Handlers</name>
          <t>Finally, while inter-protocol handlers are in charge of dealing with the interaction of protocols being executed in the same node, communication handlers manage data arriving from different nodes, and thus, inter-node communication.</t>
          <t>With a great deal of complexity being abstracted by the framework, at the protocol level, we are concerned with providing a generic API to the developer which allows a node to send and receive information from other nodes without having to deal with the intricacies of managing such connections.
Namely, we extend our framework to regard different technologies, ranging from the typical network-based protocols like TCP <xref target="RFC9293"/>, UDP <xref target="RFC768"/>, QUIC <xref target="RFC9000"/>, etc., to short-range technologies such as Bluetooth Low Energy (BLE) <xref target="RFC7668"/> (more details are provided in the following sections).</t>
          <t>To achieve this and provide a more user-friendly interface for newcomers, we propose a keyword-based approach instead of requiring developers to explicitly specify the transport protocols they wish to use for communication. In this approach, keywords represent the desired characteristics and guarantees of communication between nodes. These keywords include properties such as reliable or unreliable, secure or unsecure, lightweight, connection-oriented or connectionless, among others.</t>
          <t>Internally, as explained in detail in later sections, the framework maps the specified set of keywords to an appropriate combination of transport protocols that satisfy those requirements.</t>
          <t>Communication in GFDS is fundamentally message-based. Protocols interact by sending and receiving discrete messages, ensuring reliable and scalable communication while maintaining flexibility and compatibility with a wide range of transport protocols.</t>
          <t>Thus, at the protocol level, we suggest the following abstractions:</t>
          <artwork><![CDATA[
registerCommunicationPreferences(Keywords[]: preferences, boolean?: parallelize)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerCommunicationPreferences</em> allows a developer to specify its   preferences regarding communication ( i.e., <xref target="arch-communicationmanager-arch"/>).
 Preferences are passed to functions as keyword arguments. If a conflict arises that prevents a valid match (e.g., specifying both secure and unsecure), the framework notifies the developer with an appropriate error message. If no preference set is provided, the framework defaults to its predefined settings. Additionally, the function accepts a boolean parameter that determines whether the framework should parallelize the opening of different transport paths during startup. If the developer passes <em>true</em>, the framework initializes all transport paths in parallel when starting the protocol. If <em>false</em>, the framework sequentially opens the interfaces, prioritizing those at the top of the list and only initializing additional ones if the primary interfaces fail. The first approach reduces overhead during connection loss, whereas the second optimizes resource consumption. If no argument is provided, the framework defaults to its predefined configuration.</t>
            </li>
          </ul>
          <artwork><![CDATA[
registerCommunicationHandler(MessageType: msg, MessageHandler: function)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerCommunicationHandler</em> should only be invoked in the <em>init</em> function and ensures that all the transmissions/communication arriving at the node from other nodes are properly handled. The function receives the message type (which encapsulates the information to be passed on as an argument to the handler) and the callback function to be triggered when a message arrives. It is worth noting that since these message types are meant to be sent/received through the network and other transmission media, they should implement the proper serializers and deserializers.</t>
            </li>
          </ul>
          <artwork><![CDATA[
sendMessage(Message: msg, Peer: destination)

sendMessage(Message: msg, Peer: destination, Properties: props)

sendMessage(Message: msg, Peer: destination, String: alias, Properties: props)
]]></artwork>
          <t><em>sendMessage</em> can be invoked in three distinct ways:</t>
          <ul spacing="normal">
            <li>
              <t>A simple, default version that only requires the message and its destination as arguments. It sends the message using the preferences specified in the initializer.</t>
            </li>
            <li>
              <t>A more specialized version allows the developer to specify the message along with a set of optional properties (props). The purpose of this properties parameter is to enhance expressiveness, particularly for transport paths that require additional metadata (e.g., MQTT, where a topic must be specified for transmission).</t>
            </li>
            <li>
              <t>Finally, the last variant enables a node to send a message using a specific alias. In other words, a protocol can transmit a message while presenting an identity different from its default.</t>
            </li>
          </ul>
          <t>These abstractions allow protocols to have some control over how data is sent to other nodes while hiding the complexity of dealing with such. On the other hand, if a protocol is only concerned with guaranteeing that information flows in and out of its host node, it can make use of the more simple abstractions following the default configuration embedded into the framework.</t>
          <t>The following example illustrates what was presented:</t>
          <artwork><![CDATA[
//Types definition
PayloadMessage {
 string payload
}

AckMessage {
 long timestamp
}

PublishRequest {
 string topic,
 string msg
}

init():
 //Omitting request and notification registration for simplicity

 preferences = {unreliable, lightweight}
 registerCommunicationPreferences(preferences)

 registerCommunicationHandler(PayloadMessage, uponPayloadMessage)
 ...

uponPublishRequest(PublishRequest: request, Protocol: sourceProto):
 props = {characteristic: "topic"}
 payload = PayloadMessage(request.msg)
 sendMessage(payload, p, props)

uponPayloadMessage(PayloadMessage: message, Peer: sender, t: registerCommunicationPreferences):
 msg = AckMessage(Time.now)
 sendMessage(msg, sender)
]]></artwork>
          <t>The different abstractions related to interactions with multiple protocols of different nature (i.e., subscribing to a topic in MQTT, listening to a characteristic in BLE, etc.) are still under development.</t>
        </section>
      </section>
      <section anchor="protocol-handlers-procedures">
        <name>Procedures</name>
        <t>Beyond the information defined above that specifies the use of the abstractions provided by the framework, protocols may also need to execute procedures. Procedures can range from simple calculations on specific parameters to updates on the local state.
Thus, protocols should be allowed to declare an arbitrary number of procedures and invoke them inside the different handlers defined in the <em>init</em> function.
The declaration of a procedure should be as follows:</t>
        <artwork><![CDATA[
procedureName(args):
 //Perform computations on args

 return result;
]]></artwork>
        <t>Possible usage of a procedure within a protocol:</t>
        <artwork><![CDATA[
calcIntersection (set1, set2):
 return set1 ^ set2;

uponSetMessage(SetMessage: message, Peer: origin):
 intersect = calcIntersection(this.set, msg.set)
 this.set = intersect
 sendReply(SetUpdateReply(this.set), destProto)
]]></artwork>
      </section>
      <section anchor="example">
        <name>Example</name>
        <t>In this section, we will provide a simple but complete example of a protocol definition using the constructions stated above. Some definitions are omitted for clarity and succinctness.</t>
        <artwork><![CDATA[
                         Types Definition


def BroadcastRequest{
 byte [] data
}

def BroadcastNotification {
 byte [] data
}

def NeighborDownNotification {
 Peer neighbor
}

def BroadcastMessage {
 byte [] data,
 long timestamp,
 short ttl

 serializer(out):
  out.writeByteArray(data)
  out.writeLong(timestamp)
  out.writeShort(ttl)

 deserializer(in):
  data = in.readByteArray()
  timestamp = in.readLong(in)
  ttl=in.readShort(ttl)
  return BroadcastMessage(data, timestamp, ttl)
}

def GarbageCollectionTimer {
 long interval
}
]]></artwork>
        <artwork><![CDATA[
                                Protocol

state = {
 dataSet : Set<BroadcastMessage>,
 neighbors: Set<Peer>,
 protocolApp: Protocol

 @AutoConfigurable
 @Adaptive
 long ttl,
}

init(properties):
 this.dataSet = Set<BroadcastMessage>()
 this.neighbors = Set<Peer>()
 this.app = properties.protocol
 //ttl will be configured by the framework

 registerDiscoveryHandler(uponDiscovery)

 registerSelfConfiguration(properties, uponSelfConfig)

 registerAdaptiveConfiguration(properties, uponAdaptive)

 resources = {SYSTEM_NETWORK_WRITE_BYTES}
 registerResourceMonitor(resources, uponResourceSample)

 preferences = {reliable, connectionOriented}
 registerCommunicationPreferences(preferences)

 registerRequestHandler(BroadcastRequest, uponBroadcastRequest)
 subscribeNotification(NeighborDownNotification,uponNeighborUpNotification)

 registerTimerHandler(GarbageCollectionTimer, uponGarbageCollectionTimer)
 setupPeriodicTimer(GarbageCollectionTimer(properties.interval), uponGarbageCollectionTimer)

 registerCommunicationHandler(BroadcastMessage, uponBroadcastMessage)

// Request/Reply Handlers
uponBroadcastRequest(BroadcastRequest: request, Protocol: sourceProtocol):
 BroadcastMessage = BroadcastMessage(request.data, Time.now)
 deliver(BroadcastMessage)
 propagate(this.neighbors, BroadcastMessage)

// Timer Handlers
uponGarbageCollectionTimer(GarbageCollectionTimer: timer):
 this.dataSet.removeIf(data -> Time.now - data.timestamp >
 timer.interval && data.ttl >= state.ttl)

// Notification Handlers
uponNeighborDownNotification(NeighborDownNotification: notification):
 this.neighbors.remove(notification.neighbor)

// Discovery, Configuration and Resources
uponDiscovery(DiscoveryNotification: notification):
 this.neighbors.add(event.peer)

uponSelfConfig(SelfConfigParameters selfConfig):
 for p in state as AutoConfigurable:
  p = selfConfig.parameters.get(p)

uponAdaptive(SelfConfigParameters adaptive):
 for p in state as Adaptive:
  p = adaptive.parameters.get(p)

uponResourceSample(ResourceEvent sample):
  log("Resource Sample: {} {}", sample.resourceType, sample.usage)

// Communication Handlers
uponBroadcastMessage(BroadcastMessage: msg, Peer: sender):
 msg.ttl++
 deliver(msg)
 propagate(this.neighbors - sender, msg)

// Procedures
deliver(BroadcastMessage: msg):
 if(!this.dataSet.contains(msg)):
 this.dataSet.add(msg)

 notification = BroadcastNotification(msg.data)
 triggerNotification(notification)

propagate(Set<Peer> destinations, BroadcastMessage: msg):
 destinations.forEach(n -> sendMessage(msg, n))
]]></artwork>
      </section>
    </section>
    <section anchor="architecture">
      <name>Architecture</name>
      <t>GFDS aims to simplify the development and management of highly dynamic decentralized systems.
To achieve this, we propose an architecture where great part of the complexity is hidden underneath different layers of abstractions.
The layers are in charge of different aspects of the system, ranging from inter-protocol event dispatching, to guaranteeing secure communication among nodes.
The architecture overview is depicted in the following diagram:</t>
      <artwork><![CDATA[
    +------------------------------------------------------------+
    |    +------------+    +------------+    +------------+      |
    |    |            |    |            |    |            |      |
    |    | Protocol 1 |    | Protocol 2 | .. | Protocol N |      |
    |    |            |    |            |    |            |      |
    |    +------------+    +------------+    +------------+      |
    |     | ^               | ^               | ^                |
    |     | | +-------+     | | +-------+     | | +-------+      |
    |     | | | Event |     | | | Event |     | | | Event |      |
    |  +--|-|-|-------|-----|-|-|-------|-----|-|-|-------|---+  |
    |  |  | | | Queue |     | | | Queue |     | | | Queue |   |  |
    |  |  | | +-------+     | | +-------+     | | +-------+   |  |
    |  |  v |               v |               v |             |  |
    |  | +--------------------------------------------------+ |  |
    |  | |         +----------+  +-----------+  +---------+ | |  |
    |  | |  Event  | Resource |  | Discovery |  |  Timer  | | |  |
    |  | | Manager |  Manager |  |  Manager  |  | Manager | | |  |
    |  | |         +----------+  +-----------+  +---------+ | |  |
    |  | +--------------------------------------------------+ |  |
    |  |       ^  |                            ^  |           |  |
    |  |       |  v                            |  v           |  |
    |  | +---------------+             +--------------------+ |  |
    |  | |               |             |                    | |  |
    |  | |               |  ---------> |   Configuration    | |  |
    |  | |               |  <--------- |      Manager       | |  |
    |  | |               |             |                    | |  |
    |  | | Communication |             +--------------------+ |  |
    |  | |    Manager    |             +--------------------+ |  |
    |  | |               |             |                    | |  |
    |  | |               |  ---------> |     Security       | |  |
    |  | |               |  <--------- |      Manager       | |  |
    |  | |               |             |                    | |  |
    |  | +--------------+              +--------------------+ |  |
    |  |                                                      |  |
    |  |                        Core                          |  |
    |  +------------------------------------------------------+  |
    +------------------------------------------------------------+
                | |                                | |
                | |                                | |
    <-----------+ |                                | +------------>
   <--------------+      Incoming and Outgoing     +--------------->
                              Connections
]]></artwork>
      <t>Figure 1: Framework architecture</t>
      <t>As stated previously, the base unit of interaction is the protocol. Protocols "live" on top of the stack and developers interact with the framework by specifying protocols, implementing their logic and defining the proper handlers to receive events (i.e., timers, inter-protocol, etc.) from the framework. This means that, to a developer, the interaction with the other layers is virtually non-existent.
The event manager is in charge of dispatching events to the correct protocols, managing timers, and communicating with the communication manager and configuration manager. Finally, the security manager is responsible for identity management and ensuring secure communication among nodes.
All of this is encapsulated in what we call the <em>core</em>.</t>
      <t>The <em>core</em> is a centralized component that coordinates the execution of the different protocols through an event queue. It is separated into different elements, as depicted in Figure 1, each responsible for a different task. In the following subsections, we specify the different details of each component.In the following subsections, we specify the different details of each component.</t>
      <t>This design allows the framework to make a clear separation of concerns regarding what a developer is to interact with, and what is managed internally.</t>
      <section anchor="arch-protocol">
        <name>Protocols</name>
        <t>Developers interact with the framework by specifying protocols. Protocols have access to common abstractions and APIs that allow to make use of the tools provided by the framework (i.e., explained in <xref target="protocol"/>).</t>
        <t>Protocols send/receive events to/from the event manager. Each of these events contains information about their type (i.e., request, reply, notification, etc.) and the necessary information to be correctly interpreted by the proper destination (e.g., a request event contains the source protocol to which the destination can reply). Thus, each protocol can be seen as a state machine whose state evolves by receiving and processing events.</t>
        <t>Each protocol has an event queue that orders and serializes incoming events. Each protocol should control its life-cycle by advancing "time" in a manner it sees fit (i.e., per clock tick, periodically, etc.). In other words, protocols are in charge of pooling their respective queue and processing events by their order of arrival by matching the respective event with the registered handler.
Events emitted by the protocol are sent to the event manager who handles their proper processing and forwarding to the correct destination.</t>
        <t>From the developer's point of view, a protocol is responsible for defining the callbacks used to process the different events in the queue and interact with other components in the framework by sending those events. This means that developers only worry about registering the proper callbacks for each type and implementing their logic and interact with other protocols by sending events, while letting the framework handle event management through interaction with the queue.</t>
        <t>Although each protocol contains its own event queue, these are mediated by the event manager, the component responsible for delivering events to each protocol queue and forwarding the events issued by protocols to their correct destination.</t>
        <t>The following diagram depicts a protocol overview, divided by two views.
A <em>developer view</em> specifies the environment and elements to be handled by the developer (i.e., setup callbacks, manage protocol state, etc.), and an <em>internal view</em> which is managed by the framework. With this design, developers only worry about creating the respective handlers, and the framework handles that events are properly dispatched to other components in the framework and that the protocol receives events accordingly.</t>
        <artwork><![CDATA[
+---------------------------------------------------------------------+
|                           ----------+                     Developer |
|                           |         |                        View   |
|                           |  State  |                               |
|                           |         |                               |
|                           +----------                               |
|                                                                     |
|    +---------+         +---------+        +---------+               |
|    | +---------+       | +---------+      | +---------+             |
|    | | +---------+     | | +---------+    | | +---------+           |
|    | | |     | | |     | | |     | | |    | | |     | | |           |
|    +-|-|-----+ | |     +-|-|-----+ | |    +-|-|-----+ | |           |
|      +-|-------+ |       +-|-------+ |      +-|-------+ |           |
|        |      ...|         |      ...|        |      ...|           |
|        +---------+         +---------+        +---------+           |
|                                                                     |
|    Request Handlers    Reply Handlers     Notification Handlers     |
|                                                                     |
|    +---------+          +---------+        +---------+              |
|    | +---------+        | +---------+      | +---------+            |
|    | | +---------+      | | +---------+    | | +---------+          |
|    | | |     | | |      | | |     | | |    | | |     | | |          |
|    +-|-|-----+ | |      +-|-|-----+ | |    +-|-|-----+ | |          |
|      +-|-------+ |        +-|-------+ |      +-|-------+ |          |
|        |      ...|          |      ...|        |      ...|          |
|        +---------+          +---------+        +---------+          |
|                                                                     |
|    Timer Handlers       Communication       Discovery, Resource     |
|                            Handlers          and Configuration      |
|                                                  Handlers           |
|                                                                     |
|<------------------------------------------------------------------->|
|                             ^      ^      ^                         |
|                              \     |     /                          |
|                               v    v    v                           |
|                             +-------------+                         |
|                      +----- | +---------+ |                         |
|                Poll  |      | |  Event  | |                         |
|                queue |      | |  Queue  | |                         |
|                      +----> | +---------+ |                Internal |
|                             +-------------+                  View   |
+---------------------------------------------------------------------+
]]></artwork>
        <t>Figure 2: Protocol overview</t>
      </section>
      <section anchor="arch-eventmanager">
        <name>Event Manager</name>
        <t>The event manager is one of the most important components of the framework and the bridge between developers (i.e., protocols) and the framework's inner workings. It is responsible for the following tasks: exchanging events between respective protocols (i.e., <em>inter-protocol</em>), forwarding events coming from the communication and configuration manager to the right protocols, and handling discovery and timers.</t>
        <t>Each protocol has a unique identifier associated with it (i.e., a random identifier issued by the framework or passed on as an argument during initialization). During protocol registration, the event manager stores the different identifiers in order to forward events to their respective destination. Moreover, since notifications are meant to ensure one-to-many semantics, the event manager maintains a mapping between notifications and subscriptions of the corresponding protocols. With this information, we are able to guarantee the proper dispatching of events to their destination.</t>
        <t>In the upcoming subsections, we will detail the different subtasks of the event manager.</t>
        <section anchor="inter-protocol-interaction">
          <name>Inter Protocol Interaction</name>
          <t>Inter-protocol interactions-communication between protocols in the same machine-is done through requests, replies and notifications. While requests and replies offer one-to-one semantics, notifications provide one-to-many semantics with the use of subscriptions.</t>
          <t>Requests, and their replies, receive a destination protocol, which allows the event manager to insert these events in the appropriate protocol queues, by accessing the set of registered protocols. This simple but effective design ensures that protocols can interact with each other in an efficient way, in order to build complex behaviours through the sharing of information.</t>
          <t>In contrast, notification triggers are meant to be delivered to all protocols that are interested in it. To achieve this, the event manager scans its mapping of notifications to subscriptions and transmits such information to all.</t>
        </section>
        <section anchor="communication-and-configuration">
          <name>Communication and Configuration</name>
          <t>The event manager acts as an intermediary between the protocol layer and both the communication and configuration manager.
The communication manager handles connections with other nodes, while the configuration manager is responsible for self-configuration and adaptability during runtime. Consequently, the event manager has to guarantee that these events arrive at the protocols that are interested in them.</t>
          <t>During initialization, each protocol registers handlers for external events they wish to listen to (i.e., transmissions, configuration updates, etc.). Internally, the framework maps each event to their respective consumers so that they are rightfully informed when such events happen. Subsequently, when, for instance, a message arrives from another node, the event manager can successfully generate an event to the correct protocol (or protocols) that registered it during initialization, by placing them in the protocol event queue for later processing.</t>
          <t>Once again, at the protocol level, the protocol should only be concerned with defining the proper handlers and the framework will guarantee that information is correctly forwarded to its destination and that protocols will be rightfully apprized when an event they registered is triggered.</t>
          <artwork><![CDATA[
                                    ^
                                    |
                                    |
        +---------------------------|-------------------------+
        |                           |                         |
        |                           |                         |
        | +-------------------------------------------------+ |
        | | destProtos = getProtocolsRegistered(event.type) | |
        | |                                                 | |
        | | for p in destProtos:                            | |
        | |  dispatchEvent(event, p)                        | |
        | +-------------------------------------------------+ |
        |          ^                               ^          |
        |          |                               |          |
        +----------|-------------------------------|----------+
                   |                               |
                   |                               |
        +---------------------+         +---------------------+
        |                     |         |                     |
        |    Communication    |         |    Configuration    |
        |       Manager       |         |       Manager       |
        |                     |         |                     |
        +---------------------+         +---------------------+
]]></artwork>
          <t>Figure 3: Overview of communication and configuration flow.</t>
          <t>In <xref target="arch-communicationmanager"/> and <xref target="arch-configmanager"/> a detailed explanation is provided regarding event generation in this context.</t>
        </section>
        <section anchor="timer-manager">
          <name>Timer Manager</name>
          <t>The timer manager is a small module that ensures that tasks are triggered at specific time intervals or after a certain amount of time has passed.</t>
          <t>Protocols create timers by either invoking <em>setupTimer</em> or <em>setupPeriodicTimer</em>. When doing this, an event is sent by the corresponding protocol to the event manager, which in turn passes it along to the timer manager. The timer manager stores all the timers issued by the different protocols and is in charge of advancing "time" (e.g., clock ticks). When the timer manager detects that a timer has come to its conclusion, it informs the respective protocol that registered it by placing an event in its queue. It is worth noting that regular timers and periodic timers work in the same manner internally, with the only difference being that one is removed from the timer manager after it's finished, while the other remains active until the end of the execution of the program, or its cancellation.</t>
          <t>Each timer has a unique identifier associated with it at the moment of creation (i.e., <xref target="protocol-handlers-timer"/>). Protocols can use this identifier to cancel timers and remove them from the timer manager. This can be achieved by invoking a cancel timer event from the protocol to the event manager.</t>
          <artwork><![CDATA[
                   |                |                  ^
                   |                |                  |
                   |                |                  |
        +----------|----------------|------------------|--------+
        |          |                |                  |        |
        |          v                v                  |        |
        |    +-----------+    +-----------+      +-----------+  |
        |    | Register  |    |  Cancel   |      |  Trigger  |  |
        |    |   Timer   |    |   Timer   |      |   Timer   |  |
        |    +-----------+    +-----------+      +-----------+  |
        |                                              |        |
        |                                              |        |
        |               +------------------------------------+  |
        |          +--> | timer = poll()                     |  |
        |          |    |                                    |  |
        |  Advance |    | if timer is ready:                 |  |
        |   Time   |    |    dispatchEvent(timer, destProto) |  |
        |          |    |                                    |  |
        |          +--- |                                    |  |
        |               +------------------------------------+  |
        |                                                       |
        +-------------------------------------------------------+
]]></artwork>
          <t>Figure 4: Timer manager overview</t>
        </section>
        <section anchor="discovery-manager">
          <name>Discovery Manager</name>
          <t>In the context of decentralized systems, a frequent problem is that of identifying a contact-a node already present in the system-that can help a new node join the network. While in small systems this can be easily achieved by storing information about the different participants, in a complex and highly distributed environment this solution is no longer feasible.</t>
          <t>The discovery manager is a subcomponent that facilitates the discovery and management of peers.
During initialization, the framework provides an optional mechanism for registering the desired discovery methods. Based on this information, the discovery manager will search for nodes using the specified methods during startup. When new nodes are discovered, protocols receive notifications through the handler registered via <em>registerDiscoveryHandler</em> (i.e., <xref target="protocol-disc-communication"/>).</t>
          <artwork><![CDATA[
registerDiscoveryMethods(DiscoveryMethod []: methods)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerDiscoveryMethods</em> states the preferences of a developer regarding discovery methods. In other words, the developer can choose how the framework discovers other nodes by specifying which technologies and protocols are used to achieve this (e.g., mDNS <xref target="RFC6762"/>, multicast etc.).</t>
            </li>
          </ul>
          <artwork><![CDATA[
main(config):
 ...
 // Setup discovery
 discoveryMethods = {mDNS}
 framework.registerDiscoveryMethods(discoveryMethods)
 ...

                  Ex 1.: Discovery Method Registration
]]></artwork>
          <t>Moreover, when a explicit request for an announcement or probe is received, the respective action is triggered by the discovery manager. Namely, announce that the node sending the message is providing a certain service, or probe the system for nodes that offer a specific service.</t>
          <t>The framework should specify a list of methods available for this purpose, for instance, mDNS, DHT, etc., or analogously, allow the definition of lists of contact nodes per protocol, for bootstrapping (e.g., in a peer-to-peer online video game there may exist well known players which could be used as contact points).</t>
          <artwork><![CDATA[
          |                                                    ^
          |                                                    |
          |                                                    |
  +-------|----------------------------------------------------|---+
  |       |                                                    |   |
  |       v                                                    |   |
  | +--------------+      +--------------------------------+   |   |
  | |   Register   |      |                                |   |   |
  | |  Discovery   |      | discoveryMethods               |   |   |
  | |    Method    | ---->|         .add(method, protocol) |   |   |
  | |              |      |                                |   |   |
  | +--------------+      +--------------------------------+   |   |
  |                                                            |   |
  |                                                            |   |
  |                                                            |   |
  |                +---------------------------------------------+ |
  |                |                                             | |
  |          +---->| data = newParticipantDiscovered()           | |
  |          |     |                                             | |
  |          |     | protocols = protocolsByMethod(data.method)  | |
  |  Listen  |     |                                             | |
  |          |     | for p in protocols:                         | |
  |          |     |   dispatchEvent(data, p)                    | |
  |          +-----|                                             | |
  |                +---------------------------------------------+ |
  |                                                                |
  |                +---------------------------------------------+ |
  |                |                                             | |
  |          +---->| for method in methods                       | |
  |          |     |   announce = Announce(myself, method)       | |
  | Announce |     |   send(announce)                            | |
  |          |     |                                             | |
  |          +-----|                                             | |
  |                +---------------------------------------------+ |
  |                                                                |
  +----------------------------------------------------------------+
]]></artwork>
          <t>Figure 5: Discovery manager diagram</t>
        </section>
        <section anchor="resource-manager">
          <name>Resource Manager</name>
          <t>In decentralized systems, nodes often operate under heterogeneous and dynamic conditions, where computational power, memory, storage, and network bandwidth can vary widely. Protocols running on these nodes must be resilient to such variability in order to maintain consistent performance, reliability, and fairness across the network.</t>
          <t>The Resource Manager is a subcomponent responsible for monitoring and reporting system resource usage, ensuring the stable and efficient operation of the framework. It provides a unified interface that allows both the framework and protocols to remain aware of current resource conditions and adapt their behavior accordingly.</t>
          <t>During initialization, the framework offers mechanisms for registering methods of metrics collection, which may range from simple scheduled sampling to triggering alerts when a resource approaches its limits (e.g., high CPU load). The framework should define a list of supported collection strategies, such as periodically, onDemand, onLimit, to name a few.</t>
          <artwork><![CDATA[
registerResourceMethods(ResourceMethod []: methods)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerResourceMethods</em> specifies the developer’s preferences regarding resource sampling strategies. In practice, this allows the developer to control when the framework collects resource data and informs protocols (e.g., periodically, only when a threshold is reached, etc.).</t>
            </li>
          </ul>
          <artwork><![CDATA[
main(config):
  ...
  //Setup resource method
  resourceMethods =  {periodically, onLimit}
  framework.registerResourceMethods(resourceMethods)
  ...
]]></artwork>
          <t>To relay resource information to protocols, during initialization, each protocol registers its own handlers for processing resource usage samples via <em>registerResourceMonitor</em> (see <xref target="protocol-handlers-resources"/>). Additionally, protocols may subscribe to notifications using the resource-related events exposed by the framework (see <xref target="arch-frameworkevents"/>).</t>
          <t>In summary, the framework configures the sampling methods at startup, monitors the selected resource types, and delivers usage data or warnings to the subscribed protocols according to the defined sampling strategies. This interaction is illustrated in the following diagram:</t>
          <artwork><![CDATA[
  | |
  | |                                                                ^
  | |                                                                |
+-|-|----------------------------------------------------------------|-+
| | |   +-----------------+           +-------------------------+    | |
| | |   |    Register     |           | resourceManager         |    | |
| | +-> |    Resource     | --------> |    .putMethod(method)   |    | |
| |     |     Method      |           |                         |    | |
| |     +-----------------+           +-------------------------+    | |
| |                                                                  | |
| |     +-----------------+           +-------------------------+    | |
| |     |    Register     |           | resourceManager         |    | |
| +---> |    Resource     | --------> |  .putResource(resource, |    | |
|       |   Monitoring    |           |               protocol) |    | |
|       +-----------------+           +-------------------------+    | |
|                                                                    | |
|                                                                    | |
|                         +-------------------------------------+    | |
|                         |                                     |    | |
|             +-------->  | for (r, pList) in resourceManager:  |    | |
|             |           |   sample = resourceManger.sample(r) |    | |
|   Execute   |           |                                     |    | |
|   for each  |           |   for p in pList:                   | ---+ |
|    method   |           |    event = ResourceEvent(sample)    |      |
|             |           |    dispatchEvent(event, p)          |      |
|             +---------  |                                     |      |
|                         +-------------------------------------+      |
|                                                                      |
+----------------------------------------------------------------------+
]]></artwork>
          <t>Figure 6: Resource manager diagram</t>
        </section>
        <section anchor="arch-frameworkevents">
          <name>Framework Events</name>
          <t>While most of the events used during execution are dedicated to inter-protocol and inter-node interaction, the framework also provides control events that enable protocols to interact directly with the framework’s internal services and functionalities. These events expose higher-level operations, allowing protocols to request, configure, or react to actions managed by the framework itself, without being tightly coupled to its internal implementation.</t>
          <t>For instance, as illustrated in <xref target="protocol-disc-communication"/>, a protocol may need to interact with the Discovery Manager to probe the system for neighboring nodes. This interaction can be achieved through a dedicated event, such as RequestAnnouncement, which instructs the framework to announce the node’s presence or gather peer information on behalf of the requesting protocol. Similarly, other managers (e.g., the Configuration Manager or the Resource Manager) define their own set of framework events that enable protocols to adapt dynamically to changes in system state or resource conditions.</t>
          <t>In this way, the framework events serve as the bridge between application logic and system management, allowing protocols to remain lightweight and modular while still leveraging essential services such as discovery, configuration, security, and resource monitoring. The design also emphasizes extensibility: developers are free to define new framework events when specialized functionality is required, ensuring that the framework can evolve alongside new use cases and deployment environments.</t>
          <t>As such, we propose the following categories of framework events:</t>
          <ul spacing="normal">
            <li>
              <t><strong>Discovery Events</strong>: Events that allow protocols to discover peers and services in the system (e.g., RequestProbe);</t>
            </li>
            <li>
              <t><strong>Configuration Events</strong>: Events that enable protocols to adjust configuration parameters dynamically, supporting self-configuration and adaptive reconfiguration (e.g., SelfConfigParameters);</t>
            </li>
            <li>
              <t><strong>Resource Events</strong>: Events that expose the node’s resource state, such as CPU, memory, bandwidth, or storage availability. These allow protocols to collect metrics for analytics or adapt to resource limitations (e.g., ResourceSample).</t>
            </li>
          </ul>
          <t><xref target="appendixB"/> specifies a generic set of events for each of these categories. Nevertheless, while these events cover common behaviors in decentralized systems, developers are strongly encouraged to define additional events tailored to their applications and requirements.</t>
        </section>
      </section>
      <section anchor="arch-configmanager">
        <name>Configuration Manager</name>
        <t>The configuration manager plays a critical role in managing and maintaining the configuration settings for a node, ensuring that all components function seamlessly together and adapt to the different changes happening in the system. Firstly, nodes should be capable of self-configuration during startup. Secondly, since a system's state will evolve throughout its execution, protocols should be able to adapt accordingly. Finally, since these systems may be constituted by hundreds or even thousands of nodes, manual, human interaction is unreliable, and therefore all of these changes should be conducted in a totally autonomous way.</t>
        <t>The configuration manager achieves by receiving information from protocols (through the event manager) of which parameters it is responsible for configuring and updating. This may happen in two distinct ways: 1) based on the local metrics collected by the node (e.g., CPU usage, memory usage, latency, etc.) the framework can make informed local decisions to alter configuration parameters, or, 2) when new information arrives through the communication manager, the configuration manager processes it and forwards the respective event to the event manager so it can be correctly dispatched to the protocol that relies on it.
In the future, we plan to describe the full interface for protocol configuration, as depicted in <xref target="RFC6241"/>.</t>
        <t>In the following subsections, we will describe the different tasks of the configuration manager.</t>
        <section anchor="self-configuration">
          <name>Self Configuration</name>
          <t>A fundamental challenge lies in obtaining an initial configuration for the node joining the network. Although it is possible to resort to a default configuration, in complex systems this may not be enough, as the system may have evolved up to a point that a default configuration is no longer suitable.</t>
          <t>One possible way to solve this issue is to obtain the configuration from a node already present in the system.</t>
          <t>As described in <xref target="protocol-config-communication"/>, protocols should tag the parameters they wish to be configured by the framework as <em>AutoConfigurable</em>. This way, during protocol initialization, the framework will register which configuration parameters it should query other nodes for.
Moreover, the framework should provide a list of available methods to achieve this, such as copy and verification (i.e., contact an already active node and copy its parameters in an autonomous way), through DNS records (i.e., analyze the TXT entries of a DNS register in order to obtain recommend values to certain parameters), to name a few.</t>
          <t>Akin to the discovery manager, the configuration manager offers a mechanism to register the method used to ensure self-configuration of the parameters tagged as <em>AutoConfigurable</em> by the different protocols. Thus, during the framework initialization, we provide the following function:</t>
          <artwork><![CDATA[
registerSelfConfigurationMethods(SelfConfigMethod: method)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerSelfConfigurationMethods</em> indicates how the framework will setup its initial configuration. The function receives an argument regarding the self-configuration method. This details how the framework will handle the search for a valid configuration, from the likes of copy-validate (e.g., copying the configuration from another node that has the same <em>AutoConfigurable</em> parameters) or using a genesis node with a recommended initial configuration.</t>
            </li>
          </ul>
          <artwork><![CDATA[
main(config):
 ...
 // Setup self-configuration methods
 selfConfigMethod = {copyValidate}
 framework.registerSelfConfigurationMethods(selfConfigMethod)
 ...

                Ex 2.: Self-Config Method Registration
]]></artwork>
          <t>The framework is in charge of communication with other entities to learn this information and communicate back its findings to the protocol, by, as usual, placing an event in its event queue for processing.</t>
          <artwork><![CDATA[
  |         |                                                    ^  ^
  |         |                                                    |  |
  |         |                                                    |  |
+-|---------|----------------------------------------------------|--|-+
| |         |                                                    |  | |
| |         v            +----------------------------------+    |  | |
| |   +------------+     |                                  |    |  | |
| |   |  Register  |     | autoConfig.add(param, protocol)  |    |  | |
| |   | AutoConfig |---->| request= Param(myself, param)    |    |  | |
| |   |   Param    |     | send(param)                      |    |  | |
| |   +------------+     |                                  |    |  | |
| |                      +----------------------------------+    |  | |
| |                                                              |  | |
| |                      +-----------------------------------+   |  | |
| |   +------------+     |                                   |   |  | |
| |   |  Retrieve  |     | from = pendingParams.remove(param)|   |  | |
| +-> | AutoConfig |---->| param = Param(myself, param)      |   |  | |
|     |   Param    |     | send(param, from)                 |   |  | |
|     +------------+     |                                   |   |  | |
|                        +-----------------------------------+   |  | |
|                                                                |  | |
|                                                                |  | |
|                                                                |  | |
|                        +-----------------------------------+   |  | |
|                        | param = deliverParam()            |   |  | |
|                  +---> |                                   |   |  | |
|                  |     | protocols = protocolsParam(param) |   |  | |
|          Listen  |     |                                   | --+  | |
|                  |     | for p in protocols:               |      | |
|                  +---- |   dispatchEvent(param, p)         |      | |
|                        |                                   |      | |
|                        +-----------------------------------+      | |
|                        +-----------------------------------+      | |
|                  +---> | param = receiveParamQuery()       |      | |
|          Listen  |     | pendingParams.add(from, param)    |      | |
|                  |     | dispatchEvent(param, p)           | -----+ |
|                  +---- |                                   |        |
|                        +-----------------------------------+        |
|                                                                     |
+---------------------------------------------------------------------+
]]></artwork>
          <t>Figure 7: Self-configuration controller overview</t>
        </section>
        <section anchor="adaptability">
          <name>Adaptability</name>
          <t>Decentralized systems need to adapt while executing, since they operate in dynamic, and often unpredictable environments, where components may join, leave, or fail unexpectedly. As resources like nodes or services can change in real time, the system must adjust to maintain efficiency, performance, and reliability <xref target="RFC7575"/>. Due to these systems complexity and size, the task of managing and adapting them proves too complex for humans. The only feasible option is to have this adaptability happen in an autonomous way. While the initial configuration of a node may prove to be correct and even efficient in a preliminary state of the system, as conditions change, such configuration may become suboptimal or even incorrect. To mitigate this issue, nodes should aim to adapt during runtime, in order to keep up with the current state of the system as a whole.</t>
          <t>These changes can be triggered locally, with values ​​calculated by the node itself given its local perception of the network, or by the node's neighbors that aim to converge to a common global configuration.</t>
          <t>To accomplish this, protocols should tag the parameters they wish to be reconfigured as <em>Adaptive</em>. Parameters with this tag will be managed by the framework and updated when a reconfiguration request is issued (i.e., due to a periodic timer, reconfiguration data arriving from another node, an intelligent controller executing an AI model <xref target="I-D.irtf-nmrg-ai-challenges-04"/>, etc. ). Reconfiguration can happen through distinct methods, such as analyzing local metrics (e.g., the CPU usage of a protocol may be too high), synchronization with other nodes running the same protocol (i.e., to reach convergence of configuration), etc. So, the framework <bcp14>SHOULD</bcp14> provide a clear clarification of the methods available and how they behave.</t>
          <t>During initialization, the developer specifies the method for automatically reconfiguring parameters tagged as <em>Adaptive</em> by protocols by selecting one of the available methods. This is achieved using the following function:</t>
          <artwork><![CDATA[
registerAdaptiveMethods(AdaptiveMethod: method)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerAdaptiveMethods</em> defines how the framework will autonomously update protocol parameters. The function takes an argument specifying the adaptive method, which determines how the framework manages updates to Adaptive parameters. This may involve leveraging local or remote metrics, requesting the state of other nodes, or other adaptive mechanisms.</t>
            </li>
          </ul>
          <artwork><![CDATA[
main(config):
 ...
 // Adaptive methods
 adaptiveMethod =  {localMetrics}
 framework.registerAdaptiveMethods(adaptiveMethod)
 ...

                  Ex 3.: Adaptive Method Registration
]]></artwork>
          <t>In the following diagrams, we show the interaction diagram regarding the requests issued to the adaptive controller and the background listeners handling incoming connections from the communication manager, respectively.</t>
          <artwork><![CDATA[
  | |        |
+-|-|--------|---------------------------------------------------------+
| | |        |                                                         |
| | |        |           +--------------------------------------+      |
| | |   +----|-------+   |                                      |      |
| | |   |  Register  |   | adaptive.add(param, protocol) |      |
| | |   |  Adaptive  |-->| request= Param(myself, param)        |      |
| | |   |   Param    |   | send(param)                          |      |
| | |   +------------+   |                                      |      |
| | |                    +--------------------------------------+      |
| | |                                                                  |
| | |                    +--------------------------------------+      |
| | |   +------------+   |                                      |      |
| | |   |  Retrieve  |   | from = pendingParams.remove(param)   |      |
| | +-> |  Adaptive  |-->| param = Param(myself, param)         |      |
| |     |   Param    |   | send(param, from)                    |      |
| |     +------------+   |                                      |      |
| |                      +--------------------------------------+      |
| |                                                                    |
| |                      +--------------------------------------+      |
| |    +-------------+   | method = getReconfigMethod(param)    |      |
| |    | Reconfigure |   |                                      |      |
| +--> |   Request   |-->| // execute reconfig method           |      |
|      |             |   |                                      |      |
|      +-------------+   |                                      |      |
|                        +--------------------------------------+      |
+----------------------------------------------------------------------+
]]></artwork>
          <t>Figure 8: Adaptive controller requests overview</t>
          <artwork><![CDATA[
                                                                   ^ ^
                                                                   | |
+------------------------------------------------------------------|-|-+
|                        +--------------------------------------+  | | |
|                        |  param = deliverParam()              |  | | |
|                   +--->|                                      |  | | |
|                   |    |  protocols  = protocolsParam(param)  |  | | |
|           Listen  |    |                                      |--+ | |
|                   |    |  for p in protocols:                 |    | |
|                   +----|    event = ParamDeliver(param)       |    | |
|                        |    dispatchEvent(param, p)           |    | |
|                        +--------------------------------------+    | |
|                        +--------------------------------------+    | |
|                   +--->|  param = receiveParamQuery()         |    | |
|           Listen  |    |  pendingParams.add(from, param)      |----+ |
|                   |    |  dispatchEvent(param, p)             |      |
|                   +----|                                      |      |
|                        +--------------------------------------+      |
+----------------------------------------------------------------------+
]]></artwork>
          <t>Figure 9: Adaptability listeners overview</t>
        </section>
      </section>
      <section anchor="arch-securitymanager">
        <name>Security Manager</name>
        <t>One of the greatest challenges in distributed systems, particularly decentralized ones, is the ability to accurately identify and authenticate nodes in the absence of a central certification authority. Over the years, various solutions have been proposed <xref target="Authentication_Survey"/>, including statistical trust models, auxiliary networks composed of trusted nodes, and other approaches.</t>
        <t>To eliminate centralized components and minimize reliance on other nodes for trust, we propose a self-signed public key cryptography mechanism as the default security solution. In this approach, each node independently generates and manages its own identity using an asymmetric cryptographic scheme.</t>
        <t>The security manager is structured into distinct components responsible for identity management and creation, secure channel establishment, and the implementation of standard security primitives. Additionally, it interacts directly with the communication manager to ensure secure communication and attestation.</t>
        <section anchor="security-primitives">
          <name>Security Primitives</name>
          <t>The security primitives component is responsible for managing cryptographic material, including private keys with associated certificates for identification, certificates of trusted nodes, and symmetric keys. It enables the framework to load this information into memory and persist it to disk when necessary.</t>
          <t>This component facilitates the execution of standard security procedures, such as certificate validation, signature generation, Message Authentication Codes (MACs), and block cipher operations. These fundamental capabilities allow higher-level components within the framework to build secure abstractions for the developer.</t>
        </section>
        <section anchor="identity-manager">
          <name>Identity Manager</name>
          <t>Properly identifying nodes in a distributed environment is inherently challenging due to factors such as the absence of a central authority, the dynamic nature of nodes, and system heterogeneity. While some decentralized trust models are more widely adopted than others, different solutions must balance security guarantees with user flexibility. As previously discussed, we propose a cryptographic model based on self-signed certificates. While this approach does not provide the same security assurances as other methods, it offers simplicity and flexibility in environments where a central authority or a predefined set of trusted nodes is not a viable option.</t>
          <t>The identity manager is responsible for handling the identities of users, services, and system components. Its primary function is to ensure secure, consistent, and efficient identification, authentication, and authorization across all nodes.</t>
          <t>Each node (i.e., Peer) is associated with a hash of its default certificate and maintains an internal list of aliases. An alias serves as an alternative identifier for a node, providing a simplified interface for interacting with the identity manager. This allows nodes to assume multiple identities, enabling more complex communication patterns for specific protocols when needed.</t>
          <t>Nodes can generate, delete, and manage aliases as required, with each alias possessing its own private key and self-signed certificate. Furthermore, when sending a message, a node can explicitly instruct the framework to use a specific alias (i.e., <xref target="protocol-handlers-communication"/>).</t>
          <t>Although this design does not support verifying human-readable node information (e.g., DNS names in certificates issued by a Central Authentication Service (CAS)), it ensures that nodes can reliably reference known peers and verify that they are communicating with the same entity as before.</t>
          <t>This simple yet powerful construct provides two essential functionalities: signing data and verifying previously signed information. These capabilities form the foundation for establishing secure communication channels.</t>
        </section>
        <section anchor="secure-communication">
          <name>Secure Communication</name>
          <t>Secure channels are communication pathways that guarantee the confidentiality, integrity, and authenticity of messages exchanged between nodes. They prevent eavesdropping, tampering, and impersonation by malicious actors.</t>
          <t>To establish secure channels, the framework relies on the identity manager to ensure proper signature generation and verification, ensuring that transmitted messages remain both confidential and authentic. When a node requests secure message transmission (i.e., <xref target="protocol-handlers-communication"/>), the communication manager coordinates with the security manager to handle the process securely.</t>
          <t>The security manager utilizes cryptographic primitives and the node's identity to sign and encrypt the data before forwarding the encrypted payload to the communication manager for transmission.</t>
          <artwork><![CDATA[
                |                            ^
                |                            |
                v                            |
          +----------+      +-------------------------------+
          |          |      | identify = getAlias(alias)    |
          |   Sign   | ---> |                               |
          |          |      | identify.sign(data)           |
          +----------+      +-------------------------------+


                |                            ^
                |                            |
                v                            |
          +----------+      +--------------------------------+
          |          |      |                                |
          |  Verify  | ---> | verify(alias, signature, data) |
          |          |      |                                |
          +----------+      +--------------------------------+
]]></artwork>
          <t>Figure 10: Identity manager and channels usage overview</t>
          <t>It is important to note that this module is entirely optional to the developer, meaning that these functionalities are only utilized if the developer requests for the transmission of messages in a secure fashion.</t>
        </section>
      </section>
      <section anchor="arch-communicationmanager">
        <name>Communication manager</name>
        <t>Handling communication can prove to be extremely complex, due to the different nature of different communication interfaces. While in a robust and resilient environment it may be viable to have a predefined established communication interface to connect two nodes, in a dynamic one such an option may not be reliable. Challenges such as the ability of nodes to join and leave the system at any point, loss of connectivity due to high mobility, or heterogeneity, make having only one communication option between any pair of nodes an impractical solution. Moreover, in practice, lots of protocols are agnostic to the communication layer and are mostly worried that information arrives at their correct destination, without being concerned about how that is accomplished.</t>
        <t>To address these challenges, we introduce a communication manager that facilitates the use and negotiation of multiple communication interfaces. These interfaces are abstracted through transports, which serve as intermediaries between protocols and communication mechanisms. Nodes communicate using the available transports, each of which corresponds to a specific communication interface (e.g., TCP, BLE, QUIC).</t>
        <t>When a protocol is initialized (i.e., <xref target="protocol-handlers-communication"/>), the developer specifies connection preferences using keyword-based parameters. These keywords define the communication guarantees the developer requires. For example:</t>
        <ul spacing="normal">
          <li>
            <t>If the preferences include {reliable, connectionOriented}, the framework will prioritize TCP as the default transport.</t>
          </li>
          <li>
            <t>If the preferences include {lightweight, connectionless}, the framework will favor UDP.</t>
          </li>
        </ul>
        <t>The specified keywords generate an ordered list of communication preferences. For instance, {reliable, unreliable} would result in {TCP, UDP} in that order. The exact mapping of keywords to transport protocols is still under development and will be detailed in future versions. If an invalid combination is provided, the framework will notify the protocol by throwing an error and terminating initialization (i.e., <xref target="arch-communication-networkevents"/>).</t>
        <t>Using this information, the communication manager sets up a transport for each interface and establishes a priority order based on the provided preferences. The communication manager will attempt to adhere to these preferences, resorting to lower-priority transports only if those higher on the list become unavailable (e.g., if a TCP connection fails, the framework will attempt to send the message via UDP).</t>
        <section anchor="arch-communicationmanager-arch">
          <name>Architecture</name>
          <t>As previously described, connections are abstracted as transports. Transports serve as an intermediary mechanism that enables nodes to interact with each other. Protocols utilize these transports in an agnostic manner to facilitate message transmission.</t>
          <t>The communication manager is divided into different components, as depicted in the following diagram:</t>
          <artwork><![CDATA[
      +-----------------------------------------------------------+
      |                                                           |
      |                  +--------------------+                   |
      |                  |                    |                   |
      |                  |    Multiplexer     |                   |
      |                  |                    |                   |
      |                  +--------------------+                   |
      |                  ^          ^          ^                  |
      |                 /           |           \                 |
      |                /            |            \                |
      |               v             v             v               |
      |  +-------------+     +-------------+     +-------------+  |
      |  |             |     |             |     |             |  |
      |  |  Transport  |     |  Transport  | ... |  Transport  |  |
      |  |          1  |     |          2  |     |          N  |  |
      |  +-------------+     +-------------+     +-------------+  |
      |    | |                     | |                     | |    |
      |    | |                     | |                     | |    |
      +----|-|---------------------|-|---------------------|-|----+
           | |                     | |                     | |
           | |                     | |                     | |
    <------+ |                     | |                     | +------>
   <---------+                     v v                     +--------->
]]></artwork>
          <t>Figure 11: Communication manager architecture</t>
          <t>The multiplexer serves as the controller responsible for selecting the appropriate transport for communication. It translates the keywords provided as preferences into concrete transport implementations, maintains the priority order established by protocols, and forwards data accordingly.
When incoming data is received, the multiplexer processes it and ensures delivery to the appropriate protocol via the event manager. Additionally, it continuously monitors transport layers for failures or errors and attempts to reestablish communication in response to abrupt connection disruptions.</t>
          <t>Transports are coupled with a communication interface. Each transport can manage multiple parallel connections (e.g., multiple TCP connections on different ports), enabling distinct "virtual connections" for different protocols. Protocols can either use a default, pre-established connection associated with the transport-created when the transport is first requested-or establish their own dedicated connections. This aspect of the framework remains a work in progress, and a formal specification for the data format used in transport communication should be defined.</t>
          <t>It is important to note that transports are highly flexible and modular, supporting a pluggable architecture. Developers specify the communication interfaces they intend to use, and the framework automatically assigns the appropriate transport. Additionally, new transports can be implemented and customized to enable alternative communication behaviors and guarantees. For instance, a developer may require a transport protocol not provided by the framework, which they can implement using the standardized transport API.</t>
        </section>
        <section anchor="peer-identification">
          <name>Peer Identification</name>
          <t>Identifying peers in a dynamic distributed system is challenging due to the system's inherent characteristics. Nodes frequently join, leave, relocate, or fail, making it difficult to maintain an accurate and up-to-date view of the system's topology. Furthermore, in the absence of a central authority responsible for maintaining a definitive "source of truth," achieving a global perspective on peer identities is infeasible.</t>
          <t>A naive approach would be to identify nodes using their network address, such as an IP address (<xref target="RFC791"/>) and port. While this may be effective in static, reliable networks, it is unsuitable for highly dynamic environments where connections can fail unexpectedly and nodes may physically relocate, resulting in loss of connectivity.</t>
          <t>To address this challenge, we propose a peer identifier abstraction that encapsulates multiple pieces of information, ensuring that each node in the system can be uniquely identified. Each node is primarily identified by a self-signed certificate, specifically a public key. Assuming the use of a well-established public-key cryptosystem such as RSA (<xref target="RFC8017"/>), the likelihood of a collision is extremely low, providing a high degree of confidence in the uniqueness of each node's identifier. Additionally, peer identification should support reliable contact mechanisms. Given that relying on a single contact path is impractical in dynamic environments, we propose that each peer identifier includes a list of transport addresses. This redundancy reduces the risk of disconnection. For example, a node may have a TCP connection via an IP address with two distinct ports and a fallback UDP connection.</t>
          <t>This version of GFDS provides a high-level overview of peer identifiers, which are subject to further refinement in future iterations. The proposed identifier consists of a hash of the node's self-signed certificate and a list of transport links, inspired by <xref target="multiaddress"/>, a self-describing network address format that enables flexible and transport-agnostic addressing.</t>
          <t>Therefore, we present a sample model of this structure:</t>
          <artwork><![CDATA[
def Peer {
  //An hash of the self-signed certificate of a node
  CertificateHash identifier,
  TransportLink {key: Transport, value...: Address}: links
  //Map of the links associated with the peer
}
]]></artwork>
          <artwork><![CDATA[
//Data forwarded by the security manager
privateKey, publicKey = RSA()
certificate = selfSign(privateKey, publicKey)

myself = Peer(certificate)

//Adds two connections to the node IP address through TCP on ports 8080 and 8081
myself.addTransportLink(TCP, 8080)
myself.addTransportLink(TCP, 8081)

//Adds a connections to the node IP address through UDP on port 700
myself.addTransportLink(UDP, 7000)

//Opens the node BLE adapter for incoming connections
myself.addTransportLink(BLE)

//See active connections
print(myself.getTransportLink(TCP))
//{ipv4/192.10.12.10/tcp/8080, ipv4/192.10.12.10/tcp/192.10.12.10:8081}

print(myself.getTransportLink(QUIC))
// {none}

print(myself.getTransportLink(BLE))
// {/ble/C0:26:DA:00:12:34}

//See node identification and connection (i.e., link and hash)
print(myself.getNodeIdentification(UDP))
//{ipv4/192.10.12.10/udp/700/node/QcSDSDAsxKDcseSsca}

]]></artwork>
          <t>It is important to note that all of this is managed internally by the framework, and the developer interacts with the communication manager by expressing the keywords englobing the behaviour he pretends to ensure during communication with other nodes.</t>
        </section>
        <section anchor="arch-communication-networkevents">
          <name>Network Events</name>
          <t>Although this layer is designed to be as agnostic as possible for developers, certain protocols may require notifications when specific changes occur in the transports they rely on. For instance, a protocol using a TCP connection as a failure detector should be notified if that connection is lost. To support this functionality, we propose the use of the framework's notification events construct.</t>
          <t>The framework materializes this as Network Events, organized into two distinct categories: <em>Transport Events</em> and <em>Connection Events</em>.
When one of these events is triggered in the communication manager (e.g., a connection failure), the framework generates a notification encapsulating the relevant information. Protocols that subscribe to such notifications will receive timely updates, while those that do not remain unaffected and agnostic to changes in the lower layers. This design ensures that protocols can react dynamically to network conditions while only processing the information they explicitly require.</t>
          <t>Transport Events provide protocols with notifications about changes in the availability, quality, or configuration of underlying transport mechanisms (e.g., TCP, UDP, QUIC). By subscribing to these events, protocols can adapt proactively to evolving network conditions without being tightly coupled to a specific transport implementation. Connection Events, on the other hand, capture the lifecycle of peer-to-peer connections within a given transport, allowing protocols to respond in real time to events such as connection establishment, failures, retries, or timeouts.</t>
          <t>With this in mind, <xref target="appendixB"/> specifies a generic set of transport and connection events to capture a wide range of network behaviors. However, while these predefined events already cover many common scenarios, the framework does not limit developers to these alone. Developers are free to define and extend new event types, enabling finer-grained control and deeper customization when building protocols. This flexibility ensures that the event system can evolve alongside the needs of diverse applications, supporting both general-purpose and highly specialized behaviors.</t>
          <t>In the following examples, we illustrate how these constructs can be used in practice:</t>
          <artwork><![CDATA[
                      ConnectionDown Example
init(properties):
  ...
  registerRequestHandler(PingRequest,uponPingRequest)
  subscribeNotification(NeighborUpNotification,uponConnectionDown)
  ...

uponPingRequest(PingRequest: request, Protocol: sourceProto):
  msg = BroadcastMessage(request.msg, this.myself)
  this.neighbors.forEach(peer -> sendMessage(msg, peer))
  sendReply(DeliverReply(request.msg), sourceProto)

uponConnectionDown(ConnectionDownNotification: notification):
  log("Connection to node {} has failed! Cause: {}", notification.peer ,notification.cause)
  this.neighbors.remove(event.peer)
]]></artwork>
          <artwork><![CDATA[
                      TransportConflict Example

init(properties):
  ...
  preferences = {reliable, secure, unsecure}
  registerCommunicationPreferences(preferences)

  registerRequestHandler(PingRequest,uponPingRequest)
  subscribeNotification(TransportConflict, uponTransportConflict)
  ...

uponTransportConflict(TransportConflict: notification)
  log.error("Impossible combination of preferences!")
  System.exit(-1)

....
]]></artwork>
        </section>
        <section anchor="arch-communicationmanager-secure">
          <name>Secure Communication</name>
          <t>To guarantee message integrity, confidentiality, and protection against unauthorized access and attacks, nodes must communicate securely. As previously described, the security manager provides cryptographic primitives for signing, verifying, encrypting, and decrypting messages. The communication manager utilizes these functionalities to establish secure communication between nodes.
For example, if a node has an open TCP connection and intends to transfer messages securely, the framework can use asymmetric cryptographic keys to upgrade the connection and establish communication via TLS <xref target="RFC8446"/> with the other node. Alternatively, it can open a new connection exclusively for TLS. The concept of transport services, explored in <xref target="RFC8922"/>, provides a common interface for utilizing transport protocols, allowing applications to easily adopt new protocols with similar security guarantees.</t>
          <t>This approach decouples security from protocol logic while ensuring flexibility. Protocols only use the framework's security components if explicitly requested (i.e., by invoking the relevant functions), thereby minimizing overhead for applications that do not require security assurances. Conversely, protocols that require secure communication can remain agnostic to the underlying complexities and simply use the provided abstractions.</t>
          <t>It is important to note that while some communication interfaces offer straightforward methods for enforcing security guarantees (e.g., TLS can be layered on top of TCP using the appropriate credentials), others, such as BLE, do not have such standardized solutions. One potential approach is encrypting data at the application level and relying on an unsecured connection for transmission. However, this remains an area of active research.</t>
        </section>
      </section>
    </section>
    <section anchor="executionmodel">
      <name>Execution Model</name>
      <t>As described in previous sections, developers interact with the platform by defining protocols. Protocols consist of various handlers that encapsulate user-defined logic. These handlers are triggered by events such as message transmissions, inter-protocol interactions, or timer-based triggers.</t>
      <t>A key requirement for ensuring a seamless developer experience is that protocols should function independently, meaning that while one protocol processes a task, other protocols and the framework itself should not be blocked. Instead, each protocol should be able to make continuous progress. To achieve this, we propose the following execution model and concurrency semantics:</t>
      <t>Each protocol is assigned a dedicated thread that handles received events sequentially via an event queue (as described in <xref target="architecture"/>), executing the corresponding callbacks. The core framework operates on its own separate thread, managing internal operations.
This design enables multiple protocols to execute concurrently (i.e., in a multi-threaded environment) while using event-based message passing to communicate. This approach eliminates concurrency-related issues for developers, as all inter-protocol interactions occur through structured event messaging. Consequently, lock-free execution is ensured for protocol interactions, while allowing multiple protocols to coexist efficiently within the same environment. This event-driven model provides developers with a clear and predictable execution flow without requiring complex concurrency mechanisms.</t>
      <section anchor="initialization">
        <name>Initialization</name>
        <t>Each instance of the framework (i.e., application) requires a main function, where the developer specifies the execution configuration (e.g., resource paths, default parameters, etc.) and registers the protocols to be executed. This setup enables the framework to allocate necessary resources and ensure each protocol operates within its designated execution environment.
Additionally, the initialization phase is when the framework configures mechanisms for node discovery, self-configuration, resource sampling, and adaptability using the available framework methods.
After initialization, the interaction is governed by the protocols and the framework is left in charge of ensuring that events are interchanged between protocols, nodes can discover other nodes running in the system, timers are correctly triggered, protocols are able to self-configure and adapt as the system evolves, and last but not least, nodes can communicate with each other.</t>
        <t>An example of initialization can be seen in the following sample:</t>
        <artwork><![CDATA[
main(config):
  framework = GFDS.newInstance()
  props = framework.loadConfig(config)

  // Discovery methods
  discoveryMethods = {mDNS}
  framework.registerDiscoveryMethods(discoveryMethods)

  //Resource management
  resourceMethods =  {periodically, onLimit}
  framework.registerResourceMethods(resourceMethods)

  //Self methods
  selfConfigMethod =  {copyValidate}
  framework.registerSelfConfigurationMethods(selfConfigMethod)

  // Adaptive methods
  adaptiveMethod =  {localMetrics}
  framework.registerAdaptiveMethods(adaptiveMethod)

  // Protocol registration
  app = BlocksApplication()
  antiEntropy = AntiEntropyProtocol()
  broadcast = EagerPushBroadcastProtocol()
  membership = FullMembership()

  framework.registerProtocol(app)
  framework.registerProtocol(antiEntropy)
  framework.registerProtocol(broadcast)
  framework.registerProtocol(membership)

  app.init(props)
  antiEntropy.init(props)
  broadcast.init(props)
  membership.init(props)

  framework.start()
]]></artwork>
      </section>
    </section>
    <section anchor="api">
      <name>Common Interfaces</name>
      <t>As described in previous sections, protocols interact with each other through inter-process events. While a simple program may only require a protocol to describe its logic, more complex and realistic applications combine multiple protocols and model complex inter-protocol interactions (i.e., an application supporting decentralized storage requires membership management, efficient propagation, authentication, etc.).</t>
      <t>While this approach presents great modularity, since an application is modelled as a set of protocols in charge of different aspects of its broader logic, handling inter-protocol interactions concisely and consistently may prove to be difficult.</t>
      <t>Following the literature, it is possible to see that, although different protocols have distinct designs and implementations, at a higher level, could aim to offer similar functionalities to the user. For example, overlay network protocols, create an abstraction layer (the "overlay") on top of an existing network infrastructure, and are divided into structured and unstructured overlays. For instance, Chord <xref target="Chord"/> and Kademlia <xref target="Kademlia"/> are structured overlay protocols that provide efficient and predictable lookups of data and nodes. On one hand, Chord uses consistent hashing to map keys to nodes in a circular fashion while Kademlia uses a XOR-based distance metric and a recursive lookup mechanism for finding nodes efficiently, but, at a higher level, both support operations for insertion, deletion and lookup of information, and hence a similar interface.</t>
      <t>With this in mind, we propose the creation of families or groups of protocols, that, although possess diverse internal logic and design, offer similar functionalities and thus can be englobed in the same category. Protocols in the same family should implement the same API, enabling high modularity and interoperability between protocols. In this fashion, even if an application swaps a protocol for another in the same family, the way of communication between protocols remains the same.</t>
      <section anchor="families">
        <name>Families</name>
        <t>As mentioned previously, while different protocols have unique implementations, when we focus on the external view that they provide to users -the API- they can be relatively similar.</t>
        <t>Protocols can be "stacked" on top of each other to create layers of abstractions. For instance, a storage protocol can interact with a dissemination protocol to transmit data, and the dissemination protocol propagates data to a subset of neighbours it receives from a membership protocol. In this manner, each protocol is only focused on the interaction with other protocols from the "layer" beneath it, which forms a much simpler interaction model.</t>
        <t>Even though this area is still a work in progress, there <bcp14>SHOULD</bcp14> be a specification of the different families and groups implemented inside the framework, with the use of already established common data types <xref target="RFC6991"/>. In this section, we will describe a proof of concept of such functionality which will be extended in the future.
At the moment of writing this draft, we propose three distinct protocol families:</t>
        <ul spacing="normal">
          <li>
            <t><strong>membership</strong>: Membership protocols are responsible for managing and maintaining the membership of a group of nodes that participate in the system. In other words, these protocols track which nodes are currently part of the system and make decisions based on the state of these nodes (whether they are up, down, joining, leaving, etc.). A common API for this family of protocols should have events for requesting information on the membership layer regarding other neighbours, for notifying protocols when nodes join and leave the system, etc.</t>
          </li>
          <li>
            <t><strong>dissemination</strong>: Dissemination protocols are designed to propagate information or updates efficiently across nodes in the system. The goal is to distribute data (e.g., state updates, configuration changes, etc.) to all or a subset of nodes within the system, ensuring that the information reaches its intended recipients in a timely and reliable manner. Not all dissemination protocols have the same semantics, for instance, a flood broadcast protocol transmits data to every node it knows, while a gossip-based protocol only disseminates data to a randomly sampled subset of nodes. Still, since all of them provide similar functionalities and in the end aim to reach the same goal, a common API should have events for dissemination of data, receiving data, etc.</t>
          </li>
          <li>
            <t><strong>storage</strong>: Storage protocols are designed to manage how data is stored, accessed, and maintained within a system. Their primary functionality is to ensure that data is stored and that it can be accessed reliably by applications or other users, even in the presence of failures, network issues, or node crashes. These storage protocols could be implementing storage solutions deployed directly on the network (i.e., decentralized storage solutions) or serve as a gateway to communicate with external storage deployments (e.g., a node uses a Cassandra <xref target="Cassandra"/> instance running off-site to store data). A common API for storage protocols should include essential methods like storing data, retrieving data, replication management, handling failures, reconfiguring namespaces, etc.</t>
          </li>
        </ul>
        <t>By defining each family and a set of common APIs, when writing protocols, developers match a protocol with a respective family and use the pre-defined events of each family to describe the interaction with the different protocols.</t>
      </section>
      <section anchor="usage">
        <name>Usage</name>
        <t>When writing an application using the framework, the developer can use an arbitrary number of protocols to achieve such a objective. The different protocols communicate with each other through events to compose a complex application. For instance, if we are building a decentralized storage system when the storage layer receives an operation from the application to write a data item, the protocol will create an event to a protocol on the dissemination layer to propagate such information to other nodes in the system. This design allows developers to build complex dynamic and decentralized systems in a modular and efficient way, and can even pave the way for experts in the area to write protocols that can be used by other less-experienced developers.</t>
        <t><xref target="appendixA"/> specifies a small set of common interfaces for the different families presented above. In the example below we showcase a sample example composing these ideas:</t>
        <artwork><![CDATA[
                      EagerGossipProtocol

init(properties):
  ...
  this.neighbors = Set()
  this.fanout = properties.fanout

  registerRequestHandler(DisseminationRequest, uponBroadcastRequest)

  registerReplyHandler(GetNeighborsSampleReply, uponNeighborsSampleReply)

  subscribeNotification(GetNeighborDownNotification, uponNeighborDown)
  ...

uponDisseminationRequest(DisseminationRequest: request, Protocol: sourceProto):
  msg = DisseminationMessage(request.payload, request.timestamp, 0)

  peers = this.neighbors.randomSubSet(this.fanout)
  for p in peers:
    sendMessage(msg, p)

uponNeighborsSampleReply(GetNeighborsSampleReply: reply):
  this.neighbors.addAll(reply.sample)

uponNeighborDown(GetNeighborDownNotification: notification):
  this.neighbors.remove(notification.peer)
]]></artwork>
        <artwork><![CDATA[
                      FloodBroadcastProtocol

init(properties):
  ...
  this.neighbors = Set()

  registerRequestHandler(DisseminationRequest, uponDisseminationRequest)

  registerReplyHandler(GetNeighborsSampleReply, uponNeighborsSampleReply)

  subscribeNotification(GetNeighborDownNotification, uponNeighborDown)
  ...

uponDisseminationRequest(DisseminationRequest: request, Protocol: sourceProto):
  msg = DisseminationMessage(request.payload, request.timestamp, 0)
  for p in neighbors:
    sendMessage(msg, p)

uponNeighborsSampleReply(GetNeighborsSampleReply: reply)
  this.neighbors.addAll(reply.sample)

uponNeighborDown(GetNeighborDownNotification: notification)
  this.neighbors.remove(notification.peer)
]]></artwork>
        <artwork><![CDATA[
                      FullMembershipProtocol
init(properties):
  ...
  registerDiscoveryHandler(uponDiscovery)

  registerRequestHandler(GetNeighborsSampleRequest, uponNeighborsSampleRequest)
  ...

uponNeighborsSampleRequest(GetNeighborsSampleRequest: request, Protocol: sourceProto):
  int sampleSize = request.sampleSize
  sample = this.neighbors.randomSubSet(sampleSize)

  reply = GetNeighborsSampleReply(sample)
  sendReply(reply, sourceProto)

uponDiscovery(DiscoveryNotification: notification):
  this.neighbors.add(event.peer)
]]></artwork>
        <t>In this example, it's possible to see two dissemination protocols (<em>EagerGossipProtocol</em> and <em>FloodBroadcastProtocol</em>) and a membership protocol (<em>FullMembershipProtocol</em>). The FullMembershipProtocol protocol offers an abstraction to obtain the node's membership, and, both dissemination protocols, although having different design choices regarding the way data is propagated, use the same API provided by the "bottom layer". This way, if an application wishes to change its dissemination protocol, it can easily do so by just registering different protocols during initialization.</t>
      </section>
      <section anchor="remarks">
        <name>Remarks</name>
        <t>At its core, the framework aims to provide a consistent set of functionalities to protocols that adhere to a common interface design. While following this design is recommended for modularity and interoperability, it is not mandatory. Not all protocols necessarily fit into a predefined category or family, and developers have the flexibility to define their own interface specifications.</t>
        <t>When implementing protocols, developers can design custom inter-protocol communication events (e.g., requests, notifications) tailored to their specific application needs. Although adopting the common interface design promotes high modularity and decouples implementation from interaction, developers are ultimately free to choose the approach that best suits their use case.</t>
      </section>
    </section>
    <section anchor="examples">
      <name>Examples</name>
      <t>In this section, we provide a full-fledged example of the framework. The example contains the initialization of the framework with the due protocols, their implementation and the respective events. We leverage the common API presented in <xref target="api"/> to present a generic example.</t>
      <t>The example showcases a message dissemination application which takes input from the user, and disseminates data through a network of nodes, as depicted in the following diagram:</t>
      <artwork><![CDATA[
                            +--------------+
                            |              |
                            | Application  |
                            |              |
                            +--------------+
                                |     ^
                                |     |
                                v     |
                            +--------------+
                            |              |
                            | Eager Gossip |
                            |              |
                            +--------------+
                                |     ^
                                |     |
                                v     |
                            +--------------+
                            |              |
                            |  Membership  |
                            |              |
                            +--------------+
]]></artwork>
      <t>Figure 12: Protocols interaction diagram</t>
      <section anchor="pseudocode">
        <name>Pseudocode</name>
        <artwork><![CDATA[
                              Main

main(config):
  framework = GFDS.newInstance()
  props = framework.loadConfig(config)

  discoveryMethods = {multicast}
  framework.registerDiscoveryMethods(discoveryMethods)

  selfConfigMethod =  {copyValidate}
  framework.registerSelfConfigurationMethods(selfConfigMethod)

  resourceMethods =  {periodically}
  framework.registerResourceMethods(resourceMethods)

  adaptiveMethod =  {localMetrics}
  framework.registerAdaptiveMethods(adaptiveMethod)

  app = MessageApplication()
  dissemination = EagerGossipProtocol()
  membership = FullMembershipProtocol()

  framework.registerProtocol(app)
  framework.registerProtocol(dissemination)
  framework.registerProtocol(membership)

  app.init(props)
  dissemination.init(props)
  membership.init(props)

  framework.start()
]]></artwork>
        <artwork><![CDATA[
                              Application

//Events
def OperationTimer {
  long timeout
}

init(props):
    this.disseminationProtocol = props.disseminationProtocol

    registerNotificationHandler(DeliveryNotification, uponDeliveryNotification)
    registerTimerHandler(OperationTimer, uponOperationTimer)

    setupPeriodicTimer( OperationTimer(props.period), props.firstTimer, props.period)

uponOperationTimer(OperationTimer: timer):
  in = input("Insert message:")
  request = DisseminationRequest(myself, in, Time.now())
  sendRequest(request, this.disseminationProtocol)

uponDeliveryNotification(DeliveryNotification: notification):
  log("Message received! Data: {}", notification.payload)
]]></artwork>
        <t>The pseudo code for the EagerGossip and FullMembership protocols can be found in <xref target="appendixC"/>.</t>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>This document defines the concept of secure transports to facilitate secure communication between nodes. Secure transports leverage security primitives provided by the framework, in conjunction with identity management.</t>
      <t>For security primitives, secure transport implementations can rely on well-established cryptographic algorithms and cryptosystems. We recommend that any framework implementation utilize proven, widely accepted cryptographic libraries, as outlined in <xref target="RFC9641"/> and <xref target="RFC9642"/>. However, for specialized use cases, the framework should also support protocols that do not require secure communication and, therefore, do not adhere to these security considerations.</t>
      <t>Identity management data should be stored in secure memory or persistent storage to protect against malicious attacks that could compromise a node's identity or lead to impersonation.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
    <section anchor="implementation-status">
      <name>Implementation Status</name>
      <t>At the moment of writing this draft, we have a reference implementation following the ideas presented in this document. <eref target="https://codelab.fct.unl.pt/di/research/tardis/wp6/babel-swarm/babel-core-swarm">Babel</eref> is a Java framework for easing the complexity of building and managing distributed systems. The framework is an active research effort, and it's being continuously updated to support more features and compliance with GFDS.
The <eref target="https://codelab.fct.unl.pt/di/research/tardis/wp6/babel-swarm/babel-protocolcommons">Common APIs</eref> repository materializes the design presented in <xref target="api"/>, and a list of applications is available in the following <eref target="https://codelab.fct.unl.pt/di/research/tardis/wp6/babel-swarm/applications">repository</eref>.</t>
      <t>Moreover, <eref target="https://codelab.fct.unl.pt/di/research/tardis/wp6/micro-babel">MicroBabel</eref> is a lightweight framework written in C, designed specifically for small embedded devices (e.g., microcontrollers). Although still under active development, it is continuously evolving to ensure compliance with the paradigm outlined in this document.</t>
    </section>
    <section anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>This work was partly funded by EU Horizon Europe under Grant Agreement no. 101093006 (TaRDIS) and FCT-Portugal under grant UIDB/04516/2020.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC7575">
          <front>
            <title>Autonomic Networking: Definitions and Design Goals</title>
            <author fullname="M. Behringer" initials="M." surname="Behringer"/>
            <author fullname="M. Pritikin" initials="M." surname="Pritikin"/>
            <author fullname="S. Bjarnason" initials="S." surname="Bjarnason"/>
            <author fullname="A. Clemm" initials="A." surname="Clemm"/>
            <author fullname="B. Carpenter" initials="B." surname="Carpenter"/>
            <author fullname="S. Jiang" initials="S." surname="Jiang"/>
            <author fullname="L. Ciavaglia" initials="L." surname="Ciavaglia"/>
            <date month="June" year="2015"/>
            <abstract>
              <t>Autonomic systems were first described in 2001. The fundamental goal is self-management, including self-configuration, self-optimization, self-healing, and self-protection. This is achieved by an autonomic function having minimal dependencies on human administrators or centralized management systems. It usually implies distribution across network elements.</t>
              <t>This document defines common language and outlines design goals (and what are not design goals) for autonomic functions. A high-level reference model illustrates how functional elements in an Autonomic Network interact. This document is a product of the IRTF's Network Management Research Group.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="7575"/>
          <seriesInfo name="DOI" value="10.17487/RFC7575"/>
        </reference>
        <reference anchor="RFC8922">
          <front>
            <title>A Survey of the Interaction between Security Protocols and Transport Services</title>
            <author fullname="T. Enghardt" initials="T." surname="Enghardt"/>
            <author fullname="T. Pauly" initials="T." surname="Pauly"/>
            <author fullname="C. Perkins" initials="C." surname="Perkins"/>
            <author fullname="K. Rose" initials="K." surname="Rose"/>
            <author fullname="C. Wood" initials="C." surname="Wood"/>
            <date month="October" year="2020"/>
            <abstract>
              <t>This document provides a survey of commonly used or notable network security protocols, with a focus on how they interact and integrate with applications and transport protocols. Its goal is to supplement efforts to define and catalog Transport Services by describing the interfaces required to add security protocols. This survey is not limited to protocols developed within the scope or context of the IETF, and those included represent a superset of features a Transport Services system may need to support.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8922"/>
          <seriesInfo name="DOI" value="10.17487/RFC8922"/>
        </reference>
        <reference anchor="I-D.irtf-nmrg-ai-challenges-04">
          <front>
            <title>Research Challenges in Coupling Artificial Intelligence and Network Management</title>
            <author fullname="Jérôme François" initials="J." surname="François">
              <organization>University of Luxembourg and Inria</organization>
            </author>
            <author fullname="Alexander Clemm" initials="A." surname="Clemm">
              <organization>Independent</organization>
            </author>
            <author fullname="Dimitri Papadimitriou" initials="D." surname="Papadimitriou">
              <organization>3NLab Belgium Reseach Center</organization>
            </author>
            <author fullname="Stenio Fernandes" initials="S." surname="Fernandes">
              <organization>Central Bank of Canada</organization>
            </author>
            <author fullname="Stefan Schneider" initials="S." surname="Schneider">
              <organization>Digital Railway (DSD) at Deutsche Bahn</organization>
            </author>
            <date day="28" month="November" year="2024"/>
            <abstract>
              <t>   This document is intended to introduce the challenges to overcome
   when Network Management (NM) problems may require coupling with
   Artificial Intelligence (AI) solutions.  On the one hand, there are
   many difficult problems in NM that to this date have no good
   solutions, or where any solutions come with significant limitations
   and constraints.  Artificial Intelligence may help produce novel
   solutions to those problems.  On the other hand, for several reasons
   (computational costs of AI solutions, privacy of data), distribution
   of AI tasks became primordial.  It is thus also expected that network
   are operated efficiently to support those tasks.

   To identify the right set of challenges, the document defines a
   method based on the evolution and nature of NM problems.  This will
   be done in parallel with advances and the nature of existing
   solutions in AI in order to highlight where AI and NM have been
   already coupled together or could benefit from a higher integration.
   So, the method aims at evaluating the gap between NM problems and AI
   solutions.  Challenges are derived accordingly, assuming solving
   these challenges will help to reduce the gap between NM and AI.

   This document is a product of the Network Management Research Group
   (NMRG) of the Internet Research Task Force (IRTF).  This document
   reflects the consensus of the research group.  It is not a candidate
   for any level of Internet Standard and is published for informational
   purposes.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-nmrg-ai-challenges-04"/>
        </reference>
        <reference anchor="RFC9642">
          <front>
            <title>A YANG Data Model for a Keystore</title>
            <author fullname="K. Watsen" initials="K." surname="Watsen"/>
            <date month="October" year="2024"/>
            <abstract>
              <t>This document presents a YANG module called "ietf-keystore" that enables centralized configuration of both symmetric and asymmetric keys. The secret value for both key types may be encrypted or hidden. Asymmetric keys may be associated with certificates. Notifications are sent when certificates are about to expire.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9642"/>
          <seriesInfo name="DOI" value="10.17487/RFC9642"/>
        </reference>
        <reference anchor="RFC9641">
          <front>
            <title>A YANG Data Model for a Truststore</title>
            <author fullname="K. Watsen" initials="K." surname="Watsen"/>
            <date month="October" year="2024"/>
            <abstract>
              <t>This document presents a YANG module for configuring bags of certificates and bags of public keys that can be referenced by other data models for trust. Notifications are sent when certificates are about to expire.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9641"/>
          <seriesInfo name="DOI" value="10.17487/RFC9641"/>
        </reference>
        <reference anchor="RFC6241">
          <front>
            <title>Network Configuration Protocol (NETCONF)</title>
            <author fullname="R. Enns" initials="R." role="editor" surname="Enns"/>
            <author fullname="M. Bjorklund" initials="M." role="editor" surname="Bjorklund"/>
            <author fullname="J. Schoenwaelder" initials="J." role="editor" surname="Schoenwaelder"/>
            <author fullname="A. Bierman" initials="A." role="editor" surname="Bierman"/>
            <date month="June" year="2011"/>
            <abstract>
              <t>The Network Configuration Protocol (NETCONF) defined in this document provides mechanisms to install, manipulate, and delete the configuration of network devices. It uses an Extensible Markup Language (XML)-based data encoding for the configuration data as well as the protocol messages. The NETCONF protocol operations are realized as remote procedure calls (RPCs). This document obsoletes RFC 4741. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6241"/>
          <seriesInfo name="DOI" value="10.17487/RFC6241"/>
        </reference>
        <reference anchor="RFC6991">
          <front>
            <title>Common YANG Data Types</title>
            <author fullname="J. Schoenwaelder" initials="J." role="editor" surname="Schoenwaelder"/>
            <date month="July" year="2013"/>
            <abstract>
              <t>This document introduces a collection of common data types to be used with the YANG data modeling language. This document obsoletes RFC 6021.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6991"/>
          <seriesInfo name="DOI" value="10.17487/RFC6991"/>
        </reference>
        <reference anchor="multiaddress" target="https://github.com/multiformats/multiaddr">
          <front>
            <title>multiaddress</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="RFC791">
          <front>
            <title>Internet Protocol</title>
            <author fullname="J. Postel" initials="J." surname="Postel"/>
            <date month="September" year="1981"/>
          </front>
          <seriesInfo name="STD" value="5"/>
          <seriesInfo name="RFC" value="791"/>
          <seriesInfo name="DOI" value="10.17487/RFC0791"/>
        </reference>
        <reference anchor="RFC9293">
          <front>
            <title>Transmission Control Protocol (TCP)</title>
            <author fullname="W. Eddy" initials="W." role="editor" surname="Eddy"/>
            <date month="August" year="2022"/>
            <abstract>
              <t>This document specifies the Transmission Control Protocol (TCP). TCP is an important transport-layer protocol in the Internet protocol stack, and it has continuously evolved over decades of use and growth of the Internet. Over this time, a number of changes have been made to TCP as it was specified in RFC 793, though these have only been documented in a piecemeal fashion. This document collects and brings those changes together with the protocol specification from RFC 793. This document obsoletes RFC 793, as well as RFCs 879, 2873, 6093, 6429, 6528, and 6691 that updated parts of RFC 793. It updates RFCs 1011 and 1122, and it should be considered as a replacement for the portions of those documents dealing with TCP requirements. It also updates RFC 5961 by adding a small clarification in reset handling while in the SYN-RECEIVED state. The TCP header control bits from RFC 793 have also been updated based on RFC 3168.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="7"/>
          <seriesInfo name="RFC" value="9293"/>
          <seriesInfo name="DOI" value="10.17487/RFC9293"/>
        </reference>
        <reference anchor="RFC768">
          <front>
            <title>User Datagram Protocol</title>
            <author fullname="J. Postel" initials="J." surname="Postel"/>
            <date month="August" year="1980"/>
          </front>
          <seriesInfo name="STD" value="6"/>
          <seriesInfo name="RFC" value="768"/>
          <seriesInfo name="DOI" value="10.17487/RFC0768"/>
        </reference>
        <reference anchor="RFC6762">
          <front>
            <title>Multicast DNS</title>
            <author fullname="S. Cheshire" initials="S." surname="Cheshire"/>
            <author fullname="M. Krochmal" initials="M." surname="Krochmal"/>
            <date month="February" year="2013"/>
            <abstract>
              <t>As networked devices become smaller, more portable, and more ubiquitous, the ability to operate with less configured infrastructure is increasingly important. In particular, the ability to look up DNS resource record data types (including, but not limited to, host names) in the absence of a conventional managed DNS server is useful.</t>
              <t>Multicast DNS (mDNS) provides the ability to perform DNS-like operations on the local link in the absence of any conventional Unicast DNS server. In addition, Multicast DNS designates a portion of the DNS namespace to be free for local use, without the need to pay any annual fee, and without the need to set up delegations or otherwise configure a conventional DNS server to answer for those names.</t>
              <t>The primary benefits of Multicast DNS names are that (i) they require little or no administration or configuration to set them up, (ii) they work when no infrastructure is present, and (iii) they work during infrastructure failures.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6762"/>
          <seriesInfo name="DOI" value="10.17487/RFC6762"/>
        </reference>
        <reference anchor="RFC8017">
          <front>
            <title>PKCS #1: RSA Cryptography Specifications Version 2.2</title>
            <author fullname="K. Moriarty" initials="K." role="editor" surname="Moriarty"/>
            <author fullname="B. Kaliski" initials="B." surname="Kaliski"/>
            <author fullname="J. Jonsson" initials="J." surname="Jonsson"/>
            <author fullname="A. Rusch" initials="A." surname="Rusch"/>
            <date month="November" year="2016"/>
            <abstract>
              <t>This document provides recommendations for the implementation of public-key cryptography based on the RSA algorithm, covering cryptographic primitives, encryption schemes, signature schemes with appendix, and ASN.1 syntax for representing keys and for identifying the schemes.</t>
              <t>This document represents a republication of PKCS #1 v2.2 from RSA Laboratories' Public-Key Cryptography Standards (PKCS) series. By publishing this RFC, change control is transferred to the IETF.</t>
              <t>This document also obsoletes RFC 3447.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8017"/>
          <seriesInfo name="DOI" value="10.17487/RFC8017"/>
        </reference>
        <reference anchor="RFC9000">
          <front>
            <title>QUIC: A UDP-Based Multiplexed and Secure Transport</title>
            <author fullname="J. Iyengar" initials="J." role="editor" surname="Iyengar"/>
            <author fullname="M. Thomson" initials="M." role="editor" surname="Thomson"/>
            <date month="May" year="2021"/>
            <abstract>
              <t>This document defines the core of the QUIC transport protocol. QUIC provides applications with flow-controlled streams for structured communication, low-latency connection establishment, and network path migration. QUIC includes security measures that ensure confidentiality, integrity, and availability in a range of deployment circumstances. Accompanying documents describe the integration of TLS for key negotiation, loss detection, and an exemplary congestion control algorithm.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9000"/>
          <seriesInfo name="DOI" value="10.17487/RFC9000"/>
        </reference>
        <reference anchor="RFC7668">
          <front>
            <title>IPv6 over BLUETOOTH(R) Low Energy</title>
            <author fullname="J. Nieminen" initials="J." surname="Nieminen"/>
            <author fullname="T. Savolainen" initials="T." surname="Savolainen"/>
            <author fullname="M. Isomaki" initials="M." surname="Isomaki"/>
            <author fullname="B. Patil" initials="B." surname="Patil"/>
            <author fullname="Z. Shelby" initials="Z." surname="Shelby"/>
            <author fullname="C. Gomez" initials="C." surname="Gomez"/>
            <date month="October" year="2015"/>
            <abstract>
              <t>Bluetooth Smart is the brand name for the Bluetooth low energy feature in the Bluetooth specification defined by the Bluetooth Special Interest Group. The standard Bluetooth radio has been widely implemented and available in mobile phones, notebook computers, audio headsets, and many other devices. The low-power version of Bluetooth is a specification that enables the use of this air interface with devices such as sensors, smart meters, appliances, etc. The low-power variant of Bluetooth has been standardized since revision 4.0 of the Bluetooth specifications, although version 4.1 or newer is required for IPv6. This document describes how IPv6 is transported over Bluetooth low energy using IPv6 over Low-power Wireless Personal Area Network (6LoWPAN) techniques.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="7668"/>
          <seriesInfo name="DOI" value="10.17487/RFC7668"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="Lib2p" target="https://libp2p.io">
          <front>
            <title>Lib2p</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="PeerSim" target="https://peersim.sourceforge.net">
          <front>
            <title>PeerSim</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="Cassandra" target="https://cassandra.apache.org/_/index.html">
          <front>
            <title>Cassandra</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="Authentication_Survey">
          <front>
            <title>Authentication in Peer-to-Peer Network: Survey and Research Directions</title>
            <author fullname="Zhongwen Li" initials="Z." surname="Li">
              <organization/>
            </author>
            <author fullname="Xiaochen Xu" initials="X." surname="Xu">
              <organization/>
            </author>
            <author fullname="Liang Shi" initials="L." surname="Shi">
              <organization/>
            </author>
            <author fullname="Jian Liu" initials="J." surname="Liu">
              <organization/>
            </author>
            <author fullname="Chen Liang" initials="C." surname="Liang">
              <organization/>
            </author>
            <date year="2009"/>
          </front>
          <seriesInfo name="2009 Third International Conference on Network and System Security" value="pp. 115-122"/>
          <seriesInfo name="DOI" value="10.1109/nss.2009.30"/>
          <refcontent>IEEE</refcontent>
        </reference>
        <reference anchor="Chord">
          <front>
            <title>Chord: A scalable peer-to-peer lookup service for internet applications</title>
            <author fullname="Ion Stoica" initials="I." surname="Stoica">
              <organization>University of California, Berkeley</organization>
            </author>
            <author fullname="Robert Morris" initials="R." surname="Morris">
              <organization>MIT Laboratory for Computer Science</organization>
            </author>
            <author fullname="David Karger" initials="D." surname="Karger">
              <organization>MIT Laboratory for Computer Science</organization>
            </author>
            <author fullname="M. Frans Kaashoek" initials="M." surname="Kaashoek">
              <organization>MIT Laboratory for Computer Science</organization>
            </author>
            <author fullname="Hari Balakrishnan" initials="H." surname="Balakrishnan">
              <organization>MIT Laboratory for Computer Science</organization>
            </author>
            <date month="August" year="2001"/>
          </front>
          <seriesInfo name="ACM SIGCOMM Computer Communication Review" value="vol. 31, no. 4, pp. 149-160"/>
          <seriesInfo name="DOI" value="10.1145/964723.383071"/>
          <refcontent>Association for Computing Machinery (ACM)</refcontent>
        </reference>
        <reference anchor="Kademlia">
          <front>
            <title>*** BROKEN REFERENCE ***</title>
            <author>
              <organization/>
            </author>
            <date/>
          </front>
        </reference>
      </references>
    </references>
    <?line 1849?>

<section anchor="appendixA">
      <name>APIs</name>
      <t>The pseudo-code in this section describes a sample example of the common APIs mentioned in <xref target="api"/>.</t>
      <artwork><![CDATA[
                          Storage Layer APIs

// Requests
def ExecuteRequest {
  string nameSpace,
  Operation op // Data, operation type, etc.
}

def ModifyNamespaceRequest {
  string nameSpace,
  NameSpaceConfig config //Parameters to be modified
}

// Replies
def ExecuteJSONReply{
  string jsonAsString,
  Status statusCode
}

def ExecutePayloadReply {
  byte [] payload,
  Status statusCode
}

def ModifyNamespaceReply {
  string nameSpace,
  Status statusCode
}

// Notifications
def JSONDataNotification {
  string jsonAsString,
  Status statusCode
}

def PayloadNotification {
  byte [] payload,
  Status statusCode
}

// Timers
def PersistTimer {
  long periodicTimeout
}
]]></artwork>
      <artwork><![CDATA[
                          Dissemination Layer APIs

// Requests
def DisseminationRequest {
  Peer sender,
  byte [] payload,
  long timestamp
}

def MissingDataRequest {
  UUID uniqueID,
  Peer destination
}

// Notifications
def DeliveryNotification {
  byte [] payload,
  long timestamp
}

def DataFoundNotification{
  byte [] payload,
  UUID uniqueID,
}

// Messages
def DisseminationMessage {
  byte [] data,
  long timestamp,
  short ttl

  serializer(out):
    out.writeByteArray(data)
    out.writeLong(timestamp)
    out.writeShort(ttl)

  deserializer(in):
    data = in.readByteArray()
    timestamp = in.readLong(in)
    ttl = in.readShort(ttl)
    return DisseminationMessage(data, timestamp, ttl)
}
]]></artwork>
      <artwork><![CDATA[
                          Membership Layer APIs

// Requests
def GetNeighborsSampleRequest {
  int sampleSize
}

// Replies
def GetNeighborsSampleReply {
  Set<Peer> neighbors
}

// Notifications
def NeighborUpNotification {
  Peer peer
}

def NeighborDownNotification {
  Peer peer
}
]]></artwork>
    </section>
    <section anchor="appendixB">
      <name>Control Events</name>
      <artwork><![CDATA[
                        Discovery Events

def RequestProbe {
  string serviceName
}

def RequestAnnouncement {
  string serviceName,
  Peer provider,
}

def DiscoveryNotification {
  string serviceName,
  Peer [] peers,
}
]]></artwork>
      <artwork><![CDATA[
                        Configuration Events

def SelfConfigParameters {
   string configMethod,
   Map<Parameter, Config> parameters,
}

def AdaptiveParameters {
  string adaptiveMethod,
  Map<Parameter, Config> parameters,
}
]]></artwork>
      <artwork><![CDATA[
                        Resource Events

def ResourceSample {
  string resourceType,     // e.g., CPU, Memory, Bandwidth
  string unit,             // e.g., KPBs, MB, etc.
  string value,
  float usagePercent,
}

def ResourceLimitWarningNotification {
  string resourceType,
  float usagePercent,
  string message
}
]]></artwork>
      <artwork><![CDATA[
                        Transport Events

def TransportAvailableNotification {
  Transport transport,
  Throwable cause,
  string message
}

def TransportUnavailableNotification {
  Transport transport,
  Throwable cause,
  string message
}

def TransportConflict {
  Transport transport,
  Throwable cause,
  string message,
}
]]></artwork>
      <artwork><![CDATA[
                        Connection Events

def ConnectionUpNotification {
  Transport transport,
  Peer peer,
}

def ConnectionDownNotification {
  Transport transport,
  Peer peer,
  Throwable cause,
  string message,
}

def ConnectionErrorNotification {
  Transport transport,
  Throwable cause,
  string message,
}

def ConnectionTimeout {
  Transport transport,
  string message,
}
]]></artwork>
    </section>
    <section anchor="appendixC">
      <name>Examples</name>
      <artwork><![CDATA[
                      EagerGossipProtocol


state = {
  this.neighbors: Set<Peer>,
  this.dataSet : Set<DisseminationMessage>,

  @AutoConfigurable
  @Adaptive
  long fanout,
}

/*
This is a simple and pragmatic implementation
of a eager push gossip-based broadcast protocol.
The implementation assumes that there exists a
membership service that uses the interface made
available in commons API.
*/
init(properties):
  this.dataSet = Set<DisseminationMessage>()
  this.neighbors = Set<Peer>()
  //fanout will be setup by the framework

  registerSelfConfiguration(properties, uponSelfConfig)

  registerAdaptiveConfiguration(properties, uponAdaptive)

  preferences = {reliable}
  registerCommunicationPreferences(preferences)

  registerRequestHandler(DisseminationRequest, uponBroadcastRequest)

  registerReplyHandler(GetNeighborsSampleReply, uponNeighborsSampleReply)

  subscribeNotification(GetNeighborDownNotification, uponNeighborDown)

  registerTimerHandler(GarbageCollectionTimer, uponGarbageCollectionTimer)
  setupPeriodicTimer(GarbageCollectionTimer(properties.interval), uponGarbageCollectionTimer)

  registerCommunicationHandler(DisseminationMessage, uponDisseminationMessage)

// Request/Reply Handlers
uponDisseminationRequest(DisseminationRequest: request, Protocol: sourceProto):
  msg = DisseminationMessage(request.payload, request.timestamp, 0)
  deliver(msg)
  peers = this.neighbors.randomSubSet(this.fanout)
  propagate(peers, msg)

uponNeighborsSampleReply(GetNeighborsSampleReply: reply)
  this.neighbors.addAll(reply.sample)

// Notification Handlers
uponNeighborDown(GetNeighborDownNotification: notification)
  this.neighbors.remove(notification.peer)

// Timer Handlers
uponGarbageCollectionTimer(GarbageCollectionTimer: timer):
  this.dataSet.removeIf(data -> Time.now - data.timestamp >
                    timer.interval && data.ttl >= state.ttl)


// Configuration and Adaptive
uponSelfConfig(SelfConfigParameters selfConfig):
 for p in state as AutoConfigurable:
  p = selfConfig.parameters.get(p)

uponAdaptive(SelfConfigParameters adaptive):
 for p in state as Adaptive:
  p = adaptive.parameters.get(p)

// Communication Handlers
uponDisseminationMessage(DisseminationMessage: msg, Peer: sender):
  msg.ttl++
  deliver(msg)

  peers = this.neighbors.randomSubSet(this.fanout)
  propagate(peers, msg)


// Procedures
deliver(DisseminationMessage: msg):
  if(!this.dataSet.contains(msg)):
    this.dataSet.add(msg)

    notification = DeliveryNotification(msg.data)
    triggerNotification(notification)

propagate(Set<Peer> destinations, DisseminationMessage: msg):
  destinations.forEach(n -> sendMessage(msg,n))
]]></artwork>
      <artwork><![CDATA[
                      FullMembershipProtocol

/*
This is a membership protocol that should only be used
either on very small scale settings or
for testing purposes. It creates a global
membership abstraction where every single node in
the system knows every other node (except himself).
/*
init(properties):
  this.neighbors = Set<Peer>()

  registerDiscoveryHandler(uponDiscovery)

  resources = {SYSTEM_NETWORK_WRITE_BYTES,SYSTEM_NETWORK_READ_BYTES}
  registerResourceMonitor(resources, uponResourceSample)

  //This is a simple protocol, so it doesn't have self configuration or adaptive parameters

  registerCommunicationPreferences({reliable, connectionOriented})

  registerRequestHandler(GetNeighborsSampleRequest, uponNeighborsSampleRequest)
  subscribeNotification(ConnectionFailedNotification, uponConnectionFailed)

uponNeighborsSampleRequest(GetNeighborsSampleRequest: request, Protocol: sourceProto):
  int sampleSize = request.sampleSize
  sample = this.neighbors.randomSubSet(sampleSize)

  reply = GetNeighborsSampleReply(sample)
  sendReply(reply, sourceProto)

uponDiscovery(DiscoveryNotification: notification):
  this.neighbors.add(event.peer)

uponResourceSample(ResourceEvent sample):
  file.append("Resource Sample: {} {}", sample.resourceType, sample.usage)

uponResourceLimitWarning(ResourceLimitWarning warning):
  log.warn("Resource {} Limit Warning, take action", warning.resourceType)
  if(warning.resourceType == SYSTEM_NETWORK_WRITE_BYTES)
    this.neighbors.removeRandom()


uponConnectionFailed(ConnectionFailedNotification: notification)
  this.neighbors.remove(notification.peer)

  triggerNotification(NeighborDown(notification.peer))
]]></artwork>
    </section>
    <section anchor="contributors" numbered="false" toc="include" removeInRFC="false">
      <name>Contributors</name>
      <contact initials="R." surname="Matos" fullname="Rafael Matos">
        <organization>TaRDIS</organization>
        <address>
          <postal>
            <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
          </postal>
          <email>rd.matos@campus.fct.unl.pt</email>
        </address>
      </contact>
      <contact initials="T." surname="Galvão" fullname="Tomas Galvão">
        <organization>TaRDIS</organization>
        <address>
          <postal>
            <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
          </postal>
          <email>t.galvao@campus.fct.unl.pt</email>
        </address>
      </contact>
      <contact initials="F." surname="Carmo" fullname="Felipe Carmo">
        <organization>TaRDIS</organization>
        <address>
          <postal>
            <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
          </postal>
          <email>fp.carmo@campus.fct.unl.pt</email>
        </address>
      </contact>
      <contact initials="J." surname="Bordalo" fullname="João Bordalo">
        <organization>TaRDIS</organization>
        <address>
          <postal>
            <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
          </postal>
          <email>j.bordalo@campus.fct.unl.pt</email>
        </address>
      </contact>
      <contact initials="J." surname="Brilha" fullname="João Brilha">
        <organization>TaRDIS</organization>
        <address>
          <postal>
            <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
          </postal>
          <email>j.brilha@campus.fct.unl.pt</email>
        </address>
      </contact>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+S9W5fbyJUu+M5fgZbXOk6mSOpS5bpku6o7S6mydSyV5EpV
1/Hq0/YCSZAJCwRoAFQWLalXv8/rvMzbrDX/ZOaf9C+ZfY3YEQCYlJRlT59h
u1VJEAjEZceOff32dDodtXlbZGfJnfPkN1mZ1fki+bZON9l1Vb9KVlWdfLPL
i2VerpOLfZlu4OeLbJGVbZ0W+V+zZXK5b9ps0yQnv/n24nJ8Z5TO53X2GtrD
73dGi7TN1lW9P0uadjkaLasFNAKvW9bpqp3+OWt2zXS9WjbT+w9GzW6+yZsm
r8p2v4V7njx++e1oVO4286w+Gy2hpbPk4f2Hv5re/2L68IvRoiqbrIQGzpK2
3mUjeCk08irbQ9eXZ6NkmiyDnjbcU/pBhpKVr/O6KjdwF11vrtMa7hilu/aq
qqmNhPt7kVfrKvnv2N9RAp+qXqdl/te0hd6eJS/T7y+eXNIPTVtnWXuWfPf8
X86Tp+m8qtMWxk9T+ajabHdtVieXizwrF1mSlsvkSQk/baChBUwiP/Xku0eX
Y2ot26R5AbOVzmiq/nm1aGe7sphtW9O3/179P/9XlTzN8hb++3fo3Z8XswJe
nla2e7A6bZ3Pd204j9+nqzQrkmfw2r/HRNbL2QZf/c+LFFpoZr3z+bLapE3y
m7R4/feZz3a2hnfDdB7q5LdZkW+z5BEQ7N+jj6vtbIGvPthHJsxvYDumxd+F
MGdzfvcxvazz4ir9+3SSXt3Tx1HJT7/OYAsl33/76PNfff6rs+QcNhXxr++y
Ftk0MGf++YsvHz48Sy539etsf5ktdnXe7l/Wadlsq7q9zOrX+SLDXfdkejHL
63Y1LTf1eprm08VVWhRZuc6AD396BmPZbQto9fyJvOFZWqbyji8/+/Thmfvz
gfz52UP4M4G7H1XlSi59+SVc+kNari/SNn0JHB1fvdkVbZ4ul3XWNGc0DdOz
4CJda9N6jRN91bbb5uzevXXeXu3ms0W1uUf38qw299yD/BSfZEFro1yXwE8i
9uvJCxnDwy8/gTV+JF8//+yLs+SHC/n22eefwXxuLr67lPm9/+BzYGGX5/Ls
/fv3z5Lf//DkkT6MT3/z9LHc/emnn0HTTy9H8P1pPn+4dQOmb70jLfL59uF2
lld2RHr7iyyrL/ONa0a+9za0hd+afDNrql29yGAO1tmszFrbrH/8Udo0QK91
6pp2V3obX+ivs3SbLq6yGTR/70/38nKZ/TS7ajeFfY1tCkj3Cg7bfEGbS0gV
TtfnT2YP7s8ePLj/5b3vLi9nD+/f/3L2yX3s2RUe5v6GT391D8ju84efzD75
4pP7nz+AW36XLrNNkafurl/B595nn372ySefzj774nNYtdFoNJ1Ok3QOOzhd
wMYaOakGt+kGyRu/XOXrq2LvxAP87SqDTV2tQTSqdk2/RJEs0jLZ1tXrLGmr
ZJ4lf9nlbZbopsKGlzv6DQafrOssbRMg5W2R/QQblN7SLNIiS6pV0uwWV4FY
Mhu9vMrhxdVih9+TZpst8lWeNUl6GwLbJLm+yuGV2J+qoVbrbJXVzMLqxRWM
ZNHuauZn2U/AVWjlNtUSjnF83TJ7nRXVtjOXMNYm0ymi18AIcZbypU71tMBn
3bJAuw3O0q4B0p3xkm3y5bLIRqNfJM9fIwPLrs3a9a9GjoOQ+aUu2YVo0+aV
XY28vMLBtsmu3NbZMl+06Twv+pdFXjBLXtqhwc9tViYojeZNizcTA4K3JyVM
EozoCtZ7k+6RMooKBeIlvDZZ5qsVv3qdVes63cI6pAXM/prmAV9fZnArdHRR
FQWfNvDWLN0UwNmATOEXnk+8yswdzi68Bn8ByQDbpb7Sq/IF9ApGVee4yvB+
t1Agcu/gUpG/gh4zv08KeFW52E9oCMkKDiogAVjF1/B8Oi9wIOkS2m1YxoMe
T+jVFYjvc+gaPQY/b4t0kRHdwhu3ad1iN9I6pHA4N2BtYTVwXJOQcNwc1Hhc
lrpD09fQJeoIzhN0bYvTDxsQWiqB1uAfYEY5zM0O5pSIu8R3AQVvYcsQdftR
8RaoM9i38D2pq/kOVnKVwozBq4sMjlA50JusWE2vshRPx2STAWWVebNBYv2R
6BuYYZ69JtqE2Vei4Kls9uXiCgYtksWEdxQoMDVvF6ASoFMhmqsUBoMNCHki
5SNtIc3y1OCMwg2dDZBcV7tiicRWZwWdezBfWdpADwzdA+uhfhF1h83sypyW
CwYHXJ8IGma+hf+nPZ7c4SOFelMDP7/DfBL+oVmBMYPkUfOYqY992xTXqNYd
Ms9ouCuQror9RNgILDJMSLkHVkMERLdA1/M6qa6BmIBHACvE8YXzMuHNuq5g
4YEVlBWsYQ2UkBazJOFV6uMac+ClKxj4qq42OF05iHJNizuONgoRMdHmHtrH
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
ZXO2LJL3I3vnX/nIruEL/9iJaULe9ym877eyyLbPdBzJDyff1FW6XKRNK9e5
5/HVsS6Vb2Vb7LWNC+jua7nGz9srnWdfItnqs79hcfoRS9MvmaKxiZ4fOi1d
KK1oa/jgC4rWyLfAf/SBEZxoc2Z435mjVp/6LsvXV/Oq/mFrf+Vu9P/W6Umw
LJ25fcbnZDS3clXawu2DbFxXzPJt3arAu93PTqFC4a0o5ihyKQOGg/3Cc9Zo
IwdaRHwG5k0oPun4tC0vAkUHWixTi2ERI1wk2EF72chpsd6laCnPNNKIgl9Q
UXtNYTcNheGkLQrC6vR3L+ho1XpkcoBAmojQxYILu2CrDbQeKtsov4oME52s
zPvHPD09gzB6S89EuCHUQDztakcqJvy9RhsmkM0TMaw1rECSV+U6LwovflxV
136u2aTaJ6nNkm93NQ1JzbOwYGm91OXqBMLRaQDSvz1uvQsWV9y9VeYY5GI6
qlHmdVYNmKzYGK26L6ZAmHbo3HZut0CmXIAaqS4ria7w4qnEioDKP3GkhKQo
hwFKe8VeIwHIxc0v2VODII6v8qxYgij+YIxKCnYKeGO6bcgD5naGyM4dWZdE
zdaSPEshD8dsYOrQwanIOm6ZI3oWCVpoXwMHMjhz2+Ag5SANWKH9X9k5Q2KC
pJeoPVlO23v3KDo5WTpD8gj+TGIGk7wZQaPAKv7130jEARkjR2mi2j6qYHHh
KzowQevMQVGio+P5Jm9pkkCDZLGqZib1btR3xOMvt8gJR32/dZo4SzbNekJd
P4N+lks4H86w8/xOGikz1d9mHEzQt4Fi/tdUBXpdUaCnUFUS6Xl+hWbU9tHS
1Me7nyRoJX31gtAjGOnHPrEOt/ZhI5ZY0oLcBnAk0OE3PXQwTEkURHMp3eq5
NPmjwyGiG5y1dQ6G4DgJZ7RxNoTAQFbBaFYokabO1JZukHrUVEb7fAvTAQyO
aRztEaIvQAPojwVGSEMln5FrRjSkfre4j2Ygb71E31Hg2Ku8JKManP/uXKZe
8EZcopIRGvmcDSsIIKpoSnAMU1htFOJlVfAg7HbSn53k4911feLewnf+4knX
3iv2lV5ylI3dKynRl5eUYNbqn5PE3nLmLZGjUYPSNP3KT56puoCWHP4CtD1O
pl/TFXnghUzY8IOrvEYpkb/w/JpG2K7DT/sX1U8uxrwXp2gP6Q7udKJBcaio
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
IJJ3D4V4bqo20300sdGs7VXmz4ig+g48x99N9zVp+bCV/TwcbzNyTTibevKG
OveMe9RrVI9XPWzjICzaJ7Mz34lBQ3rHzy8h9ezkb3RNbHiN3BH5aFyVMeHU
YiV382Y4q6uZmC5erYEPwlcu1uMK/PC+lqJttj7SQCVC5wX0ARmuTH1ggutJ
EPzwTMEwQTD5OA3k7eHGjlRH7vY1dtcO825ydC+jTJMBi/Rbt8b91uihVhxt
oq3wGEv0oS6FxsIjTNGDjXWshR8zWZ3PxyzjR35+xp7d6px1TNLHGKT7GpPc
2JjObrZI9zWmFwfpbMgkPdTYrc1Z7+dDV/MWPj9fz7olh9+qREfFlFTelkzn
rinMNvbWiOeZYyPHjC9s7K7ajiUgP1E6Axkgk9RIlS59QuJAY/aauePDekaf
vjn74Ma6nw9ZzVvPDPzCCDpGzHASibesHTf0Gz9/fI/qaTd83t7epLw1/vGB
z/HL9fZm4zj8cLP3hW473BiZx4+nysONvdWeOf1s0AEz3FhgbD+2Z1xS/eae
HYMRKPcenjMGU9NMZhraBa9DKPnc2Ji/6xhPwDGNvQ9b+Js1pnR2sxvmwDBj
0rjZD5OwL/yA78Q1dvP0H8GXPWnc/PkvxOS/PAt8IkZjtI4TzHGhVMY4d0hT
HH320HNvqllTAbCm9dHmnBdlqg+4rCguXLCjlNcoc6oq0WSQs6lJ+0mxvAs0
kGVY8lVKN7ArYQc3YhlttDywHU5rV88bNbAh2je9gqJkvbEMH65qylzDenH0
2D5LMSkCMfPQX6AFEhp2NMylyjjjIb15c+5fjw1e7urX2R7tlzlW31pK6lCL
Fko0obQ1+mDICopZ4bufYHzoKhALNvtRqGmcVbw5W6oZhXxNbEdxKGtsoBaX
A0yAnUnjb6JErbyEu/6asWOHJqaMA6/5lUHmZspBjpi0imBJu3mRL5JX2T5Z
1Ptti7Wvtld7ExWcKioZh98rybh5JDQzdtfIKARLS7L+lxlyAyrW6+rpNqZ8
hEfYYjJo9xrmCcvZ7DdsmrK9wxxAmKuNorS7LpliFpz5Tbb5vGxNXo+ZxDhZ
yL3f1LWgwEep1SUpwewSKbMiyQirMG+uJGNZLDhhOj6lobXwW1ovfVe3NSZD
YoRvjPJFpd3YrtT0QBv0V8224dncxU6FxLTFzaxekF9YrvDCdSaaUN9LP299
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
/H1ExPhh5wmn9c/oQPovHfsmpuD+AQA=

-->

</rfc>
