<?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.23 (Ruby 3.2.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-jesus-gfds-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.27.0 -->
  <front>
    <title abbrev="GFDS">A Generic Framework for Building Dynamic Decentralized Systems (GFDS)</title>
    <seriesInfo name="Internet-Draft" value="draft-jesus-gfds-00"/>
    <author initials="D." surname="Jesus" fullname="Diogo Jesus">
      <organization>TaRDIS</organization>
      <address>
        <postal>
          <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
        </postal>
        <email>da.jesus@fct.unl.pt</email>
      </address>
    </author>
    <author initials="J." surname="Leitão" fullname="João Leitão">
      <organization>TaRDIS</organization>
      <address>
        <postal>
          <street>NOVA Laboratory for Computer Science and Informatics (NOVA LINCS)</street>
        </postal>
        <email>jc.leitao@fct.unl.pt</email>
      </address>
    </author>
    <date year="2025" month="February" day="28"/>
    <keyword>decentralized systems</keyword>
    <keyword>dynamic environments</keyword>
    <keyword>swarms</keyword>
    <abstract>
      <?line 89?>

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

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

<t>The following abbreviations are used throughout the document:</t>
      <ul spacing="normal">
        <li>
          <t>API: Application Programming Interface</t>
        </li>
        <li>
          <t>GFDS: Generic Framework for Building Dynamic Decentralized Systems</t>
        </li>
        <li>
          <t>CAS: Central Authentication Service</t>
        </li>
      </ul>
    </section>
    <section anchor="protocol">
      <name>Protocol Anatomy</name>
      <t>The main unit of interaction in the framework is the <em>protocol</em>.
Protocols are assigned an unique identifier and embed the logic implemented by the developer and use the abstractions provided by the framework to interact with other protocols being executed locally, as well as handling communication with other nodes. A process may execute an arbitrary number of protocols concurrently at any given time, and protocols can communicate with each other to cooperate and delegate tasks. Moreover, as it is very common in distributed protocols to capture certain behaviours, protocols can execute actions periodically through the use of timers (e.g., execute a garbage collection function).</t>
      <t>Each protocol is composed of the following concepts that dictate the anatomy and life cycle of a protocol:</t>
      <ul spacing="normal">
        <li>
          <t><strong>state</strong> describes the inner state of the protocol, containing the necessary data and data structures to ensure its correct behaviour. The state should be initialized in a specialized <em>init</em> function and can be mutated through interaction with other local protocols, periodic timers that alter the state of the protocol and, finally, communication with other nodes running the same protocol on different machines;</t>
        </li>
        <li>
          <t><strong>timer handlers</strong> are meant to execute periodic or scheduled tasks. When the timer expires, a handler is executed with user-defined logic. Additionally, protocols can cancel timers if they are no longer relevant (e.g., a timer set up by the lack of an acknowledgement can be cancelled if the acknowledged arrived in the meantime);</t>
        </li>
        <li>
          <t><strong>inter-protocol handlers</strong> are in charge of managing communication between protocols running on the same machine. These handlers are divided into two categories: one-to-one <em>requests/replies</em> and one-to-many <em>notifications</em>;</t>
        </li>
        <li>
          <t><strong>communication handlers</strong> which manage incoming and outgoing communications between different nodes. At the protocol level such information arrives in the form of messages;</t>
        </li>
        <li>
          <t><strong>discovery and configuration handlers</strong> which deal with peer discovery 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 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 and configuration
 registerSelfConfiguration(properties, uponSelfConfig)

 registerAdaptiveConfiguration(properties, uponAdaptive)

 // 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(Map<Parameter, Config>: parameters):
 for p in state as AutoConfigurable:
  p = parameters.get(p)

uponAdaptive(Map<Parameter, Config>: parameters):
 for p in state as Adaptive:
  p = parameters.get(p)

]]></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)

 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 and Configuration
uponDiscovery(DiscoveryNotification: notification):
 this.neighbors.add(event.peer)

uponSelfConfig(Map<Parameter, Config> parameters):
 for p in state as AutoConfigurable:
 p = parameters.get(p)

