<?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.31 (Ruby 3.2.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-jesus-gfds-02" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.31.0 -->
  <front>
    <title abbrev="GFDS">A Generic Framework for Building Dynamic Decentralized Systems (GFDS)</title>
    <seriesInfo name="Internet-Draft" value="draft-jesus-gfds-02"/>
    <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="2026" month="February" day="23"/>
    <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.</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>
          <t>Even though this area is still a work in progress, the framework <bcp14>SHOULD</bcp14> provide a clear clarification of the methods available and how they behave.
At the moment of writing this draft, we propose following distinct methods:</t>
          <ul spacing="normal">
            <li>
              <t><em>localMetrics</em>: In this method, the framework relies exclusively on local machine metrics—such as CPU load, memory consumption, and network usage—to adapt its parameters dynamically. Decisions are made based on the current state of the node, allowing real-time adjustments according to the device’s resource conditions and current load.</t>
            </li>
            <li>
              <t><em>systemMetrics</em>: In contrast to relying solely on local metrics, this method considers system-wide information when adapting parameter values. For example, the framework may estimate the overall system size (e.g., network width) and adjust dissemination protocol parameters, such as fanout size, accordingly.</t>
            </li>
          </ul>
        </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 1857?>

<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+S9W5fbyJUm+s5fgZbXGidTJHWpcl2yXTWdpVTZGksluVLV
NV49bS+QBJmwQIAGQGXRknr1+3mdl/N21jr/5Jx/0r/k7GvEjgDApKQs+/QM
261KgkAgLjt27Ou3p9PpqM3bIjtL7pwnv8nKrM4Xybd1usmuq/pVsqrq5Jtd
Xizzcp1c7Mt0Az9fZIusbOu0yP+aLZPLfdNmmyY5+c23F5fjO6N0Pq+z19Ae
fr8zWqRttq7q/VnStMvRaFktoBF43bJOV+30z1mza6br1bKZ3n84anbzTd40
eVW2+y3c8+Txy29Ho3K3mWf12WgJLZ0lD+8//AzunT78ZLSoyiYroYGzpK13
2QheCo28yvbQ9eXZKJkmy6CnDfeUfpChZOXrvK7KDdxF15vrtIY7Rumuvapq
aiPh/l7k1bpK/hv2d5TAp6rXaZn/NW2ht2fJy/T7iyeX9EPT1lnWniXfPf/n
8+RpOq/qtIXx01Q+qjbbXZvVyeUiz8pFlqTlMnlSwk8baGgBk8hPPfnu0eWY
Wss2aV7AbKUzmqp/Wi3a2a4sZtvW9O2/Vf/v/10lT7O8hf/+HXr358WsgJen
le0erE5b5/NdG87j9+kqzYrkGbz27zGR9XK2wVf/0yKFFppZ73y+rDZpk/wm
LV7/feazna3h3TCdhzr5bVbk2yx5BAT79+jjajtb4KsP9pEJ8xvYjmnxdyHM
2ZzffUwv67y4Sv8+naRX9/RxVPLTrzPYQsn33z76/Fef/+osOYdNRfzru6xF
Ng3MmX/+4suHD8+Sy139OttfZotdnbf7l3VaNtuqbi+z+nW+yHDXPZlezPK6
XU3LTb2epvl0cZUWRVauM+DDn57BWHbbAlo9fyJveJaWqbzjy88+fXjm/nwg
f372EP5M4O5HVbmSS19+CZf+kJbri7RNXwJHx1dvdkWbp8tlnTXNGU3D9Cy4
SNfatF7jRF+17bY5u3dvnbdXu/lsUW3u0b08q8099yA/xSdZ0Noo1yXwk4j9
evJCxvDwy09gjR/J188/++Is+eFCvn32+Wcwn5uL7y5lfu8/+BxY2OW5PHv/
/v2z5Pc/PHmkD+PT3zx9LHd/+uln0PTTyxF8f5rPH27dgOlb70iLfL59uJ3l
lR2R3v4iy+rLfOOake+9DW3htybfzJpqVy8ymIN1Niuz1jbrH3+UNg3Qa526
pt2V3sYX+uss3aaLq2wGzd/70728XGY/za7aTWFfY5sC0r2CwzZf0OYSUoXT
9fmT2YP7swcP7n9577vLy9nD+/e/nH1yH3t2hYe5v+HTX90Dsvv84SezT774
5P7nD+CW36XLbFPkqbvrV/C599mnn33yyaezz774HFZtNBpNp9MkncMOThew
sUZOqsFtukHyxi9X+fqq2DvxAH+7ymBTV2sQjapd0y9RJIu0TLZ19TpL2iqZ
Z8lfdnmbJbqpsOHljn6DwSfrOkvbBEh5W2Q/wQaltzSLtMiSapU0u8VVIJbM
Ri+vcnhxtdjh96TZZot8lWdNkt6GwDZJrq9yeCX2p2qo1TpbZTWzsHpxBSNZ
tLua+Vn2E3AVWrlNtYRjHF+3zF5nRbXtzCWMtcl0iug1MEKcpXypUz0t8Fm3
LNBug7O0a4B0Z7xkm3y5LLLR6BfJ89fIwLJrs3b9q5HjIGR+qUt2Idq0eWVX
Iy+vcLBtsiu3dbbMF206z4v+ZZEXzJKXdmjwc5uVCUqjedPizcSA4O1JCZME
I7qC9d6ke6SMokKBeAmvTZb5asWvXmfVuk63sA5pAbO/pnnA15cZ3AodXVRF
wacNvDVLNwVwNiBT+IXnE68yc4ezC6/BX0AywHapr/SqfAG9glHVOa4yvN8t
FIjcO7hU5K+gx8zvkwJeVS72ExpCsoKDCkgAVvE1PJ/OCxxIuoR2G5bxoMcT
enUF4vscukaPwc/bIl1kRLfwxm1at9iNtA4pHM4NWFtYDRzXJCQcNwc1Hpel
7tD0NXSJOoLzBF3b4vTDBoSWSqA1+AeYUQ5zs4M5JeIu8V1AwVvYMkTdflS8
BeoM9i18T+pqvoOVXKUwY/DqIoMjVA70JitW06ssxdMx2WRAWWXebJBYfyT6
BmaYZ6+JNmH2lSh4Kpt9ubiCQYtkMeEdBQpMzdsFqAToVIjmKoXBYANCnkj5
SFtIszw1OKNwQ2cDJNfVrlgisdVZQecezFeWNtADQ/fAeqhfRN1hM7syp+WC
wQHXJ4KGmW/h/2mPJ3f4SKHe1MDP7zCfhH9oVmDMIHnUPGbqY982xTWqdYfM
MxruCqSrYj8RNgKLDBNS7oHVEAHRLdD1vE6qayAm4BHACnF84bxMeLOuK1h4
YAVlBWtYAyWkxSxJeJX6uMYceOkKBr6qqw1OVw6iXNPijqONQkRMtLmH9nHn
8p3IIZRjFPkGtCBiY9AJmAtkeFWOZAc9FHLj4aWwwxav8DIwnV25BALbzyJG
bbkvNDjfy+jLtKV24GX5mlgCTJDsGtnLsCVh6tu6Wu6QcJdLaM6cOIYOtBv2
xaS6VQUQdXj0rOAPZB7A/vs5Lx8R26LCXYQ8HXR/PKngXSCKgEi50jHIoUHN
ulOD5hje+syQm51fvHGFQ9Dvjd0O2euqeA0vo4O4GTqJZ8mPIEvCIVxd8wkC
b15ObDsb3PvwKHEX7DmdASISQDt7WgqYU3weeB4wpop2PNEyMBNov4L5B+5X
77Yt3VWuK/ovEK3SR8Rzmgr4f0OCEUxoBUuf0QQyowCBf1pnsC6rfL3jq0xG
y3SrB9YseQbzDmOvYaMLh8K+0Njc4uNywHL//NyJ944jQjyT+bRHYvOkSA2j
/DQ3xxROO1MEUMOFly9WKucwqYGsXMN5BG2zHNJHknCoN8T4gav9ZedJIXPH
uGmUll6lkf550xMv3p8i31hOGZBq6baVFZpQzhGe5K+IQEEHX1Fdq5C0oEMd
ZiYlvhcd2JZJRQfXRE4u1geFh6VFU4U8b1AgwxVy2xcmZAPEh2JUw4w2RWkC
ZOQpnfn4O0z1wtOo8D13QMySS5jCV3yWzGF34yE0h2FkMGjz5mDOgA0t6t0C
mDjOAJFlBnKicgbdc7hcMJYcmS+eEKT60SFXK10uKjibFm0JkwnE9RiPQdq8
KvgoTU3c6N68If3r3buJE7dA+iUxxnMk4hVVwaQ4VwEVlbAp7F38r76CuTOv
sewj6Fi2he2R1kQ4C9SKqG2aWOIaMlBLvn67M+2x6ggtr5CIYEtlP8E7SCpq
MhJMV7uSphb2CBM0dYQIfV79pJJXSucybvfrdN/QWYgSF7Ma4YmshCxQVIfd
2+B00ekX031M66BugtxWIxMFkoI5bKtaKPnNG9FH371DTlNdJyAT50uc87Zq
907BaDNesWg3unN81xLJ0U5ZLJBbogDE+gqoXsUUFqGwqoyVRSe4CrR0+Hhy
ig/gONbp9tQRqfRcadQ0uszg8NvLMfaySsQKIRPrFw+WjHQhVLlo+k9Pb0GX
Oz2dJfiHkqnqQXV2FdIBUeok2ObMJOYwt/A0XlvwGQpC+dbyJmg1X5cTGenE
HN4RA063wDCYDQgPQbqSY3SCIjtQCLErPuIL4VPEvKbCvGgarwyPJkbAquqS
JNcy1kn1ZF1mwIeLxnIRFheAjWXTxX7Bih1R1wJ/O6FtALTsBODWvnksglsZ
asX8GmZmMrs8HTVPHzI9XmKv7xl1hAiaJCLa6spzY2VZuO75iyfMYLISJox0
N+K8OoiI+yq9hm8HLYtIXUcIB/XiFczzL36RXKikBxx6R+OLRUBY/gXsuI+3
PhB3a0lK5DctkdWuKtz4zdkIzbNv3ui4gCP4F5+6JTudhksGc29mkQ6FeBUn
3LBdwqDx4OZgpSfU3eMXUd7kqJOIk97FdMlKWGhOEV5sOsAtE80mXZrV0Wzz
ziDgnjU0s3FEskrJPEDdX4oyYd7kaTWeQrrR7GYW4yYx6QX0686uHqHATUyK
olUDPXfsynDSBogGzuFKlQq+Gck0eVSVr9GGqC+6ABkGlh+/M7d4BfIN+gCb
5M6zHy5f3pnwf5PvntPf3z/+/Q9Pvn98gX9f/vb86VP3x0juuPzt8x+eXvi/
/JOPnj979vi7C34YribBpdGdZ+d/uMOM4s7zFy+fPP/u/Okd3mh2FyEnZP2E
JgkYNMmTzUjXkAxE3zx68f/8Xw8+hbn6h++/ffTwwYMvYa74yxcPPv8UvqCd
g99WlXDG8VcU70awXiBNkPoNQvsCKKRNieXDjrtC9RkFd5jN03/BmfnXs+TX
88X2wadfywUccHBR5yy4SHPWvdJ5mCex51LPa9xsBtejmQ77e/6H4LvOu7n4
6/8KzDJLpg+++K9fj+REIU5DfJsc1rmcVCnJlWhyAmVotyapkvinrB2wpiny
4bPk3GyJF2a3PdHdBjfiaXz2UYwSGnl0Dm084p86BnS2++G2eKE78bwEqWqz
T978wvFPHjMZ0Po4Zcwl8ZQlqUQbOJ2NXriDEqcobVAMyOg8FM0KdjD0a4V2
E9qym3kmzKtaw+hQgaCDx3MfJ1bQAzsRhQLlQ1hDP8PSITCbquD32pzn8wwn
l1ksaVKivMMWuM5gU6SNtVnZc9M0R+ruLDl3RlW0S0mbLAvMc+htvU84TCEU
KZwprC2cNWudo4WyzTci75i709J0JONuZOlC+0KGYDYhsHYAR0ZGBiDSxqxC
gDpZi6sI35zORjZnLzD7F2PDINyjOLPIalRf2SKXV7u6mUQ9dIPXFQLSrpZs
GdFNQ0uF64kHGowUZKGTbLaeTfzTIFHXc5Qa0badMRmqejJGxQzH7Q+XUOpr
gw2Ms5xtW5EyyYTfCinJTmBjgT1CU9c2yhpwIJ2eksHi9DQ6R/OydIZAebM+
OSG5UpR9/KHMkESQGMi8QkuEfzgZpzHKK0oToov62WZzPb8N+LTYcel0E7ZA
BlVSv+TCKf566uaO5V22p2x2LVmTdFU6JzvTFe0MI1S4JdW1E+MPOrdb171o
MhIyo8FBzJvs8IZK6l3pZq2BHe2bqaxjZIPmdNDU/1GWiPojckrdwFohK9pk
oCfQxAptue6j0r+4ykBVx0ngPfLjlQjE3Fb20zYn62qqzSKtOaZBHUd31HSJ
QgaxEWBmwBCWy5w1aRxttIfR4lDo5OUrMbiQVg3Pg/6HRkOQorDfsi9S6Q+q
ELutcjs1ziKjWbwqq2sYCBt5dIn5XTg+fo+9Dy1UNXCbpfJ3mil4zVjnMxLh
oomNXADiLepXMfwM6NJWpV9dWUe1uOl7WCPMmcFDX6qkvUZWRBFjedacQSMZ
mk/gP6iKwynTtM29GlRP+PVUBB+6Y4Os9bSs8AASpfNURxn22AySFUXRXvMS
7lMbA5z6bLENnm3ccD2J6gHRhruB7WhkQXIBCLg5aUGc6oU/0OQi21h7Ogc2
vUBGvic9mb0toscaA3BnJGj1ZZIle1NfK+7E6zSHLix8dFM1zihkndRyKvcc
xZPoMEfSJFeB0gALAB3uqUY75H1scIHWanyVCl3G+ik2T5A7KmB9bm86S1uB
hDplW72agmRvBcZwMi+4BfDuzn1Wj1kJdnLUE2W7PN1enJoiywWZ6rxJvMC+
RSGy2jXID7Lg8BJG7gQgz8Bj5o0bBNiP4+Xwt+Nu88yxpRGoQwsUKXBf4IZO
lmqlj80b4Yyznw7V7F3N0uB2V5PbH0/BBzM/5Cx48pcNM/0JRUzhCPn0Ytus
+oTReEZHSXTowXy0ixmofQ9nIK+2wN7IixpQX0ToZGxEg5XSODz9yQyDQdRg
tqUoBVRlWw1wkmvo1MT7P50l32dr9G/UkQXE8Z+TfJYBgRDrjRXaid8/B9VZ
1xqSDwiKaKm056k/veUs1FN9yPLxb//2byN85mRLll801I4xLOfeveQBcAee
QWmUl2WUzGb4crjjobvD7P6u38hNNsiFeVvVFEFWy2xdwuo8so+YnkzgdKpK
f8d45J87l0U7/KzeZZ/8XrrzjHtzot2TR/TnMY/xExjjy75FH9kvyVfJGzhl
c7Yskvcje+df+ciu4Qv/2IlpQt73Kbzvt7LIts90HMkPJ9/UVbpcpE0r17nn
8dWxLpVvZVvstY0L6O5rucbP2yudZ18i2eqzv2Fx+hFL0y+ZorGJnh86LV0o
rWhr+OALitbIt8B/9IERnGhzZnjfmaNWn/ouy9dX86r+YWt/5W70/9bpSbAs
nbl9xudkNLdyVdrC7YNsXFfM8m3dqsC73c9OoULhrSjmKHIpA4aD/cJz1mgj
B1pEfAbmTSg+6fi0LS8CRQdaLFOLYREjXCTYQXvZyGmx3qVoKc800oiCX1BR
e01hNw2F4aQtCsLq9Hcv6GjVemRygECaiNDFggu7YKsNtB4q2yi/igwTnazM
+8c8PT2DMHpLz0S4IdRAPO1qRyom/L1GGyaQzRMxrDWsQJJX5TovCi9+XFXX
fq7ZpNonqc2Sb3c1DUnNs7Bgab3U5eoEwtFpANK/PW69CxZX3L1V5hjkYjqq
UeZ1Vg2YrNgYrbovpkCYdujcdm63QKZcgBqpLiuJrvDiqcSKgMo/caSEpCiH
AUp7xV4jAcjFzS/ZU4Mgjq/yrFiCKP5gjEoKdgp4Y7ptyAPmdobIzh1Zl0TN
1pI8SyEPx2xg6tDBqcg6bpkjehYJWmhfAwcyOHPb4CDlIA1Yof1f2TlDYoKk
l6g9WU7be/coOjlZOkPyCP5MYgaTvBlBo8Aq/uVfScQBGSNHaaLaPqpgceEr
OjBB68xBUaKj4/kmb2mSQINksapmJvVu1HfE4y+3yAlHfb91mjhLNs16Ql0/
g36WSzgfzrDz/E4aKTPV32YcTNC3gWL+11QFel1RoKdQVRLpeX6FZtT20dLU
x7ufJGglffWC0CMY6cc+sQ639mEjlljSgtwGcCTQ4Tc9dDBMSRREcynd6rk0
+aPDIaIbnLV1DobgOAlntHE2hMBAVsFoViiRps7Ulm6QetRURvt8C9MBDI5p
HO0Roi9AA+iPBUZIQyWfkWtGNKR+t7iPZiBvvUTfUeDYq7wkoxqc/+5cpl7w
RlyikhEa+ZwNKwggqmhKcAxTWG0U4mVV8CDsdtKfneTj3XV94t7Cd/7iSdfe
K/aVXnKUjd0rKdGXl5Rg1uqfk8TecuYtkaNRg9I0/cpPnqm6gJYc/gK0PU6m
X9MVeeCFTNjwg6u8RimRv/D8mkbYrsNP+xfVTy7GvBenaA/pDu50okFxqKiR
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
cFr9jA6k/wF/EZTB7gECAA==

-->

</rfc>
