mirror of
https://github.com/vacp2p/rfc-index.git
synced 2026-01-09 22:08:07 -05:00
685 lines
59 KiB
HTML
685 lines
59 KiB
HTML
<!DOCTYPE HTML>
|
||
<html lang="en" class="ayu" dir="ltr">
|
||
<head>
|
||
<!-- Book generated using mdBook -->
|
||
<meta charset="UTF-8">
|
||
<title>SDS - Vac RFC</title>
|
||
|
||
|
||
<!-- Custom HTML head -->
|
||
|
||
<meta name="description" content="">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="theme-color" content="#ffffff">
|
||
|
||
<link rel="icon" href="../../favicon.svg">
|
||
<link rel="shortcut icon" href="../../favicon.png">
|
||
<link rel="stylesheet" href="../../css/variables.css">
|
||
<link rel="stylesheet" href="../../css/general.css">
|
||
<link rel="stylesheet" href="../../css/chrome.css">
|
||
<link rel="stylesheet" href="../../css/print.css" media="print">
|
||
|
||
<!-- Fonts -->
|
||
<link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
|
||
<link rel="stylesheet" href="../../fonts/fonts.css">
|
||
|
||
<!-- Highlight.js Stylesheets -->
|
||
<link rel="stylesheet" href="../../highlight.css">
|
||
<link rel="stylesheet" href="../../tomorrow-night.css">
|
||
<link rel="stylesheet" href="../../ayu-highlight.css">
|
||
|
||
<!-- Custom theme stylesheets -->
|
||
<link rel="stylesheet" href="../../custom.css">
|
||
|
||
</head>
|
||
<body class="sidebar-visible no-js">
|
||
<div id="body-container">
|
||
<!-- Provide site root to javascript -->
|
||
<script>
|
||
var path_to_root = "../../";
|
||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "ayu";
|
||
</script>
|
||
|
||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
<script>
|
||
try {
|
||
var theme = localStorage.getItem('mdbook-theme');
|
||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
}
|
||
|
||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
}
|
||
} catch (e) { }
|
||
</script>
|
||
|
||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
<script>
|
||
var theme;
|
||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
var html = document.querySelector('html');
|
||
html.classList.remove('ayu')
|
||
html.classList.add(theme);
|
||
var body = document.querySelector('body');
|
||
body.classList.remove('no-js')
|
||
body.classList.add('js');
|
||
</script>
|
||
|
||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||
|
||
<!-- Hide / unhide sidebar before it is displayed -->
|
||
<script>
|
||
var body = document.querySelector('body');
|
||
var sidebar = null;
|
||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||
if (document.body.clientWidth >= 1080) {
|
||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
sidebar = sidebar || 'visible';
|
||
} else {
|
||
sidebar = 'hidden';
|
||
}
|
||
sidebar_toggle.checked = sidebar === 'visible';
|
||
body.classList.remove('sidebar-visible');
|
||
body.classList.add("sidebar-" + sidebar);
|
||
</script>
|
||
|
||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||
<div class="sidebar-scrollbox">
|
||
<ol class="chapter"><li class="chapter-item expanded affix "><a href="../../index.html">Introduction</a></li><li class="chapter-item expanded "><a href="../../vac/index.html"><strong aria-hidden="true">1.</strong> Vac</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../vac/1/coss.html"><strong aria-hidden="true">1.1.</strong> 1/COSS</a></li><li class="chapter-item expanded "><a href="../../vac/2/mvds.html"><strong aria-hidden="true">1.2.</strong> 2/MVDS</a></li><li class="chapter-item expanded "><a href="../../vac/3/remote-log.html"><strong aria-hidden="true">1.3.</strong> 3/Remote Log</a></li><li class="chapter-item expanded "><a href="../../vac/4/mvds-meta.html"><strong aria-hidden="true">1.4.</strong> 4/MVDS Meta</a></li><li class="chapter-item expanded "><a href="../../vac/25/libp2p-dns-discovery.html"><strong aria-hidden="true">1.5.</strong> 25/Libp2p DNS Discovery</a></li><li class="chapter-item expanded "><a href="../../vac/32/rln-v1.html"><strong aria-hidden="true">1.6.</strong> 32/RLN-V1</a></li><li class="chapter-item expanded "><a href="../../vac/raw/index.html"><strong aria-hidden="true">1.7.</strong> Raw</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../vac/raw/consensus-hashgraphlike.html"><strong aria-hidden="true">1.7.1.</strong> Consensus Hashgraphlike</a></li><li class="chapter-item expanded "><a href="../../vac/raw/decentralized-messaging-ethereum.html"><strong aria-hidden="true">1.7.2.</strong> Decentralized Messaging Ethereum</a></li><li class="chapter-item expanded "><a href="../../vac/raw/eth-mls-offchain.html"><strong aria-hidden="true">1.7.3.</strong> ETH MLS Offchain</a></li><li class="chapter-item expanded "><a href="../../vac/raw/eth-mls-onchain.html"><strong aria-hidden="true">1.7.4.</strong> ETH MLS Onchain</a></li><li class="chapter-item expanded "><a href="../../vac/raw/deleted/eth-secpm.html"><strong aria-hidden="true">1.7.5.</strong> ETH SecPM</a></li><li class="chapter-item expanded "><a href="../../vac/raw/gossipsub-tor-push.html"><strong aria-hidden="true">1.7.6.</strong> Gossipsub Tor Push</a></li><li class="chapter-item expanded "><a href="../../vac/raw/logos-capability-discovery.html"><strong aria-hidden="true">1.7.7.</strong> Logos Capability Discovery</a></li><li class="chapter-item expanded "><a href="../../vac/raw/mix.html"><strong aria-hidden="true">1.7.8.</strong> Mix</a></li><li class="chapter-item expanded "><a href="../../vac/raw/noise-x3dh-double-ratchet.html"><strong aria-hidden="true">1.7.9.</strong> Noise X3DH Double Ratchet</a></li><li class="chapter-item expanded "><a href="../../vac/raw/rln-interep-spec.html"><strong aria-hidden="true">1.7.10.</strong> RLN Interep Spec</a></li><li class="chapter-item expanded "><a href="../../vac/raw/rln-stealth-commitments.html"><strong aria-hidden="true">1.7.11.</strong> RLN Stealth Commitments</a></li><li class="chapter-item expanded "><a href="../../vac/raw/rln-v2.html"><strong aria-hidden="true">1.7.12.</strong> RLN-V2</a></li><li class="chapter-item expanded "><a href="../../vac/raw/sds.html" class="active"><strong aria-hidden="true">1.7.13.</strong> SDS</a></li></ol></li><li class="chapter-item expanded "><a href="../../vac/template.html"><strong aria-hidden="true">1.8.</strong> Template</a></li></ol></li><li class="chapter-item expanded "><a href="../../waku/index.html"><strong aria-hidden="true">2.</strong> Waku</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/standards/core/index.html"><strong aria-hidden="true">2.1.</strong> Standards - Core</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/standards/core/10/waku2.html"><strong aria-hidden="true">2.1.1.</strong> 10/Waku2</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/11/relay.html"><strong aria-hidden="true">2.1.2.</strong> 11/Relay</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/12/filter.html"><strong aria-hidden="true">2.1.3.</strong> 12/Filter</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/13/store.html"><strong aria-hidden="true">2.1.4.</strong> 13/Store</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/14/message.html"><strong aria-hidden="true">2.1.5.</strong> 14/Message</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/15/bridge.html"><strong aria-hidden="true">2.1.6.</strong> 15/Bridge</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/17/rln-relay.html"><strong aria-hidden="true">2.1.7.</strong> 17/RLN Relay</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/19/lightpush.html"><strong aria-hidden="true">2.1.8.</strong> 19/Lightpush</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/31/enr.html"><strong aria-hidden="true">2.1.9.</strong> 31/ENR</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/33/discv5.html"><strong aria-hidden="true">2.1.10.</strong> 33/Discv5</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/34/peer-exchange.html"><strong aria-hidden="true">2.1.11.</strong> 34/Peer Exchange</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/36/bindings-api.html"><strong aria-hidden="true">2.1.12.</strong> 36/Bindings API</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/64/network.html"><strong aria-hidden="true">2.1.13.</strong> 64/Network</a></li><li class="chapter-item expanded "><a href="../../waku/standards/core/66/metadata.html"><strong aria-hidden="true">2.1.14.</strong> 66/Metadata</a></li></ol></li><li class="chapter-item expanded "><a href="../../waku/standards/application/index.html"><strong aria-hidden="true">2.2.</strong> Standards - Application</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/standards/application/20/toy-eth-pm.html"><strong aria-hidden="true">2.2.1.</strong> 20/Toy ETH PM</a></li><li class="chapter-item expanded "><a href="../../waku/standards/application/26/payload.html"><strong aria-hidden="true">2.2.2.</strong> 26/Payload</a></li><li class="chapter-item expanded "><a href="../../waku/standards/application/53/x3dh.html"><strong aria-hidden="true">2.2.3.</strong> 53/X3DH</a></li><li class="chapter-item expanded "><a href="../../waku/standards/application/54/x3dh-sessions.html"><strong aria-hidden="true">2.2.4.</strong> 54/X3DH Sessions</a></li></ol></li><li class="chapter-item expanded "><a href="../../waku/standards/legacy/index.html"><strong aria-hidden="true">2.3.</strong> Standards - Legacy</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/standards/legacy/6/waku1.html"><strong aria-hidden="true">2.3.1.</strong> 6/Waku1</a></li><li class="chapter-item expanded "><a href="../../waku/standards/legacy/7/data.html"><strong aria-hidden="true">2.3.2.</strong> 7/Data</a></li><li class="chapter-item expanded "><a href="../../waku/standards/legacy/8/mail.html"><strong aria-hidden="true">2.3.3.</strong> 8/Mail</a></li><li class="chapter-item expanded "><a href="../../waku/standards/legacy/9/rpc.html"><strong aria-hidden="true">2.3.4.</strong> 9/RPC</a></li></ol></li><li class="chapter-item expanded "><a href="../../waku/informational/index.html"><strong aria-hidden="true">2.4.</strong> Informational</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/informational/22/toy-chat.html"><strong aria-hidden="true">2.4.1.</strong> 22/Toy Chat</a></li><li class="chapter-item expanded "><a href="../../waku/informational/23/topics.html"><strong aria-hidden="true">2.4.2.</strong> 23/Topics</a></li><li class="chapter-item expanded "><a href="../../waku/informational/27/peers.html"><strong aria-hidden="true">2.4.3.</strong> 27/Peers</a></li><li class="chapter-item expanded "><a href="../../waku/informational/29/config.html"><strong aria-hidden="true">2.4.4.</strong> 29/Config</a></li><li class="chapter-item expanded "><a href="../../waku/informational/30/adaptive-nodes.html"><strong aria-hidden="true">2.4.5.</strong> 30/Adaptive Nodes</a></li></ol></li><li class="chapter-item expanded "><a href="../../waku/deprecated/index.html"><strong aria-hidden="true">2.5.</strong> Deprecated</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../waku/deprecated/5/waku0.html"><strong aria-hidden="true">2.5.1.</strong> 5/Waku0</a></li><li class="chapter-item expanded "><a href="../../waku/deprecated/16/rpc.html"><strong aria-hidden="true">2.5.2.</strong> 16/RPC</a></li><li class="chapter-item expanded "><a href="../../waku/deprecated/18/swap.html"><strong aria-hidden="true">2.5.3.</strong> 18/Swap</a></li><li class="chapter-item expanded "><a href="../../waku/deprecated/fault-tolerant-store.html"><strong aria-hidden="true">2.5.4.</strong> Fault Tolerant Store</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../../nomos/index.html"><strong aria-hidden="true">3.</strong> Nomos</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../nomos/raw/index.html"><strong aria-hidden="true">3.1.</strong> Raw</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../nomos/raw/nomosda-encoding.html"><strong aria-hidden="true">3.1.1.</strong> NomosDA Encoding</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/nomosda-network.html"><strong aria-hidden="true">3.1.2.</strong> NomosDA Network</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/p2p-hardware-requirements.html"><strong aria-hidden="true">3.1.3.</strong> P2P Hardware Requirements</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/p2p-nat-solution.html"><strong aria-hidden="true">3.1.4.</strong> P2P NAT Solution</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/p2p-network-bootstrapping.html"><strong aria-hidden="true">3.1.5.</strong> P2P Network Bootstrapping</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/p2p-network.html"><strong aria-hidden="true">3.1.6.</strong> P2P Network</a></li><li class="chapter-item expanded "><a href="../../nomos/raw/sdp.html"><strong aria-hidden="true">3.1.7.</strong> SDP</a></li></ol></li><li class="chapter-item expanded "><a href="../../nomos/deprecated/index.html"><strong aria-hidden="true">3.2.</strong> Deprecated</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../nomos/deprecated/claro.html"><strong aria-hidden="true">3.2.1.</strong> Claro</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../../codex/index.html"><strong aria-hidden="true">4.</strong> Codex</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../codex/raw/index.html"><strong aria-hidden="true">4.1.</strong> Raw</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../codex/raw/codex-block-exchange.html"><strong aria-hidden="true">4.1.1.</strong> Block Exchange</a></li><li class="chapter-item expanded "><a href="../../codex/raw/codex-marketplace.html"><strong aria-hidden="true">4.1.2.</strong> Marketplace</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../../status/index.html"><strong aria-hidden="true">5.</strong> Status</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../status/24/curation.html"><strong aria-hidden="true">5.1.</strong> 24/Curation</a></li><li class="chapter-item expanded "><a href="../../status/28/featuring.html"><strong aria-hidden="true">5.2.</strong> 28/Featuring</a></li><li class="chapter-item expanded "><a href="../../status/55/1to1-chat.html"><strong aria-hidden="true">5.3.</strong> 55/1-to-1 Chat</a></li><li class="chapter-item expanded "><a href="../../status/56/communities.html"><strong aria-hidden="true">5.4.</strong> 56/Communities</a></li><li class="chapter-item expanded "><a href="../../status/61/community-history-service.html"><strong aria-hidden="true">5.5.</strong> 61/Community History Service</a></li><li class="chapter-item expanded "><a href="../../status/62/payloads.html"><strong aria-hidden="true">5.6.</strong> 62/Payloads</a></li><li class="chapter-item expanded "><a href="../../status/63/keycard-usage.html"><strong aria-hidden="true">5.7.</strong> 63/Keycard Usage</a></li><li class="chapter-item expanded "><a href="../../status/65/account-address.html"><strong aria-hidden="true">5.8.</strong> 65/Account Address</a></li><li class="chapter-item expanded "><a href="../../status/71/push-notification-server.html"><strong aria-hidden="true">5.9.</strong> 71/Push Notification Server</a></li><li class="chapter-item expanded "><a href="../../status/raw/index.html"><strong aria-hidden="true">5.10.</strong> Raw</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../status/raw/simple-scaling.html"><strong aria-hidden="true">5.10.1.</strong> Simple Scaling</a></li><li class="chapter-item expanded "><a href="../../status/raw/status-app-protocols.html"><strong aria-hidden="true">5.10.2.</strong> Status App Protocols</a></li><li class="chapter-item expanded "><a href="../../status/raw/status-mvds.html"><strong aria-hidden="true">5.10.3.</strong> Status MVDS</a></li><li class="chapter-item expanded "><a href="../../status/raw/url-data.html"><strong aria-hidden="true">5.10.4.</strong> URL Data</a></li><li class="chapter-item expanded "><a href="../../status/raw/url-scheme.html"><strong aria-hidden="true">5.10.5.</strong> URL Scheme</a></li></ol></li><li class="chapter-item expanded "><a href="../../status/deprecated/index.html"><strong aria-hidden="true">5.11.</strong> Deprecated</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../status/deprecated/3rd-party.html"><strong aria-hidden="true">5.11.1.</strong> 3rd Party</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/account.html"><strong aria-hidden="true">5.11.2.</strong> Account</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/client.html"><strong aria-hidden="true">5.11.3.</strong> Client</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/dapp-browser-API-usage.html"><strong aria-hidden="true">5.11.4.</strong> Dapp Browser API Usage</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/eips.html"><strong aria-hidden="true">5.11.5.</strong> EIPs</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/ethereum-usage.html"><strong aria-hidden="true">5.11.6.</strong> Ethereum Usage</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/group-chat.html"><strong aria-hidden="true">5.11.7.</strong> Group Chat</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/IPFS-gateway-for-sticker-Pack.html"><strong aria-hidden="true">5.11.8.</strong> IPFS Gateway for Sticker Pack</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/keycard-usage-for-wallet-and-chat-keys.html"><strong aria-hidden="true">5.11.9.</strong> Keycard Usage for Wallet and Chat Keys</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/notifications.html"><strong aria-hidden="true">5.11.10.</strong> Notifications</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/payloads.html"><strong aria-hidden="true">5.11.11.</strong> Payloads</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/push-notification-server.html"><strong aria-hidden="true">5.11.12.</strong> Push Notification Server</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/secure-transport.html"><strong aria-hidden="true">5.11.13.</strong> Secure Transport</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/waku-mailserver.html"><strong aria-hidden="true">5.11.14.</strong> Waku Mailserver</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/waku-usage.html"><strong aria-hidden="true">5.11.15.</strong> Waku Usage</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/whisper-mailserver.html"><strong aria-hidden="true">5.11.16.</strong> Whisper Mailserver</a></li><li class="chapter-item expanded "><a href="../../status/deprecated/whisper-usage.html"><strong aria-hidden="true">5.11.17.</strong> Whisper Usage</a></li></ol></li></ol></li></ol>
|
||
</div>
|
||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||
<div class="sidebar-resize-indicator"></div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Track and set sidebar scroll position -->
|
||
<script>
|
||
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
|
||
sidebarScrollbox.addEventListener('click', function(e) {
|
||
if (e.target.tagName === 'A') {
|
||
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
|
||
}
|
||
}, { passive: true });
|
||
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
|
||
sessionStorage.removeItem('sidebar-scroll');
|
||
if (sidebarScrollTop) {
|
||
// preserve sidebar scroll position when navigating via links within sidebar
|
||
sidebarScrollbox.scrollTop = sidebarScrollTop;
|
||
} else {
|
||
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
|
||
var activeSection = document.querySelector('#sidebar .active');
|
||
if (activeSection) {
|
||
activeSection.scrollIntoView({ block: 'center' });
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<div id="page-wrapper" class="page-wrapper">
|
||
|
||
<div class="page">
|
||
<div id="menu-bar-hover-placeholder"></div>
|
||
<div id="menu-bar" class="menu-bar sticky">
|
||
<div class="left-buttons">
|
||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||
<i class="fa fa-bars"></i>
|
||
</label>
|
||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||
<i class="fa fa-paint-brush"></i>
|
||
</button>
|
||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||
</ul>
|
||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||
<i class="fa fa-search"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<h1 class="menu-title">Vac RFC</h1>
|
||
|
||
<div class="right-buttons">
|
||
<a href="../../print.html" title="Print this book" aria-label="Print this book">
|
||
<i id="print-button" class="fa fa-print"></i>
|
||
</a>
|
||
<a href="https://github.com/vacp2p/rfc-index" title="Git repository" aria-label="Git repository">
|
||
<i id="git-repository-button" class="fa fa-github"></i>
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="search-wrapper" class="hidden">
|
||
<form id="searchbar-outer" class="searchbar-outer">
|
||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||
</form>
|
||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||
<div id="searchresults-header" class="searchresults-header"></div>
|
||
<ul id="searchresults">
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
<script>
|
||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
});
|
||
</script>
|
||
|
||
<div id="content" class="content">
|
||
<main>
|
||
<h1 id="sds"><a class="header" href="#sds">SDS</a></h1>
|
||
<div class="table-wrapper"><table><thead><tr><th>Field</th><th>Value</th></tr></thead><tbody>
|
||
<tr><td>Name</td><td>Scalable Data Sync protocol for distributed logs</td></tr>
|
||
<tr><td>Status</td><td>raw</td></tr>
|
||
<tr><td>Editor</td><td>Hanno Cornelius <a href="mailto:hanno@status.im">hanno@status.im</a></td></tr>
|
||
<tr><td>Contributors</td><td>Akhil Peddireddy <a href="mailto:akhil@status.im">akhil@status.im</a></td></tr>
|
||
</tbody></table>
|
||
</div><!-- timeline:start -->
|
||
<h2 id="timeline"><a class="header" href="#timeline">Timeline</a></h2>
|
||
<ul>
|
||
<li><strong>2025-12-22</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/0f1855edcf68ef982c4ce478b67d660809aa9830/docs/vac/raw/sds.md"><code>0f1855e</code></a> — Chore/fix headers (#239)</li>
|
||
<li><strong>2025-12-22</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/b1a578393edf8487ccc97a5f25b25af9bf41efb3/docs/vac/raw/sds.md"><code>b1a5783</code></a> — Chore/mdbook updates (#237)</li>
|
||
<li><strong>2025-12-18</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/d03e699084774ebecef9c6d4662498907c5e2080/docs/vac/raw/sds.md"><code>d03e699</code></a> — ci: add mdBook configuration (#233)</li>
|
||
<li><strong>2025-10-24</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/69802377a8c1df53659ac05c7aa93543be4b3e4a/vac/raw/sds.md"><code>6980237</code></a> — Fix Linting Errors (#204)</li>
|
||
<li><strong>2025-10-13</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/171e934d6186a5952f0458bbe42c966859fe2a31/vac/raw/sds.md"><code>171e934</code></a> — docs: add SDS-Repair extension (#176)</li>
|
||
<li><strong>2025-10-02</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/6672c5bedf5a08d3045d3b7d23d2b7a2e5d3aa2f/vac/raw/sds.md"><code>6672c5b</code></a> — docs: update lamport timestamps to uint64, pegged to current time (#196)</li>
|
||
<li><strong>2025-09-15</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/b1da70386edb15303fb8aa587b8a5da784a2d644/vac/raw/sds.md"><code>b1da703</code></a> — fix: use milliseconds for Lamport timestamp initialization (#179)</li>
|
||
<li><strong>2025-08-22</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/3505da6bd66d2830e5711deb0b5c2b4de9212a4d/vac/raw/sds.md"><code>3505da6</code></a> — sds lint fix (#177)</li>
|
||
<li><strong>2025-08-19</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/536d31b5b7641bd451cf35b94e8de1aa8a6c9f64/vac/raw/sds.md"><code>536d31b</code></a> — docs: re-add sender ID to messages (#170)</li>
|
||
<li><strong>2025-03-07</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/vac/raw/sds.md"><code>8ee2a6d</code></a> — docs: add optional retrieval hint to causal history in sds (#130)</li>
|
||
<li><strong>2025-02-20</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/235c1d5aa676d8278036003d4493c7c32afc033b/vac/raw/sds.md"><code>235c1d5</code></a> — docs: clarify receiving sync messages (#131)</li>
|
||
<li><strong>2025-02-18</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/718245979fd1c67d04d1eab7ea31a4aad6dbc1d2/vac/raw/sds.md"><code>7182459</code></a> — docs: update sds sync message requirements (#129)</li>
|
||
<li><strong>2025-01-28</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/7a01711ffc5b50186e111bc2f4fa2e4b02b26bf3/vac/raw/sds.md"><code>7a01711</code></a> — fix(sds): remove optional from causal history field in Message protobuf (#123)</li>
|
||
<li><strong>2024-12-17</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/08b363d67e34277e7881a20e36f788978cb0f93c/vac/raw/sds.md"><code>08b363d</code></a> — Update SDS.md: Remove Errors (#115)</li>
|
||
<li><strong>2024-11-28</strong> — <a href="https://github.com/vacp2p/rfc-index/blob/bee78c40b9a94ed4c40fe6ba2505b6b0654206b4/vac/raw/sds.md"><code>bee78c4</code></a> — docs: add SDS protocol for scalable e2e reliability (#108)</li>
|
||
</ul>
|
||
<!-- timeline:end -->
|
||
<h2 id="abstract"><a class="header" href="#abstract">Abstract</a></h2>
|
||
<p>This specification introduces the Scalable Data Sync (SDS) protocol
|
||
to achieve end-to-end reliability
|
||
when consolidating distributed logs in a decentralized manner.
|
||
The protocol is designed for a peer-to-peer (p2p) topology
|
||
where an append-only log is maintained by each member of a group of nodes
|
||
who may individually append new entries to their local log at any time and
|
||
is interested in merging new entries from other nodes in real-time or close to real-time
|
||
while maintaining a consistent order.
|
||
The outcome of the log consolidation procedure is
|
||
that all nodes in the group eventually reflect in their own logs
|
||
the same entries in the same order.
|
||
The protocol aims to scale to very large groups.</p>
|
||
<h2 id="motivation"><a class="header" href="#motivation">Motivation</a></h2>
|
||
<p>A common application that fits this model is a p2p group chat (or group communication),
|
||
where the participants act as log nodes
|
||
and the group conversation is modelled as the consolidated logs
|
||
maintained on each node.
|
||
The problem of end-to-end reliability can then be stated as
|
||
ensuring that all participants eventually see the same sequence of messages
|
||
in the same causal order,
|
||
despite the challenges of network latency, message loss,
|
||
and scalability present in any communications transport layer.
|
||
The rest of this document will assume the terminology of a group communication:
|
||
log nodes being the <em>participants</em> in the group chat
|
||
and the logged entries being the <em>messages</em> exchanged between participants.</p>
|
||
<h2 id="design-assumptions"><a class="header" href="#design-assumptions">Design Assumptions</a></h2>
|
||
<p>We make the following simplifying assumptions for a proposed reliability protocol:</p>
|
||
<ul>
|
||
<li><strong>Broadcast routing:</strong>
|
||
Messages are broadcast disseminated by the underlying transport.
|
||
The selected transport takes care of routing messages
|
||
to all participants of the communication.</li>
|
||
<li><strong>Store nodes:</strong>
|
||
There are high-availability caches (a.k.a. Store nodes)
|
||
from which missed messages can be retrieved.
|
||
These caches maintain the full history of all messages that have been broadcast.
|
||
This is an optional element in the protocol design,
|
||
but improves scalability by reducing direct interactions between participants.</li>
|
||
<li><strong>Message ID:</strong>
|
||
Each message has a globally unique, immutable ID (or hash).
|
||
Messages can be requested from the high-availability caches or
|
||
other participants using the corresponding message ID.</li>
|
||
<li><strong>Participant ID:</strong>
|
||
Each participant has a globally unique, immutable ID
|
||
visible to other participants in the communication.</li>
|
||
<li><strong>Sender ID:</strong>
|
||
The <strong>Participant ID</strong> of the original sender of a message,
|
||
often coupled with a <strong>Message ID</strong>.</li>
|
||
</ul>
|
||
<h2 id="wire-protocol"><a class="header" href="#wire-protocol">Wire protocol</a></h2>
|
||
<p>The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
|
||
“SHOULD NOT”, “RECOMMENDED”, “MAY”, and
|
||
“OPTIONAL” in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt">2119</a>.</p>
|
||
<h3 id="message"><a class="header" href="#message">Message</a></h3>
|
||
<p>Messages MUST adhere to the following meta structure:</p>
|
||
<pre><code class="language-protobuf">syntax = "proto3";
|
||
|
||
message HistoryEntry {
|
||
string message_id = 1; // Unique identifier of the SDS message, as defined in `Message`
|
||
optional bytes retrieval_hint = 2; // Optional information to help remote parties retrieve this SDS message; For example, A Waku deterministic message hash or routing payload hash
|
||
|
||
optional string sender_id = 3; // Participant ID of original message sender. Only populated if using optional SDS Repair extension
|
||
}
|
||
|
||
message Message {
|
||
string sender_id = 1; // Participant ID of the message sender
|
||
string message_id = 2; // Unique identifier of the message
|
||
string channel_id = 3; // Identifier of the channel to which the message belongs
|
||
optional uint64 lamport_timestamp = 10; // Logical timestamp for causal ordering in channel
|
||
repeated HistoryEntry causal_history = 11; // List of preceding message IDs that this message causally depends on. Generally 2 or 3 message IDs are included.
|
||
optional bytes bloom_filter = 12; // Bloom filter representing received message IDs in channel
|
||
|
||
repeated HistoryEntry repair_request = 13; // Capped list of history entries missing from sender's causal history. Only populated if using the optional SDS Repair extension.
|
||
|
||
optional bytes content = 20; // Actual content of the message
|
||
}
|
||
</code></pre>
|
||
<p>The sending participant MUST include its own globally unique identifier in the <code>sender_id</code> field.
|
||
In addition, it MUST include a globally unique identifier for the message in the <code>message_id</code> field,
|
||
likely based on a message hash.
|
||
The <code>channel_id</code> field MUST be set to the identifier of the channel of group communication
|
||
that is being synchronized.
|
||
For simple group communications without individual channels,
|
||
the <code>channel_id</code> SHOULD be set to <code>0</code>.
|
||
The <code>lamport_timestamp</code>, <code>causal_history</code> and
|
||
<code>bloom_filter</code> fields MUST be set according to the <a href="#protocol-steps">protocol steps</a>
|
||
set out below.
|
||
These fields MAY be left unset in the case of <a href="#ephemeral-messages">ephemeral messages</a>.
|
||
The message <code>content</code> MAY be left empty for <a href="#periodic-sync-message">periodic sync messages</a>,
|
||
otherwise it MUST contain the application-level content</p>
|
||
<blockquote>
|
||
<p><strong><em>Note:</em></strong> Close readers may notice that,
|
||
outside of filtering messages originating from the sender itself,
|
||
the <code>sender_id</code> field is not used for much.
|
||
Its importance is expected to increase once a p2p retrieval mechanism is added to SDS,
|
||
as is planned for the protocol.</p>
|
||
</blockquote>
|
||
<h3 id="participant-state"><a class="header" href="#participant-state">Participant state</a></h3>
|
||
<p>Each participant MUST maintain:</p>
|
||
<ul>
|
||
<li>A Lamport timestamp for each channel of communication,
|
||
initialized to current epoch time in millisecond resolution.
|
||
The Lamport timestamp is increased as described in the <a href="#protocol-steps">protocol steps</a>
|
||
to maintain a logical ordering of events while staying close to the current epoch time.
|
||
This allows the messages from new joiners to be correctly ordered with other recent messages,
|
||
without these new participants first having to synchronize past messages to discover the current Lamport timestamp.</li>
|
||
<li>A bloom filter for received message IDs per channel.
|
||
The bloom filter SHOULD be rolled over and
|
||
recomputed once it reaches a predefined capacity of message IDs.
|
||
Furthermore,
|
||
it SHOULD be designed to minimize false positives through an optimal selection of
|
||
size and hash functions.</li>
|
||
<li>A buffer for unacknowledged outgoing messages</li>
|
||
<li>A buffer for incoming messages with unmet causal dependencies</li>
|
||
<li>A local log (or history) for each channel,
|
||
containing all message IDs in the communication channel,
|
||
ordered by Lamport timestamp.</li>
|
||
</ul>
|
||
<p>Messages in the unacknowledged outgoing buffer can be in one of three states:</p>
|
||
<ol>
|
||
<li><strong>Unacknowledged</strong> - there has been no acknowledgement of message receipt
|
||
by any participant in the channel</li>
|
||
<li><strong>Possibly acknowledged</strong> - there has been ambiguous indication that the message
|
||
has been <em>possibly</em> received by at least one participant in the channel</li>
|
||
<li><strong>Acknowledged</strong> - there has been sufficient indication that the message
|
||
has been received by at least some of the participants in the channel.
|
||
This state will also remove the message from the outgoing buffer.</li>
|
||
</ol>
|
||
<h3 id="protocol-steps"><a class="header" href="#protocol-steps">Protocol Steps</a></h3>
|
||
<p>For each channel of communication,
|
||
participants MUST follow these protocol steps to populate and interpret
|
||
the <code>lamport_timestamp</code>, <code>causal_history</code> and <code>bloom_filter</code> fields.</p>
|
||
<h4 id="send-message"><a class="header" href="#send-message">Send Message</a></h4>
|
||
<p>Before broadcasting a message:</p>
|
||
<ul>
|
||
<li>the participant MUST set its local Lamport timestamp
|
||
to the maximum between the current value + <code>1</code>
|
||
and the current epoch time in milliseconds.
|
||
In other words the local Lamport timestamp is set to <code>max(timeNowInMs, current_lamport_timestamp + 1)</code>.</li>
|
||
<li>the participant MUST include the increased Lamport timestamp in the message's <code>lamport_timestamp</code> field.</li>
|
||
<li>the participant MUST determine the preceding few message IDs in the local history
|
||
and include these in an ordered list in the <code>causal_history</code> field.
|
||
The number of message IDs to include in the <code>causal_history</code> depends on the application.
|
||
We recommend a causal history of two message IDs.</li>
|
||
<li>the participant MAY include a <code>retrieval_hint</code> in the <code>HistoryEntry</code>
|
||
for each message ID in the <code>causal_history</code> field.
|
||
This is an application-specific field to facilitate retrieval of messages,
|
||
e.g. from high-availability caches.</li>
|
||
<li>the participant MUST include the current <code>bloom_filter</code>
|
||
state in the broadcast message.</li>
|
||
</ul>
|
||
<p>After broadcasting a message,
|
||
the message MUST be added to the participant’s buffer
|
||
of unacknowledged outgoing messages.</p>
|
||
<h4 id="receive-message"><a class="header" href="#receive-message">Receive Message</a></h4>
|
||
<p>Upon receiving a message,</p>
|
||
<ul>
|
||
<li>the participant SHOULD ignore the message if it has a <code>sender_id</code> matching its own.</li>
|
||
<li>the participant MAY deduplicate the message by comparing its <code>message_id</code> to previously received message IDs.</li>
|
||
<li>the participant MUST <a href="#review-ack-status">review the ACK status</a> of messages
|
||
in its unacknowledged outgoing buffer
|
||
using the received message's causal history and bloom filter.</li>
|
||
<li>if the message has a populated <code>content</code> field,
|
||
the participant MUST include the received message ID in its local bloom filter.</li>
|
||
<li>the participant MUST verify that all causal dependencies are met
|
||
for the received message.
|
||
Dependencies are met if the message IDs in the <code>causal_history</code> of the received message
|
||
appear in the local history of the receiving participant.</li>
|
||
</ul>
|
||
<p>If all dependencies are met and the message has a populated <code>content</code> field,
|
||
the participant MUST <a href="#deliver-message">deliver the message</a>.
|
||
If dependencies are unmet,
|
||
the participant MUST add the message to the incoming buffer of messages
|
||
with unmet causal dependencies.</p>
|
||
<h4 id="deliver-message"><a class="header" href="#deliver-message">Deliver Message</a></h4>
|
||
<p>Triggered by the <a href="#receive-message">Receive Message</a> procedure.</p>
|
||
<p>If the received message’s Lamport timestamp is greater than the participant's
|
||
local Lamport timestamp,
|
||
the participant MUST update its local Lamport timestamp to match the received message.
|
||
The participant MUST insert the message ID into its local log,
|
||
based on Lamport timestamp.
|
||
If one or more message IDs with the same Lamport timestamp already exists,
|
||
the participant MUST follow the <a href="#resolve-conflicts">Resolve Conflicts</a> procedure.</p>
|
||
<h4 id="resolve-conflicts"><a class="header" href="#resolve-conflicts">Resolve Conflicts</a></h4>
|
||
<p>Triggered by the <a href="#deliver-message">Deliver Message</a> procedure.</p>
|
||
<p>The participant MUST order messages with the same Lamport timestamp
|
||
in ascending order of message ID.
|
||
If the message ID is implemented as a hash of the message,
|
||
this means the message with the lowest hash would precede
|
||
other messages with the same Lamport timestamp in the local log.</p>
|
||
<h4 id="review-ack-status"><a class="header" href="#review-ack-status">Review ACK Status</a></h4>
|
||
<p>Triggered by the <a href="#receive-message">Receive Message</a> procedure.</p>
|
||
<p>For each message in the unacknowledged outgoing buffer,
|
||
based on the received <code>bloom_filter</code> and <code>causal_history</code>:</p>
|
||
<ul>
|
||
<li>the participant MUST mark all messages in the received <code>causal_history</code> as <strong>acknowledged</strong>.</li>
|
||
<li>the participant MUST mark all messages included in the <code>bloom_filter</code>
|
||
as <strong>possibly acknowledged</strong>.
|
||
If a message appears as <strong>possibly acknowledged</strong> in multiple received bloom filters,
|
||
the participant MAY mark it as acknowledged based on probabilistic grounds,
|
||
taking into account the bloom filter size and hash number.</li>
|
||
</ul>
|
||
<h4 id="periodic-incoming-buffer-sweep"><a class="header" href="#periodic-incoming-buffer-sweep">Periodic Incoming Buffer Sweep</a></h4>
|
||
<p>The participant MUST periodically check causal dependencies for each message
|
||
in the incoming buffer.
|
||
For each message in the incoming buffer:</p>
|
||
<ul>
|
||
<li>the participant MAY attempt to retrieve missing dependencies from the Store node
|
||
(high-availability cache) or other peers.
|
||
It MAY use the application-specific <code>retrieval_hint</code> in the <code>HistoryEntry</code> to facilitate retrieval.</li>
|
||
<li>if all dependencies of a message are met,
|
||
the participant MUST proceed to <a href="#deliver-message">deliver the message</a>.</li>
|
||
</ul>
|
||
<p>If a message's causal dependencies have failed to be met
|
||
after a predetermined amount of time,
|
||
the participant MAY mark them as <strong>irretrievably lost</strong>.</p>
|
||
<h4 id="periodic-outgoing-buffer-sweep"><a class="header" href="#periodic-outgoing-buffer-sweep">Periodic Outgoing Buffer Sweep</a></h4>
|
||
<p>The participant MUST rebroadcast <strong>unacknowledged</strong> outgoing messages
|
||
after a set period.
|
||
The participant SHOULD use distinct resend periods for <strong>unacknowledged</strong> and
|
||
<strong>possibly acknowledged</strong> messages,
|
||
prioritizing <strong>unacknowledged</strong> messages.</p>
|
||
<h4 id="periodic-sync-message"><a class="header" href="#periodic-sync-message">Periodic Sync Message</a></h4>
|
||
<p>For each channel of communication,
|
||
participants SHOULD periodically send sync messages to maintain state.
|
||
These sync messages:</p>
|
||
<ul>
|
||
<li>MUST be sent with empty content</li>
|
||
<li>MUST include a Lamport timestamp increased to <code>max(timeNowInMs, current_lamport_timestamp + 1)</code>,
|
||
where <code>timeNowInMs</code> is the current epoch time in milliseconds.</li>
|
||
<li>MUST include causal history and bloom filter according to regular message rules</li>
|
||
<li>MUST NOT be added to the unacknowledged outgoing buffer</li>
|
||
<li>MUST NOT be included in causal histories of subsequent messages</li>
|
||
<li>MUST NOT be included in bloom filters</li>
|
||
<li>MUST NOT be added to the local log</li>
|
||
</ul>
|
||
<p>Since sync messages are not persisted,
|
||
they MAY have non-unique message IDs without impacting the protocol.
|
||
To avoid network activity bursts in large groups,
|
||
a participant MAY choose to only send periodic sync messages
|
||
if no other messages have been broadcast in the channel after a random backoff period.</p>
|
||
<p>Participants MUST process the causal history and bloom filter of these sync messages
|
||
following the same steps as regular messages,
|
||
but MUST NOT persist the sync messages themselves.</p>
|
||
<h4 id="ephemeral-messages"><a class="header" href="#ephemeral-messages">Ephemeral Messages</a></h4>
|
||
<p>Participants MAY choose to send short-lived messages for which no synchronization
|
||
or reliability is required.
|
||
These messages are termed <em>ephemeral</em>.</p>
|
||
<p>Ephemeral messages SHOULD be sent with <code>lamport_timestamp</code>, <code>causal_history</code>, and
|
||
<code>bloom_filter</code> unset.
|
||
Ephemeral messages SHOULD NOT be added to the unacknowledged outgoing buffer
|
||
after broadcast.
|
||
Upon reception,
|
||
ephemeral messages SHOULD be delivered immediately without buffering for causal dependencies
|
||
or including in the local log.</p>
|
||
<h3 id="sds-repair-sds-r"><a class="header" href="#sds-repair-sds-r">SDS Repair (SDS-R)</a></h3>
|
||
<p>SDS Repair (SDS-R) is an optional extension module for SDS,
|
||
allowing participants in a communication to collectively repair any gaps in causal history (missing messages)
|
||
preferably over a limited time window.
|
||
Since SDS-R acts as coordinated rebroadcasting of missing messages,
|
||
which involves all participants of the communication,
|
||
it is most appropriate in a limited use case for repairing relatively recent missed dependencies.
|
||
It is not meant to replace mechanisms for long-term consistency,
|
||
such as peer-to-peer syncing or the use of a high-availability centralised cache (Store node).</p>
|
||
<h4 id="sds-r-message-fields"><a class="header" href="#sds-r-message-fields">SDS-R message fields</a></h4>
|
||
<p>SDS-R adds the following fields to SDS messages:</p>
|
||
<ul>
|
||
<li><code>sender_id</code> in <code>HistoryEntry</code>:
|
||
the original message sender's participant ID.
|
||
This is used to determine the group of participants who will respond to a repair request.</li>
|
||
<li><code>repair_request</code> in <code>Message</code>:
|
||
a capped list of history entries missing for the message sender
|
||
and for which it's requesting a repair.</li>
|
||
</ul>
|
||
<h4 id="sds-r-participant-state"><a class="header" href="#sds-r-participant-state">SDS-R participant state</a></h4>
|
||
<p>SDS-R adds the following to each participant state:</p>
|
||
<ul>
|
||
<li>
|
||
<p>Outgoing <strong>repair request buffer</strong>:
|
||
a list of locally missing <code>HistoryEntry</code>s
|
||
each mapped to a future request timestamp, <code>T_req</code>,
|
||
after which this participant will request a repair if at that point the missing dependency has not been repaired yet.
|
||
<code>T_req</code> is computed as a pseudorandom backoff from the timestamp when the dependency was detected missing.
|
||
<a href="#determine-t_req">Determining <code>T_req</code></a> is described below.
|
||
We RECOMMEND that the outgoing repair request buffer be chronologically ordered in ascending order of <code>T_req</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p>Incoming <strong>repair request buffer</strong>:
|
||
a list of locally available <code>HistoryEntry</code>s
|
||
that were requested for repair by a remote participant
|
||
AND for which this participant might be an eligible responder,
|
||
each mapped to a future response timestamp, <code>T_resp</code>,
|
||
after which this participant will rebroadcast the corresponding requested <code>Message</code> if at that point no other participant had rebroadcast the <code>Message</code>.
|
||
<code>T_resp</code> is computed as a pseudorandom backoff from the timestamp when the repair was first requested.
|
||
<a href="#determine-t_resp">Determining <code>T_resp</code></a> is described below.
|
||
We describe below how a participant can <a href="#determine-response-group">determine if they're an eligible responder</a> for a specific repair request.</p>
|
||
</li>
|
||
<li>
|
||
<p>Augmented local history log:
|
||
for each message ID kept in the local log for which the participant could be a repair responder,
|
||
the full SDS <code>Message</code> must be cached rather than just the message ID,
|
||
in case this participant is called upon to rebroadcast the message.
|
||
We describe below how a participant can <a href="#determine-response-group">determine if they're an eligible responder</a> for a specific message.</p>
|
||
</li>
|
||
</ul>
|
||
<p><strong><em>Note:</em></strong> The required state can likely be significantly reduced in future by simply requiring that a responding participant should <em>reconstruct</em> the original <code>Message</code> when rebroadcasting, rather than the simpler, but heavier,
|
||
requirement of caching the entire received <code>Message</code> content in local history.</p>
|
||
<h4 id="sds-r-global-state"><a class="header" href="#sds-r-global-state">SDS-R global state</a></h4>
|
||
<p>For a specific channel (that is, within a specific SDS-controlled communication)
|
||
the following SDS-R configuration state SHOULD be common for all participants in the conversation:</p>
|
||
<ul>
|
||
<li><code>T_min</code>: the <em>minimum</em> time period to wait before a missing causal entry can be repaired.
|
||
We RECOMMEND a value of at least 30 seconds.</li>
|
||
<li><code>T_max</code>: the <em>maximum</em> time period over which missing causal entries can be repaired.
|
||
We RECOMMEND a value of between 120 and 600 seconds.</li>
|
||
</ul>
|
||
<p>Furthermore, to avoid a broadcast storm with multiple participants responding to a repair request,
|
||
participants in a single channel MAY be divided into discrete response groups.
|
||
Participants will only respond to a repair request if they are in the response group for that request.
|
||
The global <code>num_response_groups</code> variable configures the number of response groups for this communication.
|
||
Its use is described below.
|
||
A reasonable default value for <code>num_response_groups</code> is one response group for every <code>128</code> participants.
|
||
In other words, if the (roughly) expected number of participants is expressed as <code>num_participants</code>, then
|
||
<code>num_response_groups = num_participants div 128 + 1</code>.
|
||
In other words, if there are fewer than 128 participants in a communication,
|
||
they will all belong to the same response group.</p>
|
||
<p>We RECOMMEND that the global state variables <code>T_min</code>, <code>T_max</code> and <code>num_response_groups</code>
|
||
be set <em>statically</em> for a specific SDS-R application,
|
||
based on expected number of group participants and volume of traffic.</p>
|
||
<p><strong><em>Note:</em></strong> Future versions of this protocol will recommend dynamic global SDS-R variables,
|
||
based on the current number of participants.</p>
|
||
<h4 id="sds-r-send-message"><a class="header" href="#sds-r-send-message">SDS-R send message</a></h4>
|
||
<p>SDS-R adds the following steps when sending a message:</p>
|
||
<p>Before broadcasting a message,</p>
|
||
<ul>
|
||
<li>the participant SHOULD populate the <code>repair_request</code> field in the message
|
||
with <em>eligible</em> entries from the outgoing repair request buffer.
|
||
An entry is eligible to be included in a <code>repair_request</code>
|
||
if its corresponding request timestamp, <code>T_req</code>, has expired (in other words,
|
||
<code>T_req <= current_time</code>).
|
||
The maximum number of repair request entries to include is up to the application.
|
||
We RECOMMEND that this quota be filled by the eligible entries from the outgoing repair request buffer with the lowest <code>T_req</code>.
|
||
We RECOMMEND a maximum of 3 entries.
|
||
If there are no eligible entries in the buffer,
|
||
this optional field MUST be left unset.</li>
|
||
</ul>
|
||
<h4 id="sds-r-receive-message"><a class="header" href="#sds-r-receive-message">SDS-R receive message</a></h4>
|
||
<p>On receiving a message,</p>
|
||
<ul>
|
||
<li>the participant MUST remove entries matching the received message ID from its <em>outgoing</em> repair request buffer.
|
||
This ensures that the participant does not request repairs for dependencies that have now been met.</li>
|
||
<li>the participant MUST remove entries matching the received message ID from its <em>incoming</em> repair request buffer.
|
||
This ensures that the participant does not respond to repair requests that another participant has already responded to.</li>
|
||
<li>the participant SHOULD add any unmet causal dependencies to its outgoing repair request buffer against a unique <code>T_req</code> timestamp for that entry.
|
||
It MUST compute the <code>T_req</code> for each such HistoryEntry according to the steps outlined in <a href="#determine-t_req"><em>Determine T_req</em></a>.</li>
|
||
<li>for each item in the <code>repair_request</code> field:
|
||
<ul>
|
||
<li>the participant MUST remove entries matching the repair message ID from its own outgoing repair request buffer.
|
||
This limits the number of participants that will request a common missing dependency.</li>
|
||
<li>if the participant has the requested <code>Message</code> in its local history <em>and</em> is an eligible responder for the repair request,
|
||
it SHOULD add the request to its incoming repair request buffer against a unique <code>T_resp</code> timestamp for that entry.
|
||
It MUST compute the <code>T_resp</code> for each such repair request according to the steps outlined in <a href="#determine-t_resp"><em>Determine T_resp</em></a>.
|
||
It MUST determine if it's an eligible responder for a repair request according to the steps outlined in <a href="#determine-response-group"><em>Determine response group</em></a>.</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h4 id="determine-t_req"><a class="header" href="#determine-t_req">Determine T_req</a></h4>
|
||
<p>A participant determines the repair request timestamp, <code>T_req</code>,
|
||
for a missing <code>HistoryEntry</code> as follows:</p>
|
||
<pre><code class="language-text">T_req = current_time + hash(participant_id, message_id) % (T_max - T_min) + T_min
|
||
</code></pre>
|
||
<p>where <code>current_time</code> is the current timestamp,
|
||
<code>participant_id</code> is the participant's <em>own</em> participant ID
|
||
(not the <code>sender_id</code> in the missing <code>HistoryEntry</code>),
|
||
<code>message_id</code> is the missing <code>HistoryEntry</code>'s message ID,
|
||
and <code>T_min</code> and <code>T_max</code> are as set out in <a href="#sds-r-global-state">SDS-R global state</a>.</p>
|
||
<p>This allows <code>T_req</code> to be pseudorandomly and linearly distributed as a backoff of between <code>T_min</code> and <code>T_max</code> from current time.</p>
|
||
<blockquote>
|
||
<p><strong><em>Note:</em></strong> placing <code>T_req</code> values on an exponential backoff curve will likely be more appropriate and is left for a future improvement.</p>
|
||
</blockquote>
|
||
<h4 id="determine-t_resp"><a class="header" href="#determine-t_resp">Determine T_resp</a></h4>
|
||
<p>A participant determines the repair response timestamp, <code>T_resp</code>,
|
||
for a <code>HistoryEntry</code> that it could repair as follows:</p>
|
||
<pre><code class="language-text">distance = hash(participant_id) XOR hash(sender_id)
|
||
T_resp = current_time + distance*hash(message_id) % T_max
|
||
</code></pre>
|
||
<p>where <code>current_time</code> is the current timestamp,
|
||
<code>participant_id</code> is the participant's <em>own</em> (local) participant ID,
|
||
<code>sender_id</code> is the requested <code>HistoryEntry</code> sender ID,
|
||
<code>message_id</code> is the requested <code>HistoryEntry</code> message ID,
|
||
and <code>T_max</code> is as set out in <a href="#sds-r-global-state">SDS-R global state</a>.</p>
|
||
<p>We first calculate the logical <code>distance</code> between the local <code>participant_id</code> and
|
||
the original <code>sender_id</code>.
|
||
If this participant is the original sender, the <code>distance</code> will be <code>0</code>.
|
||
It should then be clear that the original participant will have a response backoff time of <code>0</code>,
|
||
making it the most likely responder.
|
||
The <code>T_resp</code> values for other eligible participants will be pseudorandomly and
|
||
linearly distributed as a backoff of up to <code>T_max</code> from current time.</p>
|
||
<blockquote>
|
||
<p><strong><em>Note:</em></strong> placing <code>T_resp</code> values on an exponential backoff curve will likely be more appropriate and
|
||
is left for a future improvement.</p>
|
||
</blockquote>
|
||
<h4 id="determine-response-group"><a class="header" href="#determine-response-group">Determine response group</a></h4>
|
||
<p>Given a message with <code>sender_id</code> and <code>message_id</code>,
|
||
a participant with <code>participant_id</code> is in the response group for that message if</p>
|
||
<pre><code class="language-text">hash(participant_id, message_id) % num_response_groups == hash(sender_id, message_id) % num_response_groups
|
||
</code></pre>
|
||
<p>where <code>num_response_groups</code> is as set out in <a href="#sds-r-global-state">SDS-R global state</a>.
|
||
This ensures that a participant will always be in the response group for its own published messages.
|
||
It also allows participants to determine immediately on first reception of a message or
|
||
a history entry if they are in the associated response group.</p>
|
||
<h4 id="sds-r-incoming-repair-request-buffer-sweep"><a class="header" href="#sds-r-incoming-repair-request-buffer-sweep">SDS-R incoming repair request buffer sweep</a></h4>
|
||
<p>An SDS-R participant MUST periodically check if there are any incoming requests in the <strong>incoming</strong> repair request buffer* that is due for a response.
|
||
For each item in the buffer,
|
||
the participant SHOULD broadcast the corresponding <code>Message</code> from local history
|
||
if its corresponding response timestamp, <code>T_resp</code>, has expired
|
||
(in other words, <code>T_resp <= current_time</code>).</p>
|
||
<h4 id="sds-r-periodic-sync-message"><a class="header" href="#sds-r-periodic-sync-message">SDS-R Periodic Sync Message</a></h4>
|
||
<p>If the participant is due to send a periodic sync message,
|
||
it SHOULD send the message according to <a href="#sds-r-send-message">SDS-R send message</a>
|
||
if there are any eligible items in the outgoing repair request buffer,
|
||
regardless of whether other participants have also recently broadcast a Periodic Sync message.</p>
|
||
<h2 id="copyright"><a class="header" href="#copyright">Copyright</a></h2>
|
||
<p>Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a>.</p>
|
||
|
||
</main>
|
||
|
||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
<!-- Mobile navigation buttons -->
|
||
<a rel="prev" href="../../vac/raw/rln-v2.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../vac/template.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
|
||
<div style="clear: both"></div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||
<a rel="prev" href="../../vac/raw/rln-v2.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<i class="fa fa-angle-left"></i>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../../vac/template.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<i class="fa fa-angle-right"></i>
|
||
</a>
|
||
</nav>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
|
||
<script>
|
||
window.playground_copyable = true;
|
||
</script>
|
||
|
||
|
||
<script src="../../elasticlunr.min.js"></script>
|
||
<script src="../../mark.min.js"></script>
|
||
<script src="../../searcher.js"></script>
|
||
|
||
<script src="../../clipboard.min.js"></script>
|
||
<script src="../../highlight.js"></script>
|
||
<script src="../../book.js"></script>
|
||
|
||
<!-- Custom JS scripts -->
|
||
<script src="../../scripts/rfc-index.js"></script>
|
||
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|