uponAdaptive(Map<Parameter, Config> parameters):
 for p in state as Adaptive:
 p = parameters.get(p)

// 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          | Discovery |   |  Timer  |  |  |  |
    |  | |    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 & Configuration |
|                            Handlers              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="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 3: Timer manager overview</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 4: 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="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="framework-events">
          <name>Framework Events</name>
          <t>While most of the events used during execution are for inter-protocol and inter-node interaction, the framework <bcp14>SHOULD</bcp14> also provide control events for interaction with the framework. 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. To facilitate this, the framework includes a dedicated request, RequestAnnouncement, as part of its toolset.</t>
          <t>The definition of this events is still a work in progress and it will be detailed in further versions of the document.</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[
registerSelfConfiguration(SelfConfigMethod: method)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerSelfConfiguration</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.registerSelfConfiguration(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 6: Self-configuration controller overview</t>
        </section>
        <section anchor="adaptability">
          <name>Adaptability</name>
          <t>Decentralized systems need to adapt while executing, since they operate in dynamic, and often unpredictable environments, where components may join, leave, or fail unexpectedly. As resources like nodes or services can change in real time, the system must adjust to maintain efficiency, performance, and reliability <xref target="RFC7575"/>. Due to these systems complexity and size, the task of managing and adapting them proves too complex for humans. The only feasible option is to have this adaptability happen in an autonomous way. While the initial configuration of a node may prove to be correct and even efficient in a preliminary state of the system, as conditions change, such configuration may become suboptimal or even incorrect. To mitigate this issue, nodes should aim to adapt during runtime, in order to keep up with the current state of the system as a whole.</t>
          <t>These changes can be triggered locally, with values ​​calculated by the node itself given its local perception of the network, or by the node's neighbors that aim to converge to a common global configuration.</t>
          <t>To accomplish this, protocols should tag the parameters they wish to be reconfigured as <em>Adaptive</em>. Parameters with this tag will be managed by the framework and updated when a reconfiguration request is issued (i.e., due to a periodic timer, reconfiguration data arriving from another node, an intelligent controller executing an AI model <xref target="I-D.irtf-nmrg-ai-challenges-04"/>, etc. ). Reconfiguration can happen through distinct methods, such as analyzing local metrics (e.g., the CPU usage of a protocol may be too high), synchronization with other nodes running the same protocol (i.e., to reach convergence of configuration), etc. So, the framework <bcp14>SHOULD</bcp14> provide a clear clarification of the methods available and how they behave.</t>
          <t>During initialization, the developer specifies the method for automatically reconfiguring parameters tagged as <em>Adaptive</em> by protocols by selecting one of the available methods. This is achieved using the following function:</t>
          <artwork><![CDATA[
registerAdaptiveConfiguration(AdaptiveMethod: method)
]]></artwork>
          <ul spacing="normal">
            <li>
              <t><em>registerAdaptiveConfiguration</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.registerAdaptiveConfiguration(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 7: 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 8: Adaptability listeners overview</t>
        </section>
      </section>
      <section anchor="arch-securitymanager">
        <name>Security Manager</name>
        <t>One of the greatest challenges in distributed systems, particularly decentralized ones, is the ability to accurately identify and authenticate nodes in the absence of a central certification authority. Over the years, various solutions have been proposed <xref target="Authentication_Survey"/>, including statistical trust models, auxiliary networks composed of trusted nodes, and other approaches.</t>
        <t>To eliminate centralized components and minimize reliance on other nodes for trust, we propose a self-signed public key cryptography mechanism as the default security solution. In this approach, each node independently generates and manages its own identity using an asymmetric cryptographic scheme.</t>
        <t>The security manager is structured into distinct components responsible for identity management and creation, secure channel establishment, and the implementation of standard security primitives. Additionally, it interacts directly with the communication manager to ensure secure communication and attestation.</t>
        <section anchor="security-primitives">
          <name>Security Primitives</name>
          <t>The security primitives component is responsible for managing cryptographic material, including private keys with associated certificates for identification, certificates of trusted nodes, and symmetric keys. It enables the framework to load this information into memory and persist it to disk when necessary.</t>
          <t>This component facilitates the execution of standard security procedures, such as certificate validation, signature generation, Message Authentication Codes (MACs), and block cipher operations. These fundamental capabilities allow higher-level components within the framework to build secure abstractions for the developer.</t>
        </section>
        <section anchor="identity-manager">
          <name>Identity Manager</name>
          <t>Properly identifying nodes in a distributed environment is inherently challenging due to factors such as the absence of a central authority, the dynamic nature of nodes, and system heterogeneity. While some decentralized trust models are more widely adopted than others, different solutions must balance security guarantees with user flexibility. As previously discussed, we propose a cryptographic model based on self-signed certificates. While this approach does not provide the same security assurances as other methods, it offers simplicity and flexibility in environments where a central authority or a predefined set of trusted nodes is not a viable option.</t>
          <t>The identity manager is responsible for handling the identities of users, services, and system components. Its primary function is to ensure secure, consistent, and efficient identification, authentication, and authorization across all nodes.</t>
          <t>Each node (i.e., Peer) is associated with a hash of its default certificate and maintains an internal list of aliases. An alias serves as an alternative identifier for a node, providing a simplified interface for interacting with the identity manager. This allows nodes to assume multiple identities, enabling more complex communication patterns for specific protocols when needed.</t>
          <t>Nodes can generate, delete, and manage aliases as required, with each alias possessing its own private key and self-signed certificate. Furthermore, when sending a message, a node can explicitly instruct the framework to use a specific alias (i.e., <xref target="protocol-handlers-communication"/>).</t>
          <t>Although this design does not support verifying human-readable node information (e.g., DNS names in certificates issued by a Central Authentication Service (CAS)), it ensures that nodes can reliably reference known peers and verify that they are communicating with the same entity as before.</t>
          <t>This simple yet powerful construct provides two essential functionalities: signing data and verifying previously signed information. These capabilities form the foundation for establishing secure communication channels.</t>
        </section>
        <section anchor="secure-communication">
          <name>Secure Communication</name>
          <t>Secure channels are communication pathways that guarantee the confidentiality, integrity, and authenticity of messages exchanged between nodes. They prevent eavesdropping, tampering, and impersonation by malicious actors.</t>
          <t>To establish secure channels, the framework relies on the identity manager to ensure proper signature generation and verification, ensuring that transmitted messages remain both confidential and authentic. When a node requests secure message transmission (i.e., <xref target="protocol-handlers-communication"/>), the communication manager coordinates with the security manager to handle the process securely.</t>
          <t>The security manager utilizes cryptographic primitives and the node's identity to sign and encrypt the data before forwarding the encrypted payload to the communication manager for transmission.</t>
          <artwork><![CDATA[
                |                            ^
                |                            |
                v                            |
          +----------+      +-------------------------------+
          |          |      | identify = getAlias(alias)    |
          |   Sign   | ---> |                               |
          |          |      | identify.sign(data)           |
          +----------+      +-------------------------------+


                |                            ^
                |                            |
                v                            |
          +----------+      +--------------------------------+
          |          |      |                                |
          |  Verify  | ---> | verify(alias, signature, data) |
          |          |      |                                |
          +----------+      +--------------------------------+
]]></artwork>
          <t>Figure 9: 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-controlevents"/>).</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 10: 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-controlevents">
          <name>Control 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 utilize. For instance, a protocol relying on a TCP connection as a failure detector should be informed if this connection is lost. To support this functionality, we propose the use of the framework's notification events construct.</t>
          <t>When a control event occurs in the communication manager (e.g., a connection failure), the framework generates a notification encapsulating this information. Protocols that subscribe to such notifications will receive updates, while those that do not remain unaffected and agnostic to changes in the lower layers.</t>
          <t>The framework <bcp14>SHOULD</bcp14> define a standardized set of generic control events to encapsulate relevant transport-related information. In future iterations, we aim to develop a more comprehensive and fully extended version of this event set. The following example provides an initial illustration of these events and their intended usage:</t>
          <artwork><![CDATA[
// Framework Control Events
def TransportConflict {
  Throwable cause,
  string message,
}

def ConnectionUpNotification {
  Peer peer,
  Transport transport,
}

def ConnectionDownNotification {
  Peer peer,
  Throwable cause,
  string message,
  Transport transport
}
]]></artwork>
          <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, 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)

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

  // Adaptive methods
  adaptiveMethod =  {localMetrics}
  framework.registerAdaptiveConfiguration(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 11: 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.registerSelfConfiguration(selfConfigMethod)

  adaptiveMethod =  {localMetrics}
  framework.registerAdaptiveConfiguration(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="appendixB"/>.</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.</t>
      <t>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>
    </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 1735?>

<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>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(Map<Parameter, Config> parameters):
  for p in state as AutoConfigurable:
    p = parameters.get(p)

uponAdaptive(Map<Parameter, Config> parameters):
  for p in state as Adaptive:
    p = 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)

  //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)

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+y9/XIbSXYv+D+eoqyJ8BAUCErqnv6gR33NFtUzsltqTlNt
X8dcz0YBKII1AqrgqgLZGImO/X9fYiP2TXbfZJ9kz2fmyawECErsmfDdC3vU
RKEqKz9Onjyfv3N0dDToym5RnGSPTrPfFVXRlNPsuyZfFjd18y67rJvs23W5
mJXVPDvbVPkSfj4rpkXVNfmi/Esxyy42bVcs2+zgd9+dXQwfDfLJpCmuoT38
/mgwzbtiXjebk6ztZoPBrJ5CI/C6WZNfdkd/Ltp1ezS/nLVHT54M2vVkWbZt
WVfdZgX3vHr59rvBoFovJ0VzMphBSyfZsyfPfnP05NnRs68G07pqiwoaOMm6
Zl0M4KXQyLtiA12fnQyyo2wW9LTlntIPMpSiui6bulrCXXS9vckbuGOQr7ur
uqE2Mu7vWVnP6+yfsL+DDD51M8+r8i95B709yd7mP569uqAf2q4piu4ke/PD
v5xm3+eTusk7GD9N5Yt6uVp3RZNdTMuimhZZXs2yVxX8tISGpjCJ/NSrNy8u
htRasczLBcxWPqap+sfLaTdeV4vxqjN9+6f6//m/6uz7ouzgv3+D3v15Ol7A
y/Padg9Wp2vKyboL5/HH/DIvFtlreO3fYiKb2XiJr/7HaQ4ttOPkfL6tl3mb
/S5fXP9t5rMbz+HdMJ27OvldsShXRfYCCPZv0cfL1XiKr97ZRybMb2E75ou/
CWGOJ/zufXrZlIur/G/TSXp1oo+Dip++LmALZT9+9+LL33z5m5PsFDYV8a83
RYdsGpgz//zV18+enWQX6+a62FwU03VTdpu3TV61q7rpLormupwWuOteHZ2N
y6a7PKqWzfwoL4+mV/liUVTzAvjw5ycwlvVqAa2evpI3vM6rXN7x9RefPztx
fz6VP794Bn9mcPeLurqUS19/DZf+La/mZ3mXvwWOjq9erhddmc9mTdG2JzQN
RyfBRbrW5c0cJ/qq61btyfHxvOyu1pPxtF4e0708q+2xe5Cf4pMsaG1Q6hL4
ScR+vTqXMTz7+jNY4xfy9csvvjrJfjqTb198+QXM5/LszYXM75OnXwILuziV
Z588eXKS/eGnVy/0YXz62+9fyt2ff/4FNP39xQC+f19Onq3cgOlbcqSLcrJ6
thqXtR2R3n5eFM1FuXTNyPdkQyv4rS2X47ZeN9MC5mBejKuis836x1/kbQv0
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
BvilXYzWri8+adcySs4BAA==

-->

</rfc>